diff --git a/client/Client.cpp b/client/Client.cpp index 168b1d24b..3e0524f9c 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -10,27 +10,16 @@ #include "StdInc.h" #include "Client.h" -#include "CMusicHandler.h" -#include "../lib/mapping/CCampaignHandler.h" #include "../CCallback.h" #include "adventureMap/CAdvMapInt.h" #include "mapView/mapHandler.h" -#include "../lib/CConsoleHandler.h" #include "CGameInfo.h" #include "../lib/CGameState.h" #include "CPlayerInterface.h" #include "../lib/StartInfo.h" #include "../lib/battle/BattleInfo.h" -#include "../lib/CModHandler.h" -#include "../lib/CArtHandler.h" -#include "../lib/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" -#include "../lib/CTownHandler.h" -#include "../lib/CBuildingHandler.h" -#include "../lib/spells/CSpellHandler.h" #include "../lib/serializer/CTypeList.h" #include "../lib/serializer/Connection.h" -#include "../lib/serializer/CLoadIntegrityValidator.h" #include "../lib/NetPacks.h" #include "ClientNetPackVisitors.h" #include "../lib/VCMI_Lib.h" @@ -39,15 +28,12 @@ #include "../lib/mapping/CMapService.h" #include "../lib/JsonNode.h" #include "../lib/CConfigHandler.h" -#include "mainmenu/CMainMenu.h" -#include "mainmenu/CCampaignScreen.h" -#include "lobby/CBonusSelection.h" #include "battle/BattleInterface.h" #include "../lib/CThreadHelper.h" #include "../lib/registerTypes/RegisterTypes.h" #include "gui/CGuiHandler.h" #include "CServerHandler.h" -#include "../lib/ScriptHandler.h" +#include "serializer/BinaryDeserializer.h" #include #ifdef VCMI_ANDROID @@ -201,62 +187,38 @@ void CClient::newGame(CGameState * initializedGameState) void CClient::loadGame(CGameState * initializedGameState) { logNetwork->info("Loading procedure started!"); - - std::unique_ptr loader; - if(initializedGameState) - { - logNetwork->info("Game state was transferred over network, loading."); - gs = initializedGameState; - } - else - { - try - { - boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME)); - boost::filesystem::path controlServerSaveName; + logNetwork->info("Game state was transferred over network, loading."); + gs = initializedGameState; - 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(); - } - } - 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()); - } gs->preInit(VLC); gs->updateOnLoad(CSH->si.get()); logNetwork->info("Game loaded, initialize interfaces."); - + initMapHandler(); reinitScripting(); initPlayerEnvironments(); - if(loader) + // try to deserialize client data including sleepingHeroes + try + { + boost::filesystem::path clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(CSH->si->mapname, EResType::CLIENT_SAVEGAME)); + + if(clientSaveName.empty()) + throw std::runtime_error("Cannot open client part of " + CSH->si->mapname); + + std::unique_ptr loader (new CLoadFile(clientSaveName)); serialize(loader->serializer, loader->serializer.fileVersion); + logNetwork->info("Client data loaded."); + } + catch(std::exception & e) + { + logGlobal->info("Cannot load client data for game %s. Error: %s", CSH->si->mapname, e.what()); + } + initPlayerInterfaces(); } @@ -320,8 +282,7 @@ void CClient::serialize(BinaryDeserializer & h, const int version) nInt->human = isHuman; nInt->playerID = pid; - nInt->loadGame(h, version); - + bool shouldResetInterface = true; // Client no longer handle this player at all if(!vstd::contains(CSH->getAllClientPlayers(CSH->c->connectionID), pid)) { @@ -338,10 +299,18 @@ void CClient::serialize(BinaryDeserializer & h, const int version) else { installNewPlayerInterface(nInt, pid); - continue; + shouldResetInterface = false; + } + + // loadGame needs to be called after initGameInterface to load paths correctly + // initGameInterface is called in installNewPlayerInterface + nInt->loadGame(h, version); + + if (shouldResetInterface) + { + nInt.reset(); + LOCPLINT = prevInt; } - nInt.reset(); - LOCPLINT = prevInt; } #if SCRIPTING_ENABLED diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 118e50017..9806932bb 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -840,7 +840,6 @@ void ApplyClientNetPackVisitor::visitSaveGameClient(SaveGameClient & pack) try { CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(stem.to_string(), EResType::CLIENT_SAVEGAME))); - cl.saveCommonState(save); save << cl; } catch(std::exception &e) diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index d9cde524f..ab83cb5ab 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -224,11 +224,11 @@ void SelectionTab::toggleMode() case ESelectionScreen::loadGame: inputName->disable(); - parseSaves(getFiles("Saves/", EResType::CLIENT_SAVEGAME)); + parseSaves(getFiles("Saves/", EResType::SERVER_SAVEGAME)); break; case ESelectionScreen::saveGame: - parseSaves(getFiles("Saves/", EResType::CLIENT_SAVEGAME)); + parseSaves(getFiles("Saves/", EResType::SERVER_SAVEGAME)); inputName->enable(); restoreLastSelection(); break; diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index b782dbd92..bb8641a77 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -263,6 +263,7 @@ public: template void serialize(Handler &h, const int version) { + h & id; h & handlerName; h & base; h & objects; diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index e595fadd5..e7793d84f 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -14,8 +14,8 @@ VCMI_LIB_NAMESPACE_BEGIN -const ui32 SERIALIZATION_VERSION = 817; -const ui32 MINIMAL_SERIALIZATION_VERSION = 813; +const ui32 SERIALIZATION_VERSION = 818; +const ui32 MINIMAL_SERIALIZATION_VERSION = 818; const std::string SAVEGAME_MAGIC = "VCMISVG"; class CHero;