This patch makes it easier to remove the action ACTION_GAMELOOP_SET_STATE at a later stage. Additionally it's easier now to move the check to another location in the code. --- lib/wormux/include/WORMUX_action.h | 1 + src/game/game.cpp | 13 +++++++++---- src/include/action_handler.cpp | 25 ++++++++++++++----------- src/network/randomsync.cpp | 13 +++++++++++++ src/network/randomsync.h | 1 + 5 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/lib/wormux/include/WORMUX_action.h b/lib/wormux/include/WORMUX_action.h index b423346..a64a515 100644 --- a/lib/wormux/include/WORMUX_action.h +++ b/lib/wormux/include/WORMUX_action.h @@ -109,6 +109,7 @@ public: ACTION_EXPLOSION, ACTION_WIND, ACTION_NETWORK_PING, + ACTION_NETWORK_VERIFY_RANDOM_SYNC, // ######################################################## } Action_t; diff --git a/src/game/game.cpp b/src/game/game.cpp index af266bb..f62dbb6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -664,6 +664,15 @@ void Game::SetState(game_loop_state_t new_state, bool begin_game) const // already in good state, nothing to do if ((state == new_state) && !begin_game) return; + + // The action which verifys the random seed must be the first action sheduled! + // Otherwise the following could happen: + // 1. Action C gets sheduled which draws values from the random source. + // 2. Action V gets sheduled which verifies that random seed is X. + // 3. Action C gets executed: As a result the random seed has changed to another value Y. + // 4. Action V gets executed: It fails as the random seed is no longer X but Y. + RandomSync().Verify(); + // Send information about energy and position of every characters // ONLY at the beginning of a new turn! // (else you can send unstable information of a character which is moving) @@ -672,11 +681,7 @@ void Game::SetState(game_loop_state_t new_state, bool begin_game) const SyncCharacters(); MSG_DEBUG("game", "Ask for state %d", new_state); - - MSG_DEBUG("random.get", "Game::SetState(...): %d"); Action *a = new Action(Action::ACTION_GAMELOOP_SET_STATE); - uint seed = RandomSync().GetSeed(); - a->Push((int)seed); a->Push(new_state); ActionHandler::GetInstance()->NewAction(a); } diff --git a/src/include/action_handler.cpp b/src/include/action_handler.cpp index 3c1ff0b..1e747e3 100644 --- a/src/include/action_handler.cpp +++ b/src/include/action_handler.cpp @@ -346,17 +346,6 @@ static void Action_DropBonusBox (Action *a) static void Action_Game_SetState (Action *a) { - // to re-synchronize random number generator - uint seed = (uint)(a->PopInt()); -#ifdef DEBUG - if (IsLOGGING("random")) { - uint nb = RandomSync().GetSeed(); - MSG_DEBUG("random.get", "Action_Game_SetState(...): %d", nb); - ASSERT(nb == seed); - } -#endif - RandomSync().SetSeed(seed); - Game::game_loop_state_t state = Game::game_loop_state_t(a->PopInt()); Game::GetInstance()->Really_SetState(state); } @@ -799,6 +788,19 @@ static void Action_Network_RandomInit (Action *a) RandomSync().SetSeed(a->PopInt()); } +static void Action_Network_VerifyRandomSync(Action *a) +{ + uint local_seed = RandomSync().GetSeed(); + uint remote_seed = (uint)(a->PopInt()); + MSG_DEBUG("random.verify","Verify seed: %d (local) == %d (remote)", local_seed, remote_seed); + + if (IsLOGGING("random")) + ASSERT(remote_seed == local_seed); + + if (local_seed != remote_seed) + RandomSync().SetSeed(remote_seed); +} + // Nothing to do here. Just for time synchronisation static void Action_Network_Ping(Action */*a*/) { @@ -1059,6 +1061,7 @@ void Action_Handler_Init() ActionHandler::GetInstance()->Register (Action::ACTION_EXPLOSION, "explosion", &Action_Explosion); ActionHandler::GetInstance()->Register (Action::ACTION_WIND, "wind", &Action_Wind); ActionHandler::GetInstance()->Register (Action::ACTION_NETWORK_RANDOM_INIT, "NETWORK_random_init", &Action_Network_RandomInit); + ActionHandler::GetInstance()->Register (Action::ACTION_NETWORK_VERIFY_RANDOM_SYNC, "NETWORK_verify_random_sync", &Action_Network_VerifyRandomSync); ActionHandler::GetInstance()->Register (Action::ACTION_INFO_CLIENT_DISCONNECT, "INFO_client_disconnect", &Action_Info_ClientDisconnect); ActionHandler::GetInstance()->Register (Action::ACTION_INFO_CLIENT_CONNECT, "INFO_client_connect", &Action_Info_ClientConnect); diff --git a/src/network/randomsync.cpp b/src/network/randomsync.cpp index e86f8df..fb0f412 100644 --- a/src/network/randomsync.cpp +++ b/src/network/randomsync.cpp @@ -66,6 +66,19 @@ void RandomSyncGen::SetRand(uint seed) RandomGenerator::SetRand(seed); } +void RandomSyncGen::Verify() +{ + MSG_DEBUG("random.verify","Verify seed (%d)", GetSeed()); + bool turn_master = Network::GetInstance()->IsTurnMaster(); + ASSERT(turn_master); + if (!turn_master) + return; + uint seed = GetSeed(); + Action* action = new Action(Action::ACTION_NETWORK_VERIFY_RANDOM_SYNC); + action->Push((int)seed); + ActionHandler::GetInstance()->NewAction(action); +} + RandomSyncGen& RandomSync() { return (*RandomSyncGen::GetInstance()); diff --git a/src/network/randomsync.h b/src/network/randomsync.h index efb0397..181ed2b 100644 --- a/src/network/randomsync.h +++ b/src/network/randomsync.h @@ -36,6 +36,7 @@ protected: virtual void SetRand(uint seed); public: virtual void InitRandom(); + void Verify(); }; RandomSyncGen& RandomSync(); -- 1.6.0.4 _______________________________________________ Wormux-dev mailing list Wormux-dev@gna.org https://mail.gna.org/listinfo/wormux-dev