diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 345b0a1a6..1b4f55886 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -1119,7 +1119,7 @@ void SelectionTab::parseGames(const std::unordered_set &files, bool { try { - CLoadFile lf(*CResourceHandler::get()->getResourceName(file)); + CLoadFile lf(*CResourceHandler::get()->getResourceName(file), minSupportedVersion); lf.checkMagicBytes(SAVEGAME_MAGIC); // ui8 sign[8]; // lf >> sign; diff --git a/client/Client.cpp b/client/Client.cpp index fea87d2a0..be50f9f0a 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -244,7 +244,7 @@ void CClient::loadGame( const std::string & fname ) unique_ptr loader; { - CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName); + CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, minSupportedVersion); loadCommonState(checkingLoader); loader = checkingLoader.decay(); } diff --git a/lib/CModHandler.h b/lib/CModHandler.h index cbe6397a5..fa0050ea5 100644 --- a/lib/CModHandler.h +++ b/lib/CModHandler.h @@ -41,6 +41,18 @@ class CIdentifierStorage { si32 id; std::string scope; /// scope in which this ID located + + + template void serialize(Handler &h, const int version) + { + if(version >= 744) + h & id & scope; + else if(h.saving) + { + logGlobal->warnStream() << "Save compatibility, making object data with id -1 (can this happen?)"; + id = -1; + } + } }; std::multimap registeredObjects; @@ -72,6 +84,12 @@ public: /// called at the very end of loading to check for any missing ID's void finalize(); + + template void serialize(Handler &h, const int version) + { + if(version >= 744) + h & registeredObjects; + } }; /// class used to load all game data into handlers. Used only during loading @@ -249,5 +267,9 @@ public: template void serialize(Handler &h, const int version) { h & allMods & activeMods & settings & modules; + if(version >= 744) + h & identifiers; + else + logGlobal->warnStream() << "Savegame compatibility mode, omitting identifiers in modhandler. Related bugs will persist."; } }; diff --git a/lib/Connection.h b/lib/Connection.h index 79f276e32..b0c6a53f5 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -28,7 +28,8 @@ #include "mapping/CCampaignHandler.h" //for CCampaignState #include "rmg/CMapGenerator.h" // for CMapGenOptions -const ui32 version = 743; +const ui32 version = 744; +const ui32 minSupportedVersion = 743; class CConnection; class CGObjectInstance; @@ -798,6 +799,13 @@ public: for(typename std::map::const_iterator i=data.begin();i!=data.end();i++) *this << i->first << i->second; } + template + void saveSerializable(const std::multimap &data) + { + *this << ui32(data.size()); + for(typename std::map::const_iterator i = data.begin(); i != data.end(); i++) + *this << i->first << i->second; + } template void saveSerializable(const boost::variant &data) { @@ -1198,6 +1206,19 @@ public: *this >> data[t]; } } + template + void loadSerializable(std::multimap &data) + { + READ_CHECK_U32(length); + data.clear(); + T1 key; + T2 value; + for(ui32 i = 0; i < length; i++) + { + *this >> key >> value; + data.insert(std::pair(std::move(key), std::move(value))); + } + } void loadSerializable(std::string &data) { READ_CHECK_U32(length); diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 2c41222d4..fe51e362a 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -477,7 +477,7 @@ void CVCMIServer::loadGame() // } { - CLoadFile lf(*CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME))); + CLoadFile lf(*CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME)), minSupportedVersion); gh.loadCommonState(lf); lf >> gh; }