From 7ee4fca120cc24ec5b1cae87c50cd000449d74bd Mon Sep 17 00:00:00 2001 From: nordsoft Date: Wed, 28 Sep 2022 23:15:05 +0400 Subject: [PATCH 01/11] Pass whole gamestate over network --- client/CServerHandler.cpp | 6 +++--- client/CServerHandler.h | 3 ++- client/Client.cpp | 7 ++++--- client/Client.h | 2 +- client/NetPacksLobbyClient.cpp | 2 +- lib/NetPacksLobby.h | 7 ++++++- server/NetPacksLobbyServer.cpp | 2 ++ 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index e8605fb39..9e31e2148 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -516,7 +516,7 @@ void CServerHandler::sendStartGame(bool allowOnlyAI) const sendLobbyPack(lsg); } -void CServerHandler::startGameplay() +void CServerHandler::startGameplay(CGameState * gameState) { if(CMM) CMM->disable(); @@ -525,10 +525,10 @@ void CServerHandler::startGameplay() switch(si->mode) { case StartInfo::NEW_GAME: - client->newGame(); + client->newGame(gameState); break; case StartInfo::CAMPAIGN: - client->newGame(); + client->newGame(gameState); break; case StartInfo::LOAD_GAME: client->loadGame(); diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 4650bf4d9..4306161f7 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -21,6 +21,7 @@ class PlayerColor; struct StartInfo; class CMapInfo; +class CGameState; struct ClientPlayer; struct CPack; struct CPackForLobby; @@ -142,7 +143,7 @@ public: void sendGuiAction(ui8 action) const override; void sendStartGame(bool allowOnlyAI = false) const override; - void startGameplay(); + void startGameplay(CGameState * gameState = nullptr); void endGameplay(bool closeConnection = true, bool restart = false); void startCampaignScenario(std::shared_ptr cs = {}); void showServerError(std::string txt); diff --git a/client/Client.cpp b/client/Client.cpp index e145c1b12..8e4a82848 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -180,14 +180,15 @@ events::EventBus * CClient::eventBus() const return clientEventBus.get(); } -void CClient::newGame() +void CClient::newGame(CGameState * gameState) { CSH->th->update(); CMapService mapService; - gs = new CGameState(); + gs = gameState ? gameState : new CGameState(); gs->preInit(VLC); logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); - gs->init(&mapService, CSH->si.get(), settings["general"]["saveRandomMaps"].Bool()); + if(!gameState) + gs->init(&mapService, CSH->si.get(), settings["general"]["saveRandomMaps"].Bool()); logNetwork->trace("Initializing GameState (together): %d ms", CSH->th->getDiff()); initMapHandler(); diff --git a/client/Client.h b/client/Client.h index 569277e93..be7e87091 100644 --- a/client/Client.h +++ b/client/Client.h @@ -150,7 +150,7 @@ public: vstd::CLoggerBase * logger() const override; events::EventBus * eventBus() const override; - void newGame(); + void newGame(CGameState * gameState); void loadGame(); void serialize(BinarySerializer & h, const int version); void serialize(BinaryDeserializer & h, const int version); diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index 88df3c774..66b89981b 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -111,7 +111,7 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) { - GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler)); + GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler, nullptr)); } bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) diff --git a/lib/NetPacksLobby.h b/lib/NetPacksLobby.h index 0f70fb2e8..d03c473c6 100644 --- a/lib/NetPacksLobby.h +++ b/lib/NetPacksLobby.h @@ -142,8 +142,9 @@ struct LobbyStartGame : public CLobbyPackToPropagate { // Set by server std::shared_ptr initializedStartInfo; + CGameState * initializedGameState; - LobbyStartGame() : initializedStartInfo(nullptr) {} + LobbyStartGame() : initializedStartInfo(nullptr), initializedGameState(nullptr) {} bool checkClientPermissions(CVCMIServer * srv) const; bool applyOnServer(CVCMIServer * srv); void applyOnServerAfterAnnounce(CVCMIServer * srv); @@ -153,6 +154,10 @@ struct LobbyStartGame : public CLobbyPackToPropagate template void serialize(Handler &h, const int version) { h & initializedStartInfo; + bool sps = h.smartPointerSerialization; + h.smartPointerSerialization = true; + h & initializedGameState; + h.smartPointerSerialization = sps; } }; diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index 5885630fd..0e2ab7c92 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -181,6 +181,8 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv) return false; initializedStartInfo = std::make_shared(*srv->gh->getStartInfo(true)); + initializedGameState = srv->gh->gameState(); + return true; } From 2eb497b477610889b1e5dc28e17d19576c21799c Mon Sep 17 00:00:00 2001 From: nordsoft Date: Wed, 28 Sep 2022 23:38:41 +0400 Subject: [PATCH 02/11] Looks like everything works --- client/CServerHandler.cpp | 2 ++ server/CVCMIServer.cpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 9e31e2148..a51dedc00 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -514,6 +514,8 @@ void CServerHandler::sendStartGame(bool allowOnlyAI) const * si = * lsg.initializedStartInfo; } sendLobbyPack(lsg); + c->enterLobbyConnectionMode(); + c->disableStackSendingByID(); } void CServerHandler::startGameplay(CGameState * gameState) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 6015608c7..5d392990e 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -230,10 +230,16 @@ bool CVCMIServer::prepareToStartGame() state = EServerState::LOBBY; // FIXME: dirry hack to make sure old CGameHandler::run is finished boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); + + for(auto c : connections) + { + c->enterLobbyConnectionMode(); + c->disableStackSendingByID(); + } } - if(!gh) - gh = std::make_shared(this); + //if(!gh) + gh = std::make_shared(this); switch(si->mode) { case StartInfo::CAMPAIGN: From 0eb589fb58fb8db1f9aaf07153b9724b30931d19 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 00:09:18 +0400 Subject: [PATCH 03/11] Load map by itself --- client/NetPacksLobbyClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index 66b89981b..656670a18 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -105,13 +105,13 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) handler->si = initializedStartInfo; } if(settings["session"]["headless"].Bool()) - handler->startGameplay(); + handler->startGameplay(initializedGameState); return true; } void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) { - GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler, nullptr)); + GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler, initializedGameState)); } bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) From bebe0dd86cead12beec83396bab585f68242402a Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 00:35:38 +0400 Subject: [PATCH 04/11] Some change --- server/CVCMIServer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 5d392990e..7fa9be1b1 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -230,12 +230,12 @@ bool CVCMIServer::prepareToStartGame() state = EServerState::LOBBY; // FIXME: dirry hack to make sure old CGameHandler::run is finished boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - - for(auto c : connections) - { - c->enterLobbyConnectionMode(); - c->disableStackSendingByID(); - } + } + + for(auto c : connections) + { + c->enterLobbyConnectionMode(); + c->disableStackSendingByID(); } //if(!gh) From 9fb5d0e726a66027ba30de48a077d9d741085fdb Mon Sep 17 00:00:00 2001 From: nordsoft Date: Mon, 26 Sep 2022 04:50:08 +0400 Subject: [PATCH 05/11] Fix stackinstance deserialization --- lib/CCreatureSet.cpp | 3 --- lib/CCreatureSet.h | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 6753c7174..412316449 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -859,9 +859,6 @@ PlayerColor CStackInstance::getOwner() const void CStackInstance::deserializationFix() { - const CCreature *backup = type; - type = nullptr; - setType(backup); const CArmedInstance *armyBackup = _armyObj; _armyObj = nullptr; setArmyObj(armyBackup); diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 484133c2b..258f3c7b2 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -12,6 +12,7 @@ #include "HeroBonus.h" #include "GameConstants.h" #include "CArtHandler.h" +#include "CCreatureHandler.h" VCMI_LIB_NAMESPACE_BEGIN @@ -40,7 +41,20 @@ public: template void serialize(Handler &h, const int version) { - h & type; + if(h.saving) + { + CreatureID idNumber = type ? type->idNumber : CreatureID(CreatureID::NONE); + h & idNumber; + } + else + { + CreatureID idNumber; + h & idNumber; + if(idNumber != CreatureID::NONE) + setType(VLC->creh->objects[idNumber]); + else + type = nullptr; + } h & count; } From cbfa12508509f5cd208b8cbcc804349547dc6a28 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 14:29:57 +0400 Subject: [PATCH 06/11] Remove commented line --- server/CVCMIServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 7fa9be1b1..ec9f03be9 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -238,7 +238,6 @@ bool CVCMIServer::prepareToStartGame() c->disableStackSendingByID(); } - //if(!gh) gh = std::make_shared(this); switch(si->mode) { From fea05a43202e044776da91323fed4fdb3b1878f3 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 21:08:05 +0400 Subject: [PATCH 07/11] Finally game restart works # Conflicts: # lib/CGameState.cpp # server/CVCMIServer.cpp --- client/CMT.cpp | 2 +- client/CServerHandler.cpp | 11 +++++++++++ client/CServerHandler.h | 2 ++ client/NetPacksLobbyClient.cpp | 13 +++++++++++-- lib/NetPacksLobby.h | 16 ++++++++++++++++ lib/registerTypes/RegisterTypes.h | 1 + server/CVCMIServer.cpp | 7 ++++++- server/CVCMIServer.h | 1 + server/NetPacksLobbyServer.cpp | 21 +++++++++++++++++++++ 9 files changed, 70 insertions(+), 4 deletions(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index 9a9139085..1e4c3f5b8 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -1359,7 +1359,7 @@ static void handleEvent(SDL_Event & ev) break; case EUserEvent::RESTART_GAME: { - CSH->sendStartGame(); + CSH->sendRestartGame(); } break; case EUserEvent::CAMPAIGN_START_SCENARIO: diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index a51dedc00..f76e6cac4 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -502,6 +502,14 @@ void CServerHandler::sendGuiAction(ui8 action) const sendLobbyPack(lga); } +void CServerHandler::sendRestartGame() const +{ + LobbyEndGame endGame; + endGame.closeConnection = false; + endGame.restart = true; + sendLobbyPack(endGame); +} + void CServerHandler::sendStartGame(bool allowOnlyAI) const { verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool()); @@ -568,6 +576,9 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart) GH.curInt = CMainMenu::create().get(); } } + + serverConnection->enterLobbyConnectionMode(); + serverConnection->disableStackSendingByID(); } void CServerHandler::startCampaignScenario(std::shared_ptr cs) diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 4306161f7..ee850e53b 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -70,6 +70,7 @@ public: virtual void sendMessage(const std::string & txt) const = 0; virtual void sendGuiAction(ui8 action) const = 0; // TODO: possibly get rid of it? virtual void sendStartGame(bool allowOnlyAI = false) const = 0; + virtual void sendRestartGame() const = 0; }; /// structure to handle running server and connecting to it @@ -141,6 +142,7 @@ public: void setTurnLength(int npos) const override; void sendMessage(const std::string & txt) const override; void sendGuiAction(ui8 action) const override; + void sendRestartGame() const override; void sendStartGame(bool allowOnlyAI = false) const override; void startGameplay(CGameState * gameState = nullptr); diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index 656670a18..4e758682a 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -93,12 +93,21 @@ void LobbyGuiAction::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * h } } -bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) +bool LobbyEndGame::applyOnLobbyHandler(CServerHandler * handler) { if(handler->state == EClientState::GAMEPLAY) { - handler->endGameplay(false, true); + handler->endGameplay(closeConnection, restart); } + + if(restart) + handler->sendStartGame(); + + return true; +} + +bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) +{ handler->state = EClientState::STARTING; if(handler->si->mode != StartInfo::LOAD_GAME) { diff --git a/lib/NetPacksLobby.h b/lib/NetPacksLobby.h index d03c473c6..b4d8c95b5 100644 --- a/lib/NetPacksLobby.h +++ b/lib/NetPacksLobby.h @@ -138,6 +138,22 @@ struct LobbyGuiAction : public CLobbyPackToPropagate } }; +struct LobbyEndGame : public CLobbyPackToPropagate +{ + bool closeConnection = false, restart = false; + + bool checkClientPermissions(CVCMIServer * srv) const; + bool applyOnServer(CVCMIServer * srv); + void applyOnServerAfterAnnounce(CVCMIServer * srv); + bool applyOnLobbyHandler(CServerHandler * handler); + + template void serialize(Handler &h, const int version) + { + h & closeConnection; + h & restart; + } +}; + struct LobbyStartGame : public CLobbyPackToPropagate { // Set by server diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 1e068c8ca..e73740b80 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -372,6 +372,7 @@ void registerTypesLobbyPacks(Serializer &s) s.template registerType(); // Only host client send s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); // Only server send diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index ec9f03be9..81307ebc8 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -220,7 +220,7 @@ void CVCMIServer::threadAnnounceLobby() } } -bool CVCMIServer::prepareToStartGame() +void CVCMIServer::prepareToRestart() { if(state == EServerState::GAMEPLAY) { @@ -237,7 +237,12 @@ bool CVCMIServer::prepareToStartGame() c->enterLobbyConnectionMode(); c->disableStackSendingByID(); } + boost::unique_lock queueLock(mx); + gh = nullptr; +} +bool CVCMIServer::prepareToStartGame() +{ gh = std::make_shared(this); switch(si->mode) { diff --git a/server/CVCMIServer.h b/server/CVCMIServer.h index e2f9d029c..0cffc2835 100644 --- a/server/CVCMIServer.h +++ b/server/CVCMIServer.h @@ -69,6 +69,7 @@ public: ~CVCMIServer(); void run(); bool prepareToStartGame(); + void prepareToRestart(); void startGameImmidiately(); void startAsyncAccept(); diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index 0e2ab7c92..5cea42e1d 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -161,6 +161,27 @@ bool LobbyGuiAction::checkClientPermissions(CVCMIServer * srv) const return srv->isClientHost(c->connectionID); } +bool LobbyEndGame::checkClientPermissions(CVCMIServer * srv) const +{ + return srv->isClientHost(c->connectionID); +} + +bool LobbyEndGame::applyOnServer(CVCMIServer * srv) +{ + srv->prepareToRestart(); + return true; +} + +void LobbyEndGame::applyOnServerAfterAnnounce(CVCMIServer * srv) +{ + boost::unique_lock stateLock(srv->stateMutex); + for(auto & c : srv->connections) + { + c->enterLobbyConnectionMode(); + c->disableStackSendingByID(); + } +} + bool LobbyStartGame::checkClientPermissions(CVCMIServer * srv) const { return srv->isClientHost(c->connectionID); From b888e640f3d4c39adfd7d2188822cf542b5035ef Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 21:18:30 +0400 Subject: [PATCH 08/11] Fix compilation --- client/CServerHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index f76e6cac4..bf6f08896 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -577,8 +577,8 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart) } } - serverConnection->enterLobbyConnectionMode(); - serverConnection->disableStackSendingByID(); + c->enterLobbyConnectionMode(); + c->disableStackSendingByID(); } void CServerHandler::startCampaignScenario(std::shared_ptr cs) From 8a8716ce8a0faec2e7b2956c14430558eb62e699 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 29 Sep 2022 21:33:44 +0400 Subject: [PATCH 09/11] Pass loaded game over network too --- client/CServerHandler.cpp | 2 +- client/Client.cpp | 75 ++++++++++++++++++++++----------------- client/Client.h | 2 +- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index bf6f08896..9ba3a75ed 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -541,7 +541,7 @@ void CServerHandler::startGameplay(CGameState * gameState) client->newGame(gameState); break; case StartInfo::LOAD_GAME: - client->loadGame(); + client->loadGame(gameState); break; default: throw std::runtime_error("Invalid mode"); diff --git a/client/Client.cpp b/client/Client.cpp index 8e4a82848..65efe2dac 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -197,54 +197,63 @@ void CClient::newGame(CGameState * gameState) initPlayerInterfaces(); } -void CClient::loadGame() +void CClient::loadGame(CGameState * gameState) { logNetwork->info("Loading procedure started!"); - std::unique_ptr loader; - try + if(gameState) { - boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME)); - boost::filesystem::path controlServerSaveName; - - if(CResourceHandler::get("local")->existsResource(ResourceID(CSH->si->mapname, EResType::SERVER_SAVEGAME))) - { - controlServerSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::SERVER_SAVEGAME)); - } - else // create entry for server savegame. Triggered if save was made after launch and not yet present in res handler - { - controlServerSaveName = boost::filesystem::path(clientSaveName).replace_extension(".vsgm1"); - CResourceHandler::get("local")->createResource(controlServerSaveName.string(), true); - } - - if(clientSaveName.empty()) - throw std::runtime_error("Cannot open client part of " + CSH->si->mapname); - if(controlServerSaveName.empty() || !boost::filesystem::exists(controlServerSaveName)) - throw std::runtime_error("Cannot open server part of " + CSH->si->mapname); - - { - CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, MINIMAL_SERIALIZATION_VERSION); - loadCommonState(checkingLoader); - loader = checkingLoader.decay(); - } - + logNetwork->info("Game state was transferred over network, loading."); + gs = gameState; } - catch(std::exception & e) + else { - logGlobal->error("Cannot load game %s. Error: %s", CSH->si->mapname, e.what()); - throw; //obviously we cannot continue here + std::unique_ptr loader; + try + { + boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME)); + boost::filesystem::path controlServerSaveName; + + if(CResourceHandler::get("local")->existsResource(ResourceID(CSH->si->mapname, EResType::SERVER_SAVEGAME))) + { + controlServerSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::SERVER_SAVEGAME)); + } + else // create entry for server savegame. Triggered if save was made after launch and not yet present in res handler + { + controlServerSaveName = boost::filesystem::path(clientSaveName).replace_extension(".vsgm1"); + CResourceHandler::get("local")->createResource(controlServerSaveName.string(), true); + } + + if(clientSaveName.empty()) + throw std::runtime_error("Cannot open client part of " + CSH->si->mapname); + if(controlServerSaveName.empty() || !boost::filesystem::exists(controlServerSaveName)) + throw std::runtime_error("Cannot open server part of " + CSH->si->mapname); + + { + CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, MINIMAL_SERIALIZATION_VERSION); + loadCommonState(checkingLoader); + loader = checkingLoader.decay(); + } + + serialize(loader->serializer, loader->serializer.fileVersion); + } + catch(std::exception & e) + { + logGlobal->error("Cannot load game %s. Error: %s", CSH->si->mapname, e.what()); + throw; //obviously we cannot continue here + } + logNetwork->trace("Loaded common part of save %d ms", CSH->th->getDiff()); } - logNetwork->trace("Loaded common part of save %d ms", CSH->th->getDiff()); gs->preInit(VLC); gs->updateOnLoad(CSH->si.get()); + logNetwork->info("Game loaded, initialize interfaces."); + initMapHandler(); reinitScripting(); initPlayerEnvironments(); - serialize(loader->serializer, loader->serializer.fileVersion); - initPlayerInterfaces(); } diff --git a/client/Client.h b/client/Client.h index be7e87091..71fbd2eb2 100644 --- a/client/Client.h +++ b/client/Client.h @@ -151,7 +151,7 @@ public: events::EventBus * eventBus() const override; void newGame(CGameState * gameState); - void loadGame(); + void loadGame(CGameState * gameState); void serialize(BinarySerializer & h, const int version); void serialize(BinaryDeserializer & h, const int version); From 3621b05682d160e147d618c5a9f1bc6ec06a78f7 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 30 Sep 2022 18:28:17 +0400 Subject: [PATCH 10/11] Rename variable --- client/Client.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index 65efe2dac..34b9b0a13 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -180,14 +180,14 @@ events::EventBus * CClient::eventBus() const return clientEventBus.get(); } -void CClient::newGame(CGameState * gameState) +void CClient::newGame(CGameState * initializedGameState) { CSH->th->update(); CMapService mapService; - gs = gameState ? gameState : new CGameState(); + gs = initializedGameState ? initializedGameState : new CGameState(); gs->preInit(VLC); logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); - if(!gameState) + if(!initializedGameState) gs->init(&mapService, CSH->si.get(), settings["general"]["saveRandomMaps"].Bool()); logNetwork->trace("Initializing GameState (together): %d ms", CSH->th->getDiff()); @@ -197,14 +197,14 @@ void CClient::newGame(CGameState * gameState) initPlayerInterfaces(); } -void CClient::loadGame(CGameState * gameState) +void CClient::loadGame(CGameState * initializedGameState) { logNetwork->info("Loading procedure started!"); - if(gameState) + if(initializedGameState) { logNetwork->info("Game state was transferred over network, loading."); - gs = gameState; + gs = initializedGameState; } else { From 628abd142837f1c9d983bb9f03ce4314b4976f0a Mon Sep 17 00:00:00 2001 From: nordsoft Date: Mon, 3 Oct 2022 01:48:03 +0400 Subject: [PATCH 11/11] Fix campaign serialization --- client/Client.cpp | 8 +++++--- client/NetPacksLobbyClient.cpp | 3 ++- lib/mapping/CMap.h | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index 34b9b0a13..5ee3c6cb0 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -200,6 +200,8 @@ void CClient::newGame(CGameState * initializedGameState) void CClient::loadGame(CGameState * initializedGameState) { logNetwork->info("Loading procedure started!"); + + std::unique_ptr loader; if(initializedGameState) { @@ -208,7 +210,6 @@ void CClient::loadGame(CGameState * initializedGameState) } else { - std::unique_ptr loader; try { boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME)); @@ -234,8 +235,6 @@ void CClient::loadGame(CGameState * initializedGameState) loadCommonState(checkingLoader); loader = checkingLoader.decay(); } - - serialize(loader->serializer, loader->serializer.fileVersion); } catch(std::exception & e) { @@ -253,6 +252,9 @@ void CClient::loadGame(CGameState * initializedGameState) reinitScripting(); initPlayerEnvironments(); + + if(loader) + serialize(loader->serializer, loader->serializer.fileVersion); initPlayerInterfaces(); } diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index 4e758682a..a5966a40e 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -57,7 +57,8 @@ bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler) void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) { - GH.popInts(1); + if(GH.listInt.size()) + GH.popInts(1); } void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index e32d47ab6..b8047624b 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -330,7 +330,7 @@ public: h & players; h & howManyTeams; h & allowedHeroes; - h & triggeredEvents; + //Do not serialize triggeredEvents in header as they can contain information about heroes and armies h & victoryMessage; h & victoryIconIndex; h & defeatMessage; @@ -424,6 +424,7 @@ public: void serialize(Handler &h, const int formatVersion) { h & static_cast(*this); + h & triggeredEvents; //from CMapHeader h & rumors; h & allowedSpell; h & allowedAbilities;