2
0
Эх сурвалжийг харах

Merge pull request #1663 from Adriankhl/fix_load_sleeping_heroes

Fix client data deserialization, such as sleepingHeroes
Ivan Savenko 2 жил өмнө
parent
commit
129b5313c5

+ 32 - 63
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 <vcmi/events/EventBus.h>
 
 #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<CLoadFile> 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;
-
-			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);
+	logNetwork->info("Game state was transferred over network, loading.");
+	gs = initializedGameState;
 
-			{
-				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<CLoadFile> 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

+ 0 - 1
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)

+ 2 - 2
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;

+ 1 - 0
lib/mapObjects/CObjectClassesHandler.h

@@ -263,6 +263,7 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
+		h & id;
 		h & handlerName;
 		h & base;
 		h & objects;

+ 2 - 2
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;