00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "action_handler.h"
00023 #include "action.h"
00024 #include "../character/body.h"
00025 #include "../character/move.h"
00026 #include "../game/game_mode.h"
00027 #include "../game/game_loop.h"
00028 #include "../game/game.h"
00029 #include "../game/time.h"
00030 #include "../include/constant.h"
00031 #include "../network/network.h"
00032 #include "../map/camera.h"
00033 #include "../map/map.h"
00034 #include "../map/maps_list.h"
00035 #include "../map/wind.h"
00036 #include "../menu/network_menu.h"
00037 #include "../network/randomsync.h"
00038 #include "../network/network.h"
00039 #include "../team/macro.h"
00040 #include "../tool/debug.h"
00041 #include "../tool/i18n.h"
00042 #include "../tool/vector2.h"
00043 #include "../weapon/construct.h"
00044 #include "../weapon/launcher.h"
00045 #include "../weapon/supertux.h"
00046 #include "../weapon/weapon.h"
00047 #include "../weapon/weapons_list.h"
00048 #include "../weapon/explosion.h"
00049
00050
00051 #define DELTA_CROSSHAIR 0.035
00052
00053 ActionHandler * ActionHandler::singleton = NULL;
00054
00055 ActionHandler * ActionHandler::GetInstance()
00056 {
00057 if (singleton == NULL)
00058 singleton = new ActionHandler();
00059 return singleton;
00060 }
00061
00062
00063 void SyncCharacters()
00064 {
00065 assert(network.IsServer());
00066 ActionHandler* action_handler = ActionHandler::GetInstance();
00067
00068 Action a_begin_sync(Action::ACTION_SYNC_BEGIN);
00069 network.SendAction(&a_begin_sync);
00070 TeamsList::iterator
00071 it=teams_list.playing_list.begin(),
00072 end=teams_list.playing_list.end();
00073
00074 for (int team_no = 0; it != end; ++it, ++team_no)
00075 {
00076 Team& team = **it;
00077 Team::iterator
00078 tit = team.begin(),
00079 tend = team.end();
00080
00081 for (int char_no = 0; tit != tend; ++tit, ++char_no)
00082 {
00083
00084 Action* a = new Action(Action::ACTION_SET_CHARACTER_ENERGY);
00085 a->Push(team_no);
00086 a->Push(char_no);
00087 a->Push((int)(*tit).GetEnergy());
00088 action_handler->NewAction(a);
00089
00090 a = BuildActionSendCharacterPhysics(team_no, char_no);
00091 action_handler->NewAction(a);
00092 }
00093 }
00094 Action a_sync_end(Action::ACTION_SYNC_END);
00095 network.SendAction(&a_sync_end);
00096 }
00097
00098 void Action_MoveRight (Action *a)
00099 {
00100 assert(false);
00101 MoveCharacterRight (ActiveCharacter());
00102 }
00103
00104 void Action_MoveLeft (Action *a)
00105 {
00106 assert(false);
00107 MoveCharacterLeft (ActiveCharacter());
00108 }
00109
00110 void Action_Jump (Action *a)
00111 {
00112 GameLoop::GetInstance()->character_already_chosen = true;
00113 ActiveCharacter().Jump();
00114 }
00115
00116 void Action_HighJump (Action *a)
00117 {
00118 GameLoop::GetInstance()->character_already_chosen = true;
00119 ActiveCharacter().HighJump();
00120 }
00121
00122 void Action_BackJump (Action *a)
00123 {
00124 GameLoop::GetInstance()->character_already_chosen = true;
00125 ActiveCharacter().BackJump();
00126 }
00127
00128 void Action_Up (Action *a)
00129 {
00130 ActiveCharacter().AddFiringAngle(-DELTA_CROSSHAIR);
00131 }
00132
00133 void Action_Down (Action *a)
00134 {
00135 ActiveCharacter().AddFiringAngle(DELTA_CROSSHAIR);
00136 }
00137
00138 void Action_ChangeWeapon (Action *a)
00139 {
00140 ActiveTeam().SetWeapon(static_cast<Weapon::Weapon_type>(a->PopInt()));
00141 }
00142
00143 void Action_NextCharacter (Action *a)
00144 {
00145 a->RetrieveCharacter();
00146 a->RetrieveCharacter();
00147 camera.FollowObject(&ActiveCharacter(), true, true);
00148 }
00149
00150 void Action_ChangeCharacter (Action *a)
00151 {
00152 a->RetrieveCharacter();
00153 camera.FollowObject(&ActiveCharacter(), true, true);
00154 }
00155
00156 void Action_Shoot (Action *a)
00157 {
00158 double strength = a->PopDouble();
00159 double angle = a->PopDouble();
00160 a->RetrieveCharacter();
00161 ActiveTeam().AccessWeapon().PrepareShoot(strength, angle);
00162 }
00163
00164 void Action_Wind (Action *a)
00165 {
00166 wind.SetVal (a->PopInt());
00167 }
00168
00169 Action* BuildActionSendCharacterPhysics(int team_no, int char_no)
00170 {
00171 Action* a = new Action(Action::ACTION_SET_CHARACTER_PHYSICS);
00172 a->StoreCharacter(team_no, char_no);
00173 return a;
00174 }
00175
00176 void Action_SetCharacterPhysics (Action *a)
00177 {
00178 while(!a->IsEmpty())
00179 a->RetrieveCharacter();
00180 }
00181
00182 void Action_SetCharacterEnergy(Action *a)
00183 {
00184 int team_no, char_no;
00185 team_no = a->PopInt();
00186 char_no = a->PopInt();
00187 Character* c = teams_list.FindPlayingByIndex(team_no)->FindByIndex(char_no);
00188 c->SetEnergy( a->PopInt() );
00189 }
00190
00191 void Action_SetSkin (Action *a)
00192 {
00193
00194 if (!ActiveTeam().IsLocal() || network.state != Network::NETWORK_PLAYING)
00195 {
00196 ActiveTeam().ActiveCharacter().SetClothe(a->PopString());
00197 ActiveTeam().ActiveCharacter().SetMovement(a->PopString());
00198 ActiveTeam().ActiveCharacter().body->SetFrame((uint)a->PopInt());
00199 }
00200 }
00201
00202 void Action_SetCharacterDirection (Action *a)
00203 {
00204 ActiveCharacter().SetDirection (Body::Direction_t(a->PopInt()));
00205 }
00206
00207 void Action_SetMap (Action *a)
00208 {
00209 if (!network.IsClient()) return;
00210 MapsList::GetInstance()->SelectMapByName(a->PopString());
00211 network.network_menu->ChangeMapCallback();
00212 }
00213
00214 void Action_ChangeState (Action *a)
00215 {
00216 MSG_DEBUG("action.handler", "ChangeState");
00217
00218 if(network.IsServer())
00219 {
00220 switch(network.state)
00221 {
00222 case Network::NETWORK_OPTION_SCREEN:
00223
00224 network.client_inited++;
00225 break;
00226 case Network::NETWORK_INIT_GAME:
00227
00228 network.client_inited++;
00229 if(network.client_inited == network.connected_player)
00230 network.state = Network::NETWORK_READY_TO_PLAY;
00231 break;
00232 default:
00233 assert(false);
00234 break;
00235 }
00236 }
00237
00238 if(network.IsClient())
00239 {
00240 switch(network.state)
00241 {
00242 case Network::NETWORK_OPTION_SCREEN:
00243 network.state = Network::NETWORK_INIT_GAME;
00244 break;
00245 case Network::NETWORK_INIT_GAME:
00246 network.state = Network::NETWORK_READY_TO_PLAY;
00247 break;
00248 case Network::NETWORK_READY_TO_PLAY:
00249 network.state = Network::NETWORK_PLAYING;
00250 break;
00251 default:
00252 assert(false);
00253 }
00254 }
00255 }
00256
00257 void Action_SetGameMode (Action *a)
00258 {
00259 assert(network.IsClient());
00260 GameMode::GetInstance()->max_characters = a->PopInt();
00261 GameMode::GetInstance()->max_teams = a->PopInt();
00262 GameMode::GetInstance()->duration_turn = a->PopInt();
00263 GameMode::GetInstance()->duration_exchange_player = a->PopInt();
00264 GameMode::GetInstance()->duration_before_death_mode = a->PopInt();
00265 GameMode::GetInstance()->gravity = a->PopDouble();
00266 GameMode::GetInstance()->safe_fall = a->PopDouble();
00267 GameMode::GetInstance()->damage_per_fall_unit = a->PopDouble();
00268 GameMode::GetInstance()->duration_move_player = a->PopInt();
00269 GameMode::GetInstance()->allow_character_selection = a->PopInt();
00270 GameMode::GetInstance()->character.init_energy = a->PopInt();
00271 GameMode::GetInstance()->character.max_energy = a->PopInt();
00272 GameMode::GetInstance()->character.mass = a->PopInt();
00273 GameMode::GetInstance()->character.air_resist_factor = a->PopDouble();
00274 GameMode::GetInstance()->character.jump_strength = a->PopInt();
00275 GameMode::GetInstance()->character.jump_angle = a->PopDouble();
00276 GameMode::GetInstance()->character.super_jump_strength = a->PopInt();
00277 GameMode::GetInstance()->character.super_jump_angle = a->PopDouble();
00278 GameMode::GetInstance()->character.back_jump_strength = a->PopInt();
00279 GameMode::GetInstance()->character.back_jump_angle = a->PopDouble();
00280 }
00281
00282 void SendGameMode()
00283 {
00284 assert(network.IsServer());
00285 Action a(Action::ACTION_SET_GAME_MODE);
00286 a.Push((int)GameMode::GetInstance()->max_characters);
00287 a.Push((int)GameMode::GetInstance()->max_teams);
00288 a.Push((int)GameMode::GetInstance()->duration_turn);
00289 a.Push((int)GameMode::GetInstance()->duration_exchange_player);
00290 a.Push((int)GameMode::GetInstance()->duration_before_death_mode);
00291 a.Push(GameMode::GetInstance()->gravity);
00292 a.Push(GameMode::GetInstance()->safe_fall);
00293 a.Push(GameMode::GetInstance()->damage_per_fall_unit);
00294 a.Push((int)GameMode::GetInstance()->duration_move_player);
00295 a.Push(GameMode::GetInstance()->allow_character_selection);
00296 a.Push((int)GameMode::GetInstance()->character.init_energy);
00297 a.Push((int)GameMode::GetInstance()->character.max_energy);
00298 a.Push((int)GameMode::GetInstance()->character.mass);
00299 a.Push(GameMode::GetInstance()->character.air_resist_factor);
00300 a.Push((int)GameMode::GetInstance()->character.jump_strength);
00301 a.Push(GameMode::GetInstance()->character.jump_angle);
00302 a.Push((int)GameMode::GetInstance()->character.super_jump_strength);
00303 a.Push(GameMode::GetInstance()->character.super_jump_angle);
00304 a.Push((int)GameMode::GetInstance()->character.back_jump_strength);
00305 a.Push(GameMode::GetInstance()->character.back_jump_angle);
00306 network.SendAction(&a);
00307 }
00308
00309
00310 void Action_NewTeam (Action *a)
00311 {
00312 ConfigTeam the_team;
00313
00314 the_team.id = a->PopString();
00315 the_team.player_name = a->PopString();
00316 the_team.nb_characters = uint(a->PopInt());
00317
00318 teams_list.AddTeam (the_team);
00319
00320 network.network_menu->AddTeamCallback(the_team.id);
00321 }
00322
00323 void Action_UpdateTeam (Action *a)
00324 {
00325 ConfigTeam the_team;
00326
00327 the_team.id = a->PopString();
00328 the_team.player_name = a->PopString();
00329 the_team.nb_characters = uint(a->PopInt());
00330
00331 teams_list.UpdateTeam (the_team);
00332
00333 network.network_menu->UpdateTeamCallback(the_team.id);
00334 }
00335
00336
00337 void Action_DelTeam (Action *a)
00338 {
00339 std::string team = a->PopString();
00340 teams_list.DelTeam (team);
00341 network.network_menu->DelTeamCallback(team);
00342 }
00343
00344
00345 void Action_ChatMessage (Action *a)
00346 {
00347 if(Game::GetInstance()->IsGameLaunched())
00348
00349
00350 GameLoop::GetInstance()->chatsession.NewMessage(a->PopString());
00351 else
00352
00353 network.network_menu->ReceiveMsgCallback(a->PopString());
00354 }
00355
00356 void Action_ChangeTeam (Action *a)
00357 {
00358 teams_list.SetActive (a->PopString());
00359 ActiveTeam().PrepareTurn();
00360 assert (!ActiveCharacter().IsDead());
00361 }
00362
00363 void Action_AskVersion (Action *a)
00364 {
00365 if (!network.IsClient()) return;
00366 ActionHandler::GetInstance()->NewAction(new Action(Action::ACTION_SEND_VERSION, Constants::VERSION));
00367 }
00368
00369 void Action_SendVersion (Action *a)
00370 {
00371 if (!network.IsServer()) return;
00372 std::string version= a->PopString();
00373 if (version != Constants::VERSION)
00374 {
00375 Error(Format(_("Wormux versions are differents : client=%s, server=%s."),
00376 version.c_str(), Constants::VERSION.c_str()));
00377 }
00378 }
00379
00380 void Action_SendRandom (Action *a)
00381 {
00382 if (!network.IsClient()) return;
00383 randomSync.AddToTable(a->PopDouble());
00384 }
00385
00386 void Action_SupertuxState (Action *a)
00387 {
00388 assert(ActiveTeam().GetWeaponType() == Weapon::WEAPON_SUPERTUX);
00389 WeaponLauncher* launcher = static_cast<WeaponLauncher*>(&(ActiveTeam().AccessWeapon()));
00390 SuperTux* tux = static_cast<SuperTux*>(launcher->GetProjectile());
00391
00392 double x, y;
00393
00394 tux->SetAngle(a->PopDouble());
00395 x = a->PopDouble();
00396 y = a->PopDouble();
00397 tux->SetPhysXY(x, y);
00398 tux->SetSpeedXY(Point2d(0,0));
00399 }
00400
00401 void Action_SyncBegin (Action *a)
00402 {
00403 assert(!network.sync_lock);
00404 network.sync_lock = true;
00405 }
00406
00407 void Action_SyncEnd (Action *a)
00408 {
00409 assert(network.sync_lock);
00410 network.sync_lock = false;
00411 }
00412
00413
00414 void Action_Ping(Action *a)
00415 {
00416 }
00417
00418 void Action_Explosion (Action *a)
00419 {
00420 Point2i pos;
00421 ExplosiveWeaponConfig config;
00422
00423 pos.x = a->PopInt();
00424 pos.y = a->PopInt();
00425 config.explosion_range = a->PopInt();
00426 config.particle_range = a->PopInt();
00427 config.damage = a->PopInt();
00428 config.blast_range = a->PopDouble();
00429 config.blast_force = a->PopDouble();
00430 std::string son = a->PopString();
00431 bool fire_particle = a->PopInt();
00432 ParticleEngine::ESmokeStyle smoke = (ParticleEngine::ESmokeStyle)a->PopInt();
00433
00434 ApplyExplosion_common(pos, config, son, fire_particle, smoke);
00435 }
00436
00437 void Action_SetTarget (Action *a)
00438 {
00439 MSG_DEBUG("action.handler", "Set target by clicking");
00440
00441 Point2i target;
00442 target.x = a->PopInt();
00443 target.y = a->PopInt();
00444
00445 ActiveTeam().AccessWeapon().ChooseTarget (target);
00446 }
00447
00448 void Action_SetTimeout (Action *a)
00449 {
00450 WeaponLauncher* launcher = dynamic_cast<WeaponLauncher*>(&(ActiveTeam().AccessWeapon()));
00451 assert(launcher != NULL);
00452 launcher->GetProjectile()->m_timeout_modifier = a->PopInt();
00453 }
00454
00455 void Action_ConstructionUp (Action *a)
00456 {
00457 Construct* launcher = dynamic_cast<Construct*>(&(ActiveTeam().AccessWeapon()));
00458 assert(launcher != NULL);
00459 launcher->Up();
00460 }
00461
00462 void Action_ConstructionDown (Action *a)
00463 {
00464 Construct* launcher = dynamic_cast<Construct*>(&(ActiveTeam().AccessWeapon()));
00465 assert(launcher != NULL);
00466 launcher->Down();
00467 }
00468
00469 void Action_WeaponStopUse(Action *a)
00470 {
00471 ActiveTeam().AccessWeapon().ActionStopUse();
00472 }
00473
00474 void Action_Nickname(Action *a)
00475 {
00476
00477 }
00478
00479 void Action_Pause(Action *a)
00480 {
00481
00482 Game::GetInstance()->Pause();
00483 }
00484
00485 void ActionHandler::ExecActions()
00486 {
00487 Action * a;
00488 std::list<Action*> to_remove;
00489 std::list<Action*>::iterator it;
00490 assert(mutex!=NULL);
00491 for(it = queue.begin(); it != queue.end() ; ++it)
00492 {
00493 SDL_LockMutex(mutex);
00494 a = (*it);
00495 Time::GetInstance()->RefreshMaxTime((*it)->GetTimestamp());
00496
00497 if((*it)->GetTimestamp() > Time::GetInstance()->Read()) {
00498 SDL_UnlockMutex(mutex);
00499 continue;
00500 }
00501 SDL_UnlockMutex(mutex);
00502 Exec ((*it));
00503 to_remove.push_back((*it));
00504 }
00505 while(to_remove.size() != 0)
00506 {
00507 a = to_remove.front();
00508 to_remove.pop_front();
00509 queue.remove(a);
00510 delete(a);
00511 }
00512 }
00513
00514 void ActionHandler::NewAction(Action* a, bool repeat_to_network)
00515 {
00516 assert(mutex!=NULL);
00517 SDL_LockMutex(mutex);
00518
00519
00520 queue.push_back(a);
00521
00522 SDL_UnlockMutex(mutex);
00523 if (repeat_to_network) network.SendAction(a);
00524 }
00525
00526 void ActionHandler::Register (Action::Action_t action,
00527 const std::string &name,callback_t fct)
00528 {
00529 handler[action] = fct;
00530 action_name[action] = name;
00531 }
00532
00533 void ActionHandler::Exec(Action *a)
00534 {
00535 MSG_DEBUG("action_handler", "Executing action %s",GetActionName(a->GetType()).c_str());
00536 handler_it it=handler.find(a->GetType());
00537 assert(it != handler.end());
00538 (*it->second) (a);
00539 }
00540
00541 std::string ActionHandler::GetActionName (Action::Action_t action)
00542 {
00543 assert(mutex!=NULL);
00544 SDL_LockMutex(mutex);
00545 name_it it=action_name.find(action);
00546 assert(it != action_name.end());
00547 SDL_UnlockMutex(mutex);
00548 return it->second;
00549 }
00550
00551 ActionHandler::ActionHandler()
00552 {
00553 mutex = SDL_CreateMutex();
00554 SDL_LockMutex(mutex);
00555 Register (Action::ACTION_MOVE_LEFT, "move_left", &Action_MoveLeft);
00556 Register (Action::ACTION_MOVE_RIGHT, "move_right", &Action_MoveRight);
00557 Register (Action::ACTION_UP, "up", &Action_Up);
00558 Register (Action::ACTION_DOWN, "down", &Action_Down);
00559 Register (Action::ACTION_JUMP, "jump", &Action_Jump);
00560 Register (Action::ACTION_HIGH_JUMP, "super_jump", &Action_HighJump);
00561 Register (Action::ACTION_BACK_JUMP, "back_jump", &Action_BackJump);
00562 Register (Action::ACTION_SHOOT, "shoot", &Action_Shoot);
00563 Register (Action::ACTION_CHANGE_WEAPON, "change_weapon", &Action_ChangeWeapon);
00564 Register (Action::ACTION_WIND, "wind", &Action_Wind);
00565 Register (Action::ACTION_NEXT_CHARACTER, "next_character", &Action_NextCharacter);
00566 Register (Action::ACTION_CHANGE_CHARACTER, "change_character", &Action_ChangeCharacter);
00567 Register (Action::ACTION_SET_GAME_MODE, "set_game_mode", &Action_SetGameMode);
00568 Register (Action::ACTION_SET_MAP, "set_map", &Action_SetMap);
00569 Register (Action::ACTION_UPDATE_TEAM, "update_team", &Action_UpdateTeam);
00570 Register (Action::ACTION_NEW_TEAM, "new_team", &Action_NewTeam);
00571 Register (Action::ACTION_DEL_TEAM, "del_team", &Action_DelTeam);
00572 Register (Action::ACTION_CHANGE_TEAM, "change_team", &Action_ChangeTeam);
00573 Register (Action::ACTION_SET_CHARACTER_PHYSICS, "set_character_physics", &Action_SetCharacterPhysics);
00574 Register (Action::ACTION_SET_SKIN, "set_skin", &Action_SetSkin);
00575 Register (Action::ACTION_SET_CHARACTER_DIRECTION, "set_character_direction", &Action_SetCharacterDirection);
00576 Register (Action::ACTION_CHANGE_STATE, "change_state", &Action_ChangeState);
00577 Register (Action::ACTION_ASK_VERSION, "ask_version", &Action_AskVersion);
00578 Register (Action::ACTION_SEND_VERSION, "send_version", &Action_SendVersion);
00579 Register (Action::ACTION_SEND_RANDOM, "send_random", &Action_SendRandom);
00580 Register (Action::ACTION_PING, "ping", &Action_Ping);
00581 Register (Action::ACTION_SYNC_BEGIN, "sync_begin", &Action_SyncBegin);
00582 Register (Action::ACTION_SYNC_END, "sync_end", &Action_SyncEnd);
00583 Register (Action::ACTION_EXPLOSION, "explosion", &Action_Explosion);
00584 Register (Action::ACTION_SET_TARGET, "set_target", &Action_SetTarget);
00585 Register (Action::ACTION_SUPERTUX_STATE, "supertux_state", &Action_SupertuxState);
00586 Register (Action::ACTION_SET_TIMEOUT, "set_timeout", &Action_SetTimeout);
00587 Register (Action::ACTION_CONSTRUCTION_UP, "construction_up", &Action_ConstructionUp);
00588 Register (Action::ACTION_CONSTRUCTION_DOWN, "construction_down", &Action_ConstructionDown);
00589 Register (Action::ACTION_WEAPON_STOP_USE, "weapon_stop_use", &Action_WeaponStopUse);
00590 Register (Action::ACTION_SET_CHARACTER_ENERGY, "set_character_energy", &Action_SetCharacterEnergy);
00591 Register (Action::ACTION_CHAT_MESSAGE, "chat_message", Action_ChatMessage);
00592 Register (Action::ACTION_NICKNAME, "nickname", Action_Nickname);
00593 Register (Action::ACTION_PAUSE, "pause", Action_Pause);
00594 SDL_UnlockMutex(mutex);
00595 }
00596