소스 검색

Merge pull request #3147 from IvanSavenko/serialization_refactor

Serialization refactor - remove VLC from saved games
Ivan Savenko 1 년 전
부모
커밋
07472d3b05
94개의 변경된 파일1223개의 추가작업 그리고 2405개의 파일을 삭제
  1. 2 2
      AI/Nullkiller/AIGateway.cpp
  2. 2 2
      AI/VCAI/VCAI.cpp
  3. 2 2
      client/CPlayerInterface.cpp
  4. 5 5
      client/CServerHandler.cpp
  5. 8 8
      client/Client.cpp
  6. 4 0
      client/mapView/mapHandler.cpp
  7. 1 1
      client/windows/CMapOverview.cpp
  8. 11 11
      cmake_modules/VCMI_lib.cmake
  9. 2 0
      include/vcmi/Entity.h
  10. 0 18
      lib/BattleFieldHandler.h
  11. 0 70
      lib/CArtHandler.cpp
  12. 0 47
      lib/CArtHandler.h
  13. 1 78
      lib/CCreatureHandler.h
  14. 0 61
      lib/CHeroHandler.h
  15. 0 24
      lib/CSkillHandler.h
  16. 0 96
      lib/CTownHandler.h
  17. 14 13
      lib/IGameCallback.cpp
  18. 1 1
      lib/IGameCallback.h
  19. 2 2
      lib/JsonNode.h
  20. 2 1
      lib/JsonRandom.cpp
  21. 0 22
      lib/ObstacleHandler.h
  22. 0 21
      lib/RiverHandler.h
  23. 0 14
      lib/RoadHandler.h
  24. 0 29
      lib/TerrainHandler.h
  25. 0 45
      lib/VCMI_Lib.h
  26. 1 1
      lib/bonuses/BonusSelector.h
  27. 22 0
      lib/constants/EntityIdentifiers.cpp
  28. 15 5
      lib/constants/EntityIdentifiers.h
  29. 74 8
      lib/gameState/CGameState.cpp
  30. 10 0
      lib/gameState/CGameState.h
  31. 1 1
      lib/gameState/CGameStateCampaign.cpp
  32. 0 14
      lib/mapObjectConstructors/AObjectTypeHandler.h
  33. 0 9
      lib/mapObjectConstructors/CBankInstanceConstructor.h
  34. 0 15
      lib/mapObjectConstructors/CObjectClassesHandler.h
  35. 0 7
      lib/mapObjectConstructors/CRewardableConstructor.h
  36. 0 34
      lib/mapObjectConstructors/CommonConstructors.h
  37. 0 7
      lib/mapObjectConstructors/DwellingInstanceConstructor.h
  38. 0 5
      lib/mapObjectConstructors/HillFortInstanceConstructor.h
  39. 0 8
      lib/mapObjectConstructors/RandomMapInfo.h
  40. 0 7
      lib/mapObjectConstructors/SObjectSounds.h
  41. 0 5
      lib/mapObjectConstructors/ShipyardInstanceConstructor.h
  42. 1 1
      lib/mapObjects/CGObjectInstance.cpp
  43. 1 1
      lib/mapObjects/CGObjectInstance.h
  44. 12 1
      lib/mapObjects/CGTownInstance.h
  45. 0 5
      lib/mapObjects/CObjectHandler.h
  46. 5 5
      lib/mapObjects/MiscObjects.cpp
  47. 1 1
      lib/mapObjects/ObjectTemplate.h
  48. 1 1
      lib/mapping/CMapHeader.h
  49. 1 1
      lib/mapping/CMapInfo.cpp
  50. 1 1
      lib/mapping/CMapService.h
  51. 1 1
      lib/mapping/MapFormatJson.cpp
  52. 112 0
      lib/modding/ActiveModsInSaveList.cpp
  53. 51 0
      lib/modding/ActiveModsInSaveList.h
  54. 0 82
      lib/modding/CModHandler.cpp
  55. 5 32
      lib/modding/CModHandler.h
  56. 1 1
      lib/modding/CModInfo.cpp
  57. 3 33
      lib/modding/CModInfo.h
  58. 2 0
      lib/modding/CModVersion.h
  59. 0 12
      lib/modding/IdentifierStorage.h
  60. 44 0
      lib/modding/ModVerificationInfo.h
  61. 1 1
      lib/networkPacks/NetPacksLib.cpp
  62. 0 52
      lib/registerTypes/RegisterTypes.cpp
  63. 6 399
      lib/registerTypes/RegisterTypes.h
  64. 125 0
      lib/registerTypes/RegisterTypesClientPacks.h
  65. 62 0
      lib/registerTypes/RegisterTypesLobbyPacks.h
  66. 137 0
      lib/registerTypes/RegisterTypesMapObjects.h
  67. 56 0
      lib/registerTypes/RegisterTypesServerPacks.h
  68. 0 33
      lib/registerTypes/TypesClientPacks1.cpp
  69. 0 37
      lib/registerTypes/TypesClientPacks2.cpp
  70. 0 43
      lib/registerTypes/TypesLobbyPacks.cpp
  71. 0 34
      lib/registerTypes/TypesMapObjects1.cpp
  72. 0 36
      lib/registerTypes/TypesMapObjects2.cpp
  73. 0 32
      lib/registerTypes/TypesMapObjects3.cpp
  74. 0 32
      lib/registerTypes/TypesServerPacks.cpp
  75. 6 85
      lib/serializer/BinaryDeserializer.cpp
  76. 54 129
      lib/serializer/BinaryDeserializer.h
  77. 4 58
      lib/serializer/BinarySerializer.cpp
  78. 23 38
      lib/serializer/BinarySerializer.h
  79. 100 0
      lib/serializer/CLoadFile.cpp
  80. 42 0
      lib/serializer/CLoadFile.h
  81. 0 68
      lib/serializer/CLoadIntegrityValidator.cpp
  82. 0 33
      lib/serializer/CLoadIntegrityValidator.h
  83. 0 4
      lib/serializer/CMemorySerializer.cpp
  84. 72 0
      lib/serializer/CSaveFile.cpp
  85. 42 0
      lib/serializer/CSaveFile.h
  86. 24 35
      lib/serializer/CSerializer.h
  87. 0 119
      lib/serializer/CTypeList.cpp
  88. 34 162
      lib/serializer/CTypeList.h
  89. 0 40
      lib/serializer/Cast.h
  90. 1 4
      lib/serializer/Connection.cpp
  91. 0 42
      lib/spells/CSpellHandler.h
  92. 1 1
      mapeditor/mapcontroller.h
  93. 8 8
      server/CGameHandler.cpp
  94. 3 3
      server/CVCMIServer.cpp

+ 2 - 2
AI/Nullkiller/AIGateway.cpp

@@ -421,14 +421,14 @@ void AIGateway::requestRealized(PackageApplied * pa)
 	NET_EVENT_HANDLER;
 	if(status.haveTurn())
 	{
-		if(pa->packType == typeList.getTypeID<EndTurn>())
+		if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
 		{
 			if(pa->result)
 				status.madeTurn();
 		}
 	}
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 	{
 		status.receivedAnswerConfirmation(pa->requestID, pa->result);
 	}

+ 2 - 2
AI/VCAI/VCAI.cpp

@@ -505,14 +505,14 @@ void VCAI::requestRealized(PackageApplied * pa)
 	NET_EVENT_HANDLER;
 	if(status.haveTurn())
 	{
-		if(pa->packType == typeList.getTypeID<EndTurn>())
+		if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
 		{
 			if(pa->result)
 				status.madeTurn();
 		}
 	}
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 	{
 		status.receivedAnswerConfirmation(pa->requestID, pa->result);
 	}

+ 2 - 2
client/CPlayerInterface.cpp

@@ -1237,10 +1237,10 @@ void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, con
 
 void CPlayerInterface::requestRealized( PackageApplied *pa )
 {
-	if(pa->packType == typeList.getTypeID<MoveHero>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr))
 		movementController->onMoveHeroApplied();
 
-	if(pa->packType == typeList.getTypeID<QueryReply>())
+	if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
 		movementController->onQueryReplyApplied();
 }
 

+ 5 - 5
client/CServerHandler.cpp

@@ -47,7 +47,7 @@
 #include "../lib/modding/ModIncompatibility.h"
 #include "../lib/rmg/CMapGenOptions.h"
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/registerTypes/RegisterTypes.h"
+#include "../lib/registerTypes/RegisterTypesLobbyPacks.h"
 #include "../lib/serializer/Connection.h"
 #include "../lib/serializer/CMemorySerializer.h"
 
@@ -94,7 +94,7 @@ public:
 		T * ptr = static_cast<T *>(pack);
 		ApplyOnLobbyHandlerNetPackVisitor visitor(*handler);
 
-		logNetwork->trace("\tImmediately apply on lobby: %s", typeList.getTypeInfo(ptr)->name());
+		logNetwork->trace("\tImmediately apply on lobby: %s", typeid(ptr).name());
 		ptr->visit(visitor);
 
 		return visitor.getResult();
@@ -105,7 +105,7 @@ public:
 		T * ptr = static_cast<T *>(pack);
 		ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby);
 
-		logNetwork->trace("\tApply on lobby from queue: %s", typeList.getTypeInfo(ptr)->name());
+		logNetwork->trace("\tApply on lobby from queue: %s", typeid(ptr).name());
 		ptr->visit(visitor);
 	}
 };
@@ -298,7 +298,7 @@ void CServerHandler::applyPacksOnLobbyScreen()
 		boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
 		CPackForLobby * pack = packsForLobbyScreen.front();
 		packsForLobbyScreen.pop_front();
-		CBaseForLobbyApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
+		CBaseForLobbyApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
 		apply->applyOnLobbyScreen(dynamic_cast<CLobbyScreen *>(SEL), this, pack);
 		GH.windows().totalRedraw();
 		delete pack;
@@ -953,7 +953,7 @@ void CServerHandler::threadHandleConnection()
 
 void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
 {
-	if(applier->getApplier(typeList.getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
+	if(applier->getApplier(CTypeList::getInstance().getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
 	{
 		if(!settings["session"]["headless"].Bool())
 		{

+ 8 - 8
client/Client.cpp

@@ -24,6 +24,7 @@
 #include "../CCallback.h"
 #include "../lib/CConfigHandler.h"
 #include "../lib/gameState/CGameState.h"
+#include "../lib/CPlayerState.h"
 #include "../lib/CThreadHelper.h"
 #include "../lib/VCMIDirs.h"
 #include "../lib/UnlockGuard.h"
@@ -32,7 +33,7 @@
 #include "../lib/mapping/CMapService.h"
 #include "../lib/pathfinder/CGPathNode.h"
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/registerTypes/RegisterTypes.h"
+#include "../lib/registerTypes/RegisterTypesClientPacks.h"
 #include "../lib/serializer/Connection.h"
 
 #include <memory>
@@ -137,8 +138,7 @@ CClient::CClient()
 {
 	waitingRequest.clear();
 	applier = std::make_shared<CApplier<CBaseForCLApply>>();
-	registerTypesClientPacks1(*applier);
-	registerTypesClientPacks2(*applier);
+	registerTypesClientPacks(*applier);
 	IObjectInterface::cb = this;
 	gs = nullptr;
 }
@@ -523,20 +523,20 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
 
 void CClient::handlePack(CPack * pack)
 {
-	CBaseForCLApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
+	CBaseForCLApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
 	if(apply)
 	{
 		boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
 		apply->applyOnClBefore(this, pack);
-		logNetwork->trace("\tMade first apply on cl: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tMade first apply on cl: %s", typeid(pack).name());
 		gs->apply(pack);
-		logNetwork->trace("\tApplied on gs: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tApplied on gs: %s", typeid(pack).name());
 		apply->applyOnClAfter(this, pack);
-		logNetwork->trace("\tMade second apply on cl: %s", typeList.getTypeInfo(pack)->name());
+		logNetwork->trace("\tMade second apply on cl: %s", typeid(pack).name());
 	}
 	else
 	{
-		logNetwork->error("Message %s cannot be applied, cannot find applier!", typeList.getTypeInfo(pack)->name());
+		logNetwork->error("Message %s cannot be applied, cannot find applier!", typeid(pack).name());
 	}
 	delete pack;
 }

+ 4 - 0
client/mapView/mapHandler.cpp

@@ -74,6 +74,10 @@ std::string CMapHandler::getTerrainDescr(const int3 & pos, bool rightClick) cons
 
 bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b)
 {
+	//FIXME: Optimize
+	// this method is called A LOT on game start and some parts, e.g. for loops are too slow for that
+
+	assert(a && b);
 	if(!a)
 		return true;
 	if(!b)

+ 1 - 1
client/windows/CMapOverview.cpp

@@ -39,7 +39,7 @@
 #include "../../lib/TerrainHandler.h"
 #include "../../lib/filesystem/Filesystem.h"
 
-#include "../../lib/serializer/BinaryDeserializer.h"
+#include "../../lib/serializer/CLoadFile.h"
 #include "../../lib/StartInfo.h"
 #include "../../lib/rmg/CMapGenOptions.h"
 

+ 11 - 11
cmake_modules/VCMI_lib.cmake

@@ -116,6 +116,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/mapping/MapFormatJson.cpp
 		${MAIN_LIB_DIR}/mapping/ObstacleProxy.cpp
 
+		${MAIN_LIB_DIR}/modding/ActiveModsInSaveList.cpp
 		${MAIN_LIB_DIR}/modding/CModHandler.cpp
 		${MAIN_LIB_DIR}/modding/CModInfo.cpp
 		${MAIN_LIB_DIR}/modding/CModVersion.cpp
@@ -132,15 +133,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/pathfinder/PathfindingRules.cpp
 		${MAIN_LIB_DIR}/pathfinder/TurnInfo.cpp
 
-		${MAIN_LIB_DIR}/registerTypes/RegisterTypes.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesClientPacks1.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesClientPacks2.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesMapObjects1.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesMapObjects2.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesMapObjects3.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesLobbyPacks.cpp
-		${MAIN_LIB_DIR}/registerTypes/TypesServerPacks.cpp
-
 		${MAIN_LIB_DIR}/rewardable/Configuration.cpp
 		${MAIN_LIB_DIR}/rewardable/Info.cpp
 		${MAIN_LIB_DIR}/rewardable/Interface.cpp
@@ -180,9 +172,10 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 
 		${MAIN_LIB_DIR}/serializer/BinaryDeserializer.cpp
 		${MAIN_LIB_DIR}/serializer/BinarySerializer.cpp
-		${MAIN_LIB_DIR}/serializer/CLoadIntegrityValidator.cpp
+		${MAIN_LIB_DIR}/serializer/CLoadFile.cpp
 		${MAIN_LIB_DIR}/serializer/CMemorySerializer.cpp
 		${MAIN_LIB_DIR}/serializer/Connection.cpp
+		${MAIN_LIB_DIR}/serializer/CSaveFile.cpp
 		${MAIN_LIB_DIR}/serializer/CSerializer.cpp
 		${MAIN_LIB_DIR}/serializer/CTypeList.cpp
 		${MAIN_LIB_DIR}/serializer/JsonDeserializer.cpp
@@ -467,6 +460,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/mapping/MapFormatJson.h
 		${MAIN_LIB_DIR}/mapping/ObstacleProxy.h
 
+		${MAIN_LIB_DIR}/modding/ActiveModsInSaveList.h
 		${MAIN_LIB_DIR}/modding/CModHandler.h
 		${MAIN_LIB_DIR}/modding/CModInfo.h
 		${MAIN_LIB_DIR}/modding/CModVersion.h
@@ -475,6 +469,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/modding/ModIncompatibility.h
 		${MAIN_LIB_DIR}/modding/ModScope.h
 		${MAIN_LIB_DIR}/modding/ModUtility.h
+		${MAIN_LIB_DIR}/modding/ModVerificationInfo.h
 
 		${MAIN_LIB_DIR}/networkPacks/ArtifactLocation.h
 		${MAIN_LIB_DIR}/networkPacks/BattleChanges.h
@@ -503,6 +498,10 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/pathfinder/TurnInfo.h
 
 		${MAIN_LIB_DIR}/registerTypes/RegisterTypes.h
+		${MAIN_LIB_DIR}/registerTypes/RegisterTypesClientPacks.h
+		${MAIN_LIB_DIR}/registerTypes/RegisterTypesLobbyPacks.h
+		${MAIN_LIB_DIR}/registerTypes/RegisterTypesMapObjects.h
+		${MAIN_LIB_DIR}/registerTypes/RegisterTypesServerPacks.h
 
 		${MAIN_LIB_DIR}/rewardable/Configuration.h
 		${MAIN_LIB_DIR}/rewardable/Info.h
@@ -546,9 +545,10 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 
 		${MAIN_LIB_DIR}/serializer/BinaryDeserializer.h
 		${MAIN_LIB_DIR}/serializer/BinarySerializer.h
-		${MAIN_LIB_DIR}/serializer/CLoadIntegrityValidator.h
+		${MAIN_LIB_DIR}/serializer/CLoadFile.h
 		${MAIN_LIB_DIR}/serializer/CMemorySerializer.h
 		${MAIN_LIB_DIR}/serializer/Connection.h
+		${MAIN_LIB_DIR}/serializer/CSaveFile.h
 		${MAIN_LIB_DIR}/serializer/CSerializer.h
 		${MAIN_LIB_DIR}/serializer/CTypeList.h
 		${MAIN_LIB_DIR}/serializer/JsonDeserializer.h

+ 2 - 0
include/vcmi/Entity.h

@@ -50,6 +50,8 @@ template <typename IdType>
 class DLL_LINKAGE EntityT : public Entity
 {
 public:
+	using IdentifierType = IdType;
+
 	virtual IdType getId() const = 0;
 };
 

+ 0 - 18
lib/BattleFieldHandler.h

@@ -53,19 +53,6 @@ public:
 	std::string getNameTranslated() const override;
 	void registerIcons(const IconRegistar & cb) const override;
 	BattleField getId() const override;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & name;
-		h & identifier;
-		h & isSpecial;
-		h & graphics;
-		h & icon;
-		h & iconIndex;
-		h & battlefield;
-		h & impassableHexes;
-
-	}
 };
 
 class DLL_LINKAGE BattleFieldService : public EntityServiceT<BattleField, BattleFieldInfo>
@@ -85,11 +72,6 @@ public:
 	virtual const std::vector<std::string> & getTypeNames() const override;
 	virtual std::vector<JsonNode> loadLegacyData() override;
 	virtual std::vector<bool> getDefaultAllowed() const override;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 70
lib/CArtHandler.cpp

@@ -607,75 +607,6 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
 	}
 }
 
-ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts)
-{
-	std::set<ArtifactID> potentialPicks;
-
-	// Select artifacts that satisfy provided criterias
-	for (auto const * artifact : allowedArtifacts)
-	{
-		assert(artifact->aClass != CArtifact::ART_SPECIAL); // should be filtered out when allowedArtifacts is initialized
-
-		if ((flags & CArtifact::ART_TREASURE) == 0 && artifact->aClass == CArtifact::ART_TREASURE)
-			continue;
-
-		if ((flags & CArtifact::ART_MINOR) == 0 && artifact->aClass == CArtifact::ART_MINOR)
-			continue;
-
-		if ((flags & CArtifact::ART_MAJOR) == 0 && artifact->aClass == CArtifact::ART_MAJOR)
-			continue;
-
-		if ((flags & CArtifact::ART_RELIC) == 0 && artifact->aClass == CArtifact::ART_RELIC)
-			continue;
-
-		if (!accepts(artifact->id))
-			continue;
-
-		potentialPicks.insert(artifact->id);
-	}
-
-	return pickRandomArtifact(rand, potentialPicks);
-}
-
-ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, std::set<ArtifactID> potentialPicks)
-{
-	// No allowed artifacts at all - give Grail - this can't be banned (hopefully)
-	// FIXME: investigate how such cases are handled by H3 - some heavily customized user-made maps likely rely on H3 behavior
-	if (potentialPicks.empty())
-	{
-		logGlobal->warn("Failed to find artifact that matches requested parameters!");
-		return ArtifactID::GRAIL;
-	}
-
-	// Find how many times least used artifacts were picked by randomizer
-	int leastUsedTimes = std::numeric_limits<int>::max();
-	for (auto const & artifact : potentialPicks)
-		if (allocatedArtifacts[artifact] < leastUsedTimes)
-			leastUsedTimes = allocatedArtifacts[artifact];
-
-	// Pick all artifacts that were used least number of times
-	std::set<ArtifactID> preferredPicks;
-	for (auto const & artifact : potentialPicks)
-		if (allocatedArtifacts[artifact] == leastUsedTimes)
-			preferredPicks.insert(artifact);
-
-	assert(!preferredPicks.empty());
-
-	ArtifactID artID = *RandomGeneratorUtil::nextItem(preferredPicks, rand);
-	allocatedArtifacts[artID] += 1; // record +1 more usage
-	return artID;
-}
-
-ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts)
-{
-	return pickRandomArtifact(rand, 0xff, std::move(accepts));
-}
-
-ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
-{
-	return pickRandomArtifact(rand, flags, [](const ArtifactID &) { return true; });
-}
-
 void CArtHandler::makeItCreatureArt(CArtifact * a, bool onlyCreature)
 {
 	if (onlyCreature)
@@ -723,7 +654,6 @@ bool CArtHandler::legalArtifact(const ArtifactID & id)
 void CArtHandler::initAllowedArtifactsList(const std::vector<bool> &allowed)
 {
 	allowedArtifacts.clear();
-	allocatedArtifacts.clear();
 
 	for (ArtifactID i=ArtifactID::SPELLBOOK; i < ArtifactID(static_cast<si32>(objects.size())); i.advance(1))
 	{

+ 0 - 47
lib/CArtHandler.h

@@ -53,12 +53,6 @@ public:
 	bool isCombined() const;
 	const std::vector<CArtifact*> & getConstituents() const;
 	const std::vector<CArtifact*> & getPartOf() const;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & constituents;
-		h & partOf;
-	}
 };
 
 class DLL_LINKAGE CScrollArtifact
@@ -83,12 +77,6 @@ public:
 	const std::vector <std::pair<ui16, Bonus>> & getBonusesPerLevel() const;
 	std::vector <std::pair<ui16, Bonus>> & getThresholdBonuses();
 	const std::vector <std::pair<ui16, Bonus>> & getThresholdBonuses() const;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & bonusesPerLevel;
-		h & thresholdBonuses;
-	}
 };
 
 // Container for artifacts. Not for instances.
@@ -144,25 +132,6 @@ public:
 	// Is used for testing purposes only
 	void setImage(int32_t iconIndex, std::string image, std::string large);
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & static_cast<CBonusSystemNode&>(*this);
-		h & static_cast<CCombinedArtifact&>(*this);
-		h & static_cast<CGrowingArtifact&>(*this);
-		h & image;
-		h & large;
-		h & advMapDef;
-		h & iconIndex;
-		h & price;
-		h & possibleSlots;
-		h & aClass;
-		h & id;
-		h & modScope;
-		h & identifier;
-		h & warMachine;
-		h & onlyOnWaterMap;
-	}
-
 	CArtifact();
 	~CArtifact();
 
@@ -172,9 +141,6 @@ public:
 class DLL_LINKAGE CArtHandler : public CHandlerBase<ArtifactID, Artifact, CArtifact, ArtifactService>
 {
 public:
-	/// Stores number of times each artifact was placed on map via randomization
-	std::map<ArtifactID, int> allocatedArtifacts;
-
 	/// List of artifacts allowed on the map
 	std::vector<CArtifact *> allowedArtifacts;
 
@@ -182,12 +148,6 @@ public:
 
 	static CArtifact::EartClass stringToClass(const std::string & className); //TODO: rework EartClass to make this a constructor
 
-	/// Gets a artifact ID randomly and removes the selected artifact from this handler.
-	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
-	ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts);
-	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts);
-	ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::set<ArtifactID> filtered);
-
 	bool legalArtifact(const ArtifactID & id);
 	void initAllowedArtifactsList(const std::vector<bool> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
 	static void makeItCreatureArt(CArtifact * a, bool onlyCreature = true);
@@ -203,13 +163,6 @@ public:
 
 	std::vector<bool> getDefaultAllowed() const override;
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & objects;
-		h & allowedArtifacts;
-		h & allocatedArtifacts;
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CArtifact * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;

+ 1 - 78
lib/CCreatureHandler.h

@@ -83,11 +83,6 @@ public:
 		struct RayColor {
 			ColorRGBA start;
 			ColorRGBA end;
-
-			template <typename Handler> void serialize(Handler &h, const int version)
-			{
-				h & start & end;
-			}
 		};
 
 		double timeBetweenFidgets, idleAnimationTime,
@@ -100,25 +95,7 @@ public:
 
 		AnimationPath projectileImageName;
 		std::vector<RayColor> projectileRay;
-		//bool projectileSpin; //if true, appropriate projectile is spinning during flight
-
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & timeBetweenFidgets;
-			h & idleAnimationTime;
-			h & walkAnimationTime;
-			h & attackAnimationTime;
-			h & upperRightMissleOffsetX;
-			h & rightMissleOffsetX;
-			h & lowerRightMissleOffsetX;
-			h & upperRightMissleOffsetY;
-			h & rightMissleOffsetY;
-			h & lowerRightMissleOffsetY;
-			h & missleFrameAngles;
-			h & attackClimaxFrame;
-			h & projectileImageName;
-			h & projectileRay;
-		}
+
 	} animation;
 
 	//sound info
@@ -132,18 +109,6 @@ public:
 		AudioPath wince; // attacked but did not die
 		AudioPath startMoving;
 		AudioPath endMoving;
-
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & attack;
-			h & defend;
-			h & killed;
-			h & move;
-			h & shoot;
-			h & wince;
-			h & startMoving;
-			h & endMoving;
-		}
 	} sounds;
 
 	ArtifactID warMachine;
@@ -210,35 +175,6 @@ public:
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<CBonusSystemNode&>(*this);
-		h & cost;
-		h & upgrades;
-		h & fightValue;
-		h & AIValue;
-		h & growth;
-		h & hordeGrowth;
-		h & ammMin;
-		h & ammMax;
-		h & level;
-		h & animDefName;
-		h & iconIndex;
-		h & smallIconName;
-		h & largeIconName;
-
-		h & idNumber;
-		h & faction;
-		h & sounds;
-		h & animation;
-
-		h & doubleWide;
-		h & special;
-		h & identifier;
-		h & modScope;
-		h & warMachine;
-	}
-
 	CCreature();
 
 private:
@@ -303,19 +239,6 @@ public:
 	std::vector<JsonNode> loadLegacyData() override;
 
 	std::vector<bool> getDefaultAllowed() const override;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		//TODO: should be optimized, not all these informations needs to be serialized (same for ccreature)
-		h & doubledCreatures;
-		h & objects;
-		h & expRanks;
-		h & maxExpPerBattle;
-		h & expAfterUpgrade;
-		h & skillLevels;
-		h & skillRequirements;
-		h & commanderLevelPremy;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 61
lib/CHeroHandler.h

@@ -52,13 +52,6 @@ public:
 		ui32 minAmount;
 		ui32 maxAmount;
 		CreatureID creature;
-
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & minAmount;
-			h & maxAmount;
-			h & creature;
-		}
 	};
 	si32 imageIndex = 0;
 
@@ -104,29 +97,6 @@ public:
 
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & ID;
-		h & imageIndex;
-		h & initialArmy;
-		h & heroClass;
-		h & secSkillsInit;
-		h & specialty;
-		h & spells;
-		h & haveSpellBook;
-		h & gender;
-		h & special;
-		h & onlyOnWaterMap;
-		h & onlyOnMapWithoutWater;
-		h & iconSpecSmall;
-		h & iconSpecLarge;
-		h & portraitSmall;
-		h & portraitLarge;
-		h & identifier;
-		h & modScope;
-		h & battleImage;
-	}
 };
 
 class DLL_LINKAGE CHeroClass : public HeroClass
@@ -183,25 +153,6 @@ public:
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & modScope;
-		h & identifier;
-		h & faction;
-		h & id;
-		h & defaultTavernChance;
-		h & primarySkillInitial;
-		h & primarySkillLowLevel;
-		h & primarySkillHighLevel;
-		h & secSkillProbability;
-		h & selectionProbability;
-		h & affinity;
-		h & commander;
-		h & imageBattleMale;
-		h & imageBattleFemale;
-		h & imageMapMale;
-		h & imageMapFemale;
-	}
 	EAlignment getAlignment() const;
 };
 
@@ -218,11 +169,6 @@ public:
 
 	~CHeroClassHandler();
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & objects;
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CHeroClass * loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override;
@@ -262,13 +208,6 @@ public:
 
 	std::vector<bool> getDefaultAllowed() const override;
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & classes;
-		h & objects;
-		h & expPerLevel;
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CHero * loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override;

+ 0 - 24
lib/CSkillHandler.h

@@ -29,14 +29,6 @@ public:
 		std::string iconMedium;
 		std::string iconLarge;
 		std::vector<std::shared_ptr<Bonus>> effects;
-
-		template <typename Handler> void serialize(Handler & h, const int version)
-		{
-			h & iconSmall;
-			h & iconMedium;
-			h & iconLarge;
-			h & effects;
-		}
 	};
 
 private:
@@ -82,17 +74,6 @@ public:
 
 	bool onlyOnWaterMap;
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & id;
-		h & identifier;
-		h & gainChance;
-		h & levels;
-		h & obligatoryMajor;
-		h & obligatoryMinor;
-		h & onlyOnWaterMap;
-	}
-
 	friend class CSkillHandler;
 	friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill & skill);
 	friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill::LevelInfo & info);
@@ -111,11 +92,6 @@ public:
 
 	std::vector<bool> getDefaultAllowed() const override;
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CSkill * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;

+ 0 - 96
lib/CTownHandler.h

@@ -123,25 +123,6 @@ public:
 
 	void addNewBonus(const std::shared_ptr<Bonus> & b, BonusList & bonusList) const;
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & modScope;
-		h & identifier;
-		h & town;
-		h & bid;
-		h & resources;
-		h & produce;
-		h & requirements;
-		h & upgrade;
-		h & mode;
-		h & subId;
-		h & height;
-		h & overrideBids;
-		h & buildingBonuses;
-		h & onVisitBonuses;
-		h & rewardableObjectInfo;
-	}
-
 	friend class CTownHandler;
 };
 
@@ -160,17 +141,6 @@ struct DLL_LINKAGE CStructure
 	std::string identifier;
 
 	bool hiddenUpgrade; // used only if "building" is upgrade, if true - structure on town screen will behave exactly like parent (mouse clicks, hover texts, etc)
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & pos;
-		h & defName;
-		h & borderName;
-		h & areaName;
-		h & identifier;
-		h & building;
-		h & buildable;
-		h & hiddenUpgrade;
-	}
 };
 
 struct DLL_LINKAGE SPuzzleInfo
@@ -179,15 +149,6 @@ struct DLL_LINKAGE SPuzzleInfo
 	si16 x, y; //position
 	ui16 whenUncovered; //determines the sequnce of discovering (the lesser it is the sooner puzzle will be discovered)
 	ImagePath filename; //file with graphic of this puzzle
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & number;
-		h & x;
-		h & y;
-		h & whenUncovered;
-		h & filename;
-	}
 };
 
 class DLL_LINKAGE CFaction : public Faction
@@ -238,20 +199,6 @@ public:
 
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & modScope;
-		h & identifier;
-		h & index;
-		h & nativeTerrain;
-		h & boatType;
-		h & alignment;
-		h & town;
-		h & creatureBg120;
-		h & creatureBg130;
-		h & puzzleMap;
-	}
 };
 
 class DLL_LINKAGE CTown
@@ -323,44 +270,7 @@ public:
 		std::string towerIconSmall;
 		std::string towerIconLarge;
 
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & icons;
-			h & iconSmall;
-			h & iconLarge;
-			h & tavernVideo;
-			h & musicTheme;
-			h & townBackground;
-			h & guildBackground;
-			h & guildWindow;
-			h & buildingsIcons;
-			h & hallBackground;
-			h & hallSlots;
-			h & structures;
-			h & siegePrefix;
-			h & siegePositions;
-			h & siegeShooter;
-			h & towerIconSmall;
-			h & towerIconLarge;
-		}
 	} clientInfo;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & namesCount;
-		h & faction;
-		h & creatures;
-		h & dwellings;
-		h & dwellingNames;
-		h & buildings;
-		h & hordeLvl;
-		h & mageLevel;
-		h & primaryRes;
-		h & warMachine;
-		h & clientInfo;
-		h & moatAbility;
-		h & defaultTavernChance;
-	}
 	
 private:
 	///generated bonusing buildings messages for all towns of this type.
@@ -445,12 +355,6 @@ public:
 
 	static void loadSpecialBuildingBonuses(const JsonNode & source, BonusList & bonusList, CBuilding * building);
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & objects;
-		h & randomTown;
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CFaction * loadFromJson(const std::string & scope, const JsonNode & data, const std::string & identifier, size_t index) override;

+ 14 - 13
lib/IGameCallback.cpp

@@ -21,10 +21,8 @@
 #include "bonuses/Propagators.h"
 #include "bonuses/Updaters.h"
 
-#include "serializer/CSerializer.h" // for SAVEGAME_MAGIC
-#include "serializer/BinaryDeserializer.h"
-#include "serializer/BinarySerializer.h"
-#include "serializer/CLoadIntegrityValidator.h"
+#include "serializer/CLoadFile.h"
+#include "serializer/CSaveFile.h"
 #include "rmg/CMapGenOptions.h"
 #include "mapObjectConstructors/AObjectTypeHandler.h"
 #include "mapObjectConstructors/CObjectClassesHandler.h"
@@ -41,6 +39,7 @@
 #include "modding/CModInfo.h"
 #include "modding/IdentifierStorage.h"
 #include "modding/CModVersion.h"
+#include "modding/ActiveModsInSaveList.h"
 #include "CPlayerState.h"
 #include "GameSettings.h"
 #include "ScriptHandler.h"
@@ -145,14 +144,14 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std:
 	}
 }
 
-void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand) const
+void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand)
 {
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE).toArtifact());
+		out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE).toArtifact());
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR).toArtifact());
+		out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_MINOR).toArtifact());
 
-	out.push_back(VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR).toArtifact());
+	out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_MAJOR).toArtifact());
 }
 
 void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level)
@@ -184,6 +183,7 @@ void CPrivilegedInfoCallback::loadCommonState(Loader & in)
 
 	CMapHeader dum;
 	StartInfo * si = nullptr;
+	ActiveModsInSaveList activeMods;
 
 	logGlobal->info("\tReading header");
 	in.serializer & dum;
@@ -191,8 +191,8 @@ void CPrivilegedInfoCallback::loadCommonState(Loader & in)
 	logGlobal->info("\tReading options");
 	in.serializer & si;
 
-	logGlobal->info("\tReading handlers");
-	in.serializer & *VLC;
+	logGlobal->info("\tReading mod list");
+	in.serializer & activeMods;
 
 	logGlobal->info("\tReading gamestate");
 	in.serializer & gs;
@@ -201,20 +201,21 @@ void CPrivilegedInfoCallback::loadCommonState(Loader & in)
 template<typename Saver>
 void CPrivilegedInfoCallback::saveCommonState(Saver & out) const
 {
+	ActiveModsInSaveList activeMods;
+
 	logGlobal->info("Saving lib part of game...");
 	out.putMagicBytes(SAVEGAME_MAGIC);
 	logGlobal->info("\tSaving header");
 	out.serializer & static_cast<CMapHeader&>(*gs->map);
 	logGlobal->info("\tSaving options");
 	out.serializer & gs->scenarioOps;
-	logGlobal->info("\tSaving handlers");
-	out.serializer & *VLC;
+	logGlobal->info("\tSaving mod list");
+	out.serializer & activeMods;
 	logGlobal->info("\tSaving gamestate");
 	out.serializer & gs;
 }
 
 // hardly memory usage for `-gdwarf-4` flag
-template DLL_LINKAGE void CPrivilegedInfoCallback::loadCommonState<CLoadIntegrityValidator>(CLoadIntegrityValidator &);
 template DLL_LINKAGE void CPrivilegedInfoCallback::loadCommonState<CLoadFile>(CLoadFile &);
 template DLL_LINKAGE void CPrivilegedInfoCallback::saveCommonState<CSaveFile>(CSaveFile &) const;
 

+ 1 - 1
lib/IGameCallback.h

@@ -61,7 +61,7 @@ public:
 	void getAllTiles(std::unordered_set<int3> &tiles, std::optional<PlayerColor> player, int level, std::function<bool(const TerrainTile *)> filter) const;
 
 	//gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
-	void pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand) const; 
+	void pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand);
 	void getAllowedSpells(std::vector<SpellID> &out, std::optional<ui16> level = std::nullopt);
 
 	template<typename Saver>

+ 2 - 2
lib/JsonNode.h

@@ -247,8 +247,8 @@ namespace JsonDetail
 		static Type convert(const JsonNode & node)
 		{
 			///this should be triggered only for numeric types and enums
-			static_assert(boost::mpl::or_<std::is_arithmetic<Type>, std::is_enum<Type>, boost::is_class<Type> >::value, "Unsupported type for JsonNode::convertTo()!");
-			return JsonConvImpl<Type, boost::mpl::or_<std::is_enum<Type>, boost::is_class<Type> >::value >::convertImpl(node);
+			static_assert(std::is_arithmetic_v<Type> || std::is_enum_v<Type> || std::is_class_v<Type>, "Unsupported type for JsonNode::convertTo()!");
+			return JsonConvImpl<Type, std::is_enum_v<Type> || std::is_class_v<Type> >::convertImpl(node);
 
 		}
 	};

+ 2 - 1
lib/JsonRandom.cpp

@@ -24,6 +24,7 @@
 #include "CSkillHandler.h"
 #include "CHeroHandler.h"
 #include "IGameCallback.h"
+#include "gameState/CGameState.h"
 #include "mapObjects/IObjectInterface.h"
 #include "modding/IdentifierStorage.h"
 #include "modding/ModScope.h"
@@ -388,7 +389,7 @@ namespace JsonRandom
 
 		std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts, variables);
 
-		return VLC->arth->pickRandomArtifact(rng, potentialPicks);
+		return IObjectInterface::cb->gameState()->pickRandomArtifact(rng, potentialPicks);
 	}
 
 	std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)

+ 0 - 22
lib/ObstacleHandler.h

@@ -54,23 +54,6 @@ public:
 	std::vector<BattleHex> getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex'
 	
 	bool isAppropriate(const TerrainId terrainType, const BattleField & specialBattlefield) const;
-	
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & obstacle;
-		h & iconIndex;
-		h & identifier;
-		h & animation;
-		h & appearAnimation;
-		h & appearSound;
-		h & allowedTerrains;
-		h & allowedSpecialBfields;
-		h & isAbsoluteObstacle;
-		h & isForegroundObstacle;
-		h & width;
-		h & height;
-		h & blockedTiles;
-	}
 };
 
 class DLL_LINKAGE ObstacleService : public EntityServiceT<Obstacle, ObstacleInfo>
@@ -89,11 +72,6 @@ public:
 	const std::vector<std::string> & getTypeNames() const override;
 	std::vector<JsonNode> loadLegacyData() override;
 	std::vector<bool> getDefaultAllowed() const override;
-	
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 21
lib/RiverHandler.h

@@ -24,12 +24,6 @@ struct DLL_LINKAGE RiverPaletteAnimation
 	int32_t start;
 	/// total numbers of colors to cycle
 	int32_t length;
-
-	template <typename Handler> void serialize(Handler& h, const int version)
-	{
-		h & start;
-		h & length;
-	}
 };
 
 class DLL_LINKAGE RiverType : public EntityT<RiverId>
@@ -57,16 +51,6 @@ public:
 	std::vector<RiverPaletteAnimation> paletteAnimation;
 
 	RiverType();
-
-	template <typename Handler> void serialize(Handler& h, const int version)
-	{
-		h & tilesFilename;
-		h & identifier;
-		h & modScope;
-		h & deltaName;
-		h & id;
-		h & paletteAnimation;
-	}
 };
 
 class DLL_LINKAGE RiverTypeService : public EntityServiceT<RiverId, RiverType>
@@ -88,11 +72,6 @@ public:
 	virtual const std::vector<std::string> & getTypeNames() const override;
 	virtual std::vector<JsonNode> loadLegacyData() override;
 	virtual std::vector<bool> getDefaultAllowed() const override;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 14
lib/RoadHandler.h

@@ -41,15 +41,6 @@ public:
 	ui8 movementCost;
 
 	RoadType();
-
-	template <typename Handler> void serialize(Handler& h, const int version)
-	{
-		h & tilesFilename;
-		h & identifier;
-		h & modScope;
-		h & id;
-		h & movementCost;
-	}
 };
 
 class DLL_LINKAGE RoadTypeService : public EntityServiceT<RoadId, RoadType>
@@ -71,11 +62,6 @@ public:
 	virtual const std::vector<std::string> & getTypeNames() const override;
 	virtual std::vector<JsonNode> loadLegacyData() override;
 	virtual std::vector<bool> getDefaultAllowed() const override;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 29
lib/TerrainHandler.h

@@ -91,30 +91,6 @@ public:
 	bool isSurface() const;
 	bool isUnderground() const;
 	bool isTransitionRequired() const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & battleFields;
-		h & prohibitTransitions;
-		h & minimapBlocked;
-		h & minimapUnblocked;
-		h & modScope;
-		h & identifier;
-		h & musicFilename;
-		h & tilesFilename;
-		h & shortIdentifier;
-		h & terrainViewPatterns;
-		h & rockTerrain;
-		h & river;
-		h & paletteAnimation;
-
-		h & id;
-		h & moveCost;
-		h & horseSound;
-		h & horseSoundPenalty;
-		h & passabilityType;
-		h & transitionRequired;
-	}
 };
 
 class DLL_LINKAGE TerrainTypeService : public EntityServiceT<TerrainId, TerrainType>
@@ -134,11 +110,6 @@ public:
 	virtual const std::vector<std::string> & getTypeNames() const override;
 	virtual std::vector<JsonNode> loadLegacyData() override;
 	virtual std::vector<bool> getDefaultAllowed() const override;
-
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 45
lib/VCMI_Lib.h

@@ -120,51 +120,6 @@ public:
 #if SCRIPTING_ENABLED
 	void scriptsLoaded();
 #endif
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & identifiersHandler; // must be first - identifiers registry is used for handlers loading
-#if SCRIPTING_ENABLED
-		h & scriptHandler;//must be first (or second after identifiers), it can modify factories other handlers depends on
-		if(!h.saving)
-		{
-			scriptsLoaded();
-		}
-#endif
-
-		h & settingsHandler;
-		h & heroh;
-		h & arth;
-		h & creh;
-		h & townh;
-		h & objh;
-		h & objtypeh;
-		h & spellh;
-		h & skillh;
-		h & battlefieldsHandler;
-		h & obstacleHandler;
-		h & roadTypeHandler;
-		h & riverTypeHandler;
-		h & terrainTypeHandler;
-
-		if(!h.saving)
-		{
-			//modh will be changed and modh->content will be empty after deserialization
-			auto content = getContent();
-			h & modh;
-			setContent(content);
-		}
-		else
-			h & modh;
-
-		h & IS_AI_ENABLED;
-		h & bth;
-
-		if(!h.saving)
-		{
-			callWhenDeserializing();
-		}
-	}
 };
 
 extern DLL_LINKAGE LibClasses * VLC;

+ 1 - 1
lib/bonuses/BonusSelector.h

@@ -22,7 +22,7 @@ public:
 	template<typename T>
 	CSelector(const T &t,	//SFINAE trick -> include this c-tor in overload resolution only if parameter is class
 							//(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
-		typename std::enable_if < boost::mpl::or_ < std::is_class<T>, std::is_function<T >> ::value>::type *dummy = nullptr)
+		typename std::enable_if_t < std::is_class_v<T> || std::is_function_v<T> > *dummy = nullptr)
 		: TBase(t)
 	{}
 

+ 22 - 0
lib/constants/EntityIdentifiers.cpp

@@ -37,6 +37,8 @@
 #include "constants/StringConstants.h"
 #include "CGeneralTextHandler.h"
 #include "TerrainHandler.h" //TODO: remove
+#include "RiverHandler.h"
+#include "RoadHandler.h"
 #include "BattleFieldHandler.h"
 #include "ObstacleHandler.h"
 #include "CTownHandler.h"
@@ -404,6 +406,11 @@ std::string FactionID::entityType()
 	return "faction";
 }
 
+const Faction * FactionID::toEntity(const Services * service) const
+{
+	return service->factions()->getByIndex(num);
+}
+
 si32 TerrainId::decode(const std::string & identifier)
 {
 	auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier);
@@ -423,6 +430,21 @@ std::string TerrainId::entityType()
 	return "terrain";
 }
 
+const TerrainType * TerrainId::toEntity(const Services * service) const
+{
+	return VLC->terrainTypeHandler->getByIndex(num);
+}
+
+const RoadType * RoadId::toEntity(const Services * service) const
+{
+	return VLC->roadTypeHandler->getByIndex(num);
+}
+
+const RiverType * RiverId::toEntity(const Services * service) const
+{
+	return VLC->riverTypeHandler->getByIndex(num);
+}
+
 const BattleField BattleField::NONE;
 
 const BattleFieldInfo * BattleField::getInfo() const

+ 15 - 5
lib/constants/EntityIdentifiers.h

@@ -22,6 +22,10 @@ class CreatureService;
 class HeroType;
 class CHero;
 class HeroTypeService;
+class Faction;
+class RoadType;
+class RiverType;
+class TerrainType;
 
 namespace spells
 {
@@ -181,20 +185,20 @@ public:
 	static std::string entityType();
 };
 
-class HeroTypeID : public Identifier<HeroTypeID>
+class DLL_LINKAGE HeroTypeID : public Identifier<HeroTypeID>
 {
 public:
 	using Identifier<HeroTypeID>::Identifier;
 	///json serialization helpers
-	DLL_LINKAGE static si32 decode(const std::string & identifier);
-	DLL_LINKAGE static std::string encode(const si32 index);
+	static si32 decode(const std::string & identifier);
+	static std::string encode(const si32 index);
 	static std::string entityType();
 
 	const CHero * toHeroType() const;
 	const HeroType * toEntity(const Services * services) const;
 
-	DLL_LINKAGE static const HeroTypeID NONE;
-	DLL_LINKAGE static const HeroTypeID RANDOM;
+	static const HeroTypeID NONE;
+	static const HeroTypeID RANDOM;
 
 	bool isValid() const
 	{
@@ -349,6 +353,7 @@ public:
 
 	static si32 decode(const std::string& identifier);
 	static std::string encode(const si32 index);
+	const Faction * toEntity(const Services * service) const;
 	static std::string entityType();
 
 	bool isValid() const
@@ -596,6 +601,8 @@ public:
 	static const RoadId DIRT_ROAD;
 	static const RoadId GRAVEL_ROAD;
 	static const RoadId COBBLESTONE_ROAD;
+
+	const RoadType * toEntity(const Services * service) const;
 };
 
 class DLL_LINKAGE RiverId : public Identifier<RiverId>
@@ -608,6 +615,8 @@ public:
 	static const RiverId ICY_RIVER;
 	static const RiverId MUD_RIVER;
 	static const RiverId LAVA_RIVER;
+
+	const RiverType * toEntity(const Services * service) const;
 };
 
 class DLL_LINKAGE EPathfindingLayerBase : public IdentifierBase
@@ -912,6 +921,7 @@ public:
 	DLL_LINKAGE static si32 decode(const std::string & identifier);
 	DLL_LINKAGE static std::string encode(const si32 index);
 	static std::string entityType();
+	const TerrainType * toEntity(const Services * service) const;
 };
 
 class ObstacleInfo;

+ 74 - 8
lib/gameState/CGameState.cpp

@@ -42,7 +42,7 @@
 #include "../modding/IdentifierStorage.h"
 #include "../pathfinder/CPathfinder.h"
 #include "../pathfinder/PathfinderOptions.h"
-#include "../registerTypes/RegisterTypes.h"
+#include "../registerTypes/RegisterTypesClientPacks.h"
 #include "../rmg/CMapGenerator.h"
 #include "../serializer/CMemorySerializer.h"
 #include "../serializer/CTypeList.h"
@@ -157,8 +157,7 @@ CGameState::CGameState()
 	gs = this;
 	heroesPool = std::make_unique<TavernHeroesPool>();
 	applier = std::make_shared<CApplier<CBaseForGSApply>>();
-	registerTypesClientPacks1(*applier);
-	registerTypesClientPacks2(*applier);
+	registerTypesClientPacks(*applier);
 	globalEffects.setNodeType(CBonusSystemNode::GLOBAL_EFFECTS);
 }
 
@@ -760,7 +759,7 @@ void CGameState::initStartingBonus()
 					logGlobal->error("Cannot give starting artifact - no heroes!");
 					break;
 				}
-				const Artifact * toGive = VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toEntity(VLC);
+				const Artifact * toGive = pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toEntity(VLC);
 
 				CGHeroInstance *hero = elem.second.heroes[0];
 				if(!giveHeroArtifact(hero, toGive->getId()))
@@ -921,11 +920,9 @@ void CGameState::initMapObjects()
 	for(CGObjectInstance *obj : map->objects)
 	{
 		if(obj)
-		{
-			logGlobal->trace("Calling Init for object %d, %s, %s", obj->id.getNum(), obj->typeName, obj->subTypeName);
 			obj->initObj(getRandomGenerator());
-		}
 	}
+	logGlobal->debug("\tObject initialization done");
 	for(CGObjectInstance *obj : map->objects)
 	{
 		if(!obj)
@@ -1136,7 +1133,7 @@ PlayerRelations CGameState::getPlayerRelations( PlayerColor color1, PlayerColor
 
 void CGameState::apply(CPack *pack)
 {
-	ui16 typ = typeList.getTypeID(pack);
+	ui16 typ = CTypeList::getInstance().getTypeID(pack);
 	applier->getApplier(typ)->applyOnGS(this, pack);
 }
 
@@ -1971,4 +1968,73 @@ CRandomGenerator & CGameState::getRandomGenerator()
 	return rand;
 }
 
+ArtifactID CGameState::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts)
+{
+	std::set<ArtifactID> potentialPicks;
+
+	// Select artifacts that satisfy provided criterias
+	for (auto const * artifact : VLC->arth->allowedArtifacts)
+	{
+		assert(artifact->aClass != CArtifact::ART_SPECIAL); // should be filtered out when allowedArtifacts is initialized
+
+		if ((flags & CArtifact::ART_TREASURE) == 0 && artifact->aClass == CArtifact::ART_TREASURE)
+			continue;
+
+		if ((flags & CArtifact::ART_MINOR) == 0 && artifact->aClass == CArtifact::ART_MINOR)
+			continue;
+
+		if ((flags & CArtifact::ART_MAJOR) == 0 && artifact->aClass == CArtifact::ART_MAJOR)
+			continue;
+
+		if ((flags & CArtifact::ART_RELIC) == 0 && artifact->aClass == CArtifact::ART_RELIC)
+			continue;
+
+		if (!accepts(artifact->getId()))
+			continue;
+
+		potentialPicks.insert(artifact->getId());
+	}
+
+	return pickRandomArtifact(rand, potentialPicks);
+}
+
+ArtifactID CGameState::pickRandomArtifact(CRandomGenerator & rand, std::set<ArtifactID> potentialPicks)
+{
+	// No allowed artifacts at all - give Grail - this can't be banned (hopefully)
+	// FIXME: investigate how such cases are handled by H3 - some heavily customized user-made maps likely rely on H3 behavior
+	if (potentialPicks.empty())
+	{
+		logGlobal->warn("Failed to find artifact that matches requested parameters!");
+		return ArtifactID::GRAIL;
+	}
+
+	// Find how many times least used artifacts were picked by randomizer
+	int leastUsedTimes = std::numeric_limits<int>::max();
+	for (auto const & artifact : potentialPicks)
+		if (allocatedArtifacts[artifact] < leastUsedTimes)
+			leastUsedTimes = allocatedArtifacts[artifact];
+
+	// Pick all artifacts that were used least number of times
+	std::set<ArtifactID> preferredPicks;
+	for (auto const & artifact : potentialPicks)
+		if (allocatedArtifacts[artifact] == leastUsedTimes)
+			preferredPicks.insert(artifact);
+
+	assert(!preferredPicks.empty());
+
+	ArtifactID artID = *RandomGeneratorUtil::nextItem(preferredPicks, rand);
+	allocatedArtifacts[artID] += 1; // record +1 more usage
+	return artID;
+}
+
+ArtifactID CGameState::pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts)
+{
+	return pickRandomArtifact(rand, 0xff, std::move(accepts));
+}
+
+ArtifactID CGameState::pickRandomArtifact(CRandomGenerator & rand, int flags)
+{
+	return pickRandomArtifact(rand, flags, [](const ArtifactID &) { return true; });
+}
+
 VCMI_LIB_NAMESPACE_END

+ 10 - 0
lib/gameState/CGameState.h

@@ -83,6 +83,9 @@ class DLL_LINKAGE CGameState : public CNonConstInfoCallback
 	friend class CGameStateCampaign;
 
 public:
+	/// Stores number of times each artifact was placed on map via randomization
+	std::map<ArtifactID, int> allocatedArtifacts;
+
 	/// List of currently ongoing battles
 	std::vector<std::unique_ptr<BattleInfo>> currentBattles;
 	/// ID that can be allocated to next battle
@@ -130,6 +133,12 @@ public:
 	std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
 	void updateRumor();
 
+	/// Gets a artifact ID randomly and removes the selected artifact from this handler.
+	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
+	ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts);
+	ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts);
+	ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::set<ArtifactID> filtered);
+
 	/// Returns battle in which selected player is engaged, or nullptr if none.
 	/// Can NOT be used with neutral player, use battle by ID instead
 	const BattleInfo * getBattle(const PlayerColor & player) const;
@@ -176,6 +185,7 @@ public:
 		h & rand;
 		h & rumor;
 		h & campaign;
+		h & allocatedArtifacts;
 
 		BONUS_TREE_DESERIALIZATION_FIX
 	}

+ 1 - 1
lib/gameState/CGameStateCampaign.cpp

@@ -16,7 +16,7 @@
 #include "../campaign/CampaignState.h"
 #include "../mapping/CMapEditManager.h"
 #include "../mapObjects/CGHeroInstance.h"
-#include "../registerTypes/RegisterTypes.h"
+#include "../networkPacks/ArtifactLocation.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../StartInfo.h"

+ 0 - 14
lib/mapObjectConstructors/AObjectTypeHandler.h

@@ -112,20 +112,6 @@ public:
 
 	/// Returns object configuration, if available. Otherwise returns NULL
 	virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & type;
-		h & subtype;
-		h & templates;
-		h & rmgInfo;
-		h & modScope;
-		h & typeName;
-		h & subTypeName;
-		h & sounds;
-		h & aiValue;
-		h & battlefield;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 9
lib/mapObjectConstructors/CBankInstanceConstructor.h

@@ -92,15 +92,6 @@ public:
 	bool hasNameTextID() const override;
 
 	std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & levels;
-		h & bankResetDuration;
-		h & blockVisit;
-		h & coastVisitable;
-		h & static_cast<CDefaultObjectTypeHandler<CBank>&>(*this);
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 15
lib/mapObjectConstructors/CObjectClassesHandler.h

@@ -62,16 +62,6 @@ public:
 	std::string getJsonKey() const;
 	std::string getNameTextID() const;
 	std::string getNameTranslated() const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & id;
-		h & handlerName;
-		h & base;
-		h & objects;
-		h & identifier;
-		h & modScope;
-	}
 };
 
 /// Main class responsible for creation of all adventure map objects
@@ -130,11 +120,6 @@ public:
 	std::string getObjectHandlerName(MapObjectID type) const;
 
 	std::string getJsonKey(MapObjectID type) const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & objects;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 7
lib/mapObjectConstructors/CRewardableConstructor.h

@@ -30,13 +30,6 @@ public:
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
 
 	std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		AObjectTypeHandler::serialize(h, version);
-
-		h & objectInfo;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 34
lib/mapObjectConstructors/CommonConstructors.h

@@ -66,14 +66,6 @@ public:
 
 	bool hasNameTextID() const override;
 	std::string getNameTextID() const override;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & filtersJson;
-		h & faction;
-		h & filters;
-		h & static_cast<CDefaultObjectTypeHandler<CGTownInstance>&>(*this);
-	}
 };
 
 class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance>
@@ -93,14 +85,6 @@ public:
 
 	bool hasNameTextID() const override;
 	std::string getNameTextID() const override;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & filtersJson;
-		h & heroClass;
-		h & filters;
-		h & static_cast<CDefaultObjectTypeHandler<CGHeroInstance>&>(*this);
-	}
 };
 
 class DLL_LINKAGE BoatInstanceConstructor : public CDefaultObjectTypeHandler<CGBoat>
@@ -122,18 +106,6 @@ public:
 
 	/// Returns boat preview animation, for use in Shipyards
 	AnimationPath getBoatAnimationName() const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<CDefaultObjectTypeHandler<CGBoat>&>(*this);
-		h & layer;
-		h & onboardAssaultAllowed;
-		h & onboardVisitAllowed;
-		h & bonuses;
-		h & actualAnimation;
-		h & overlayAnimation;
-		h & flagAnimations;
-	}
 };
 
 class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
@@ -152,12 +124,6 @@ public:
 	void initializeObject(CGMarket * object) const override;
 	void randomizeObject(CGMarket * object, CRandomGenerator & rng) const override;
 
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<CDefaultObjectTypeHandler<CGMarket>&>(*this);
-		h & marketModes;
-		h & marketEfficiency;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 7
lib/mapObjectConstructors/DwellingInstanceConstructor.h

@@ -33,13 +33,6 @@ public:
 
 	bool producesCreature(const CCreature * crea) const;
 	std::vector<const CCreature *> getProducedCreatures() const;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & availableCreatures;
-		h & guards;
-		h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 5
lib/mapObjectConstructors/HillFortInstanceConstructor.h

@@ -24,11 +24,6 @@ protected:
 	void initializeObject(HillFort * object) const override;
 
 public:
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<AObjectTypeHandler&>(*this);
-		h & parameters;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 8
lib/mapObjectConstructors/RandomMapInfo.h

@@ -33,14 +33,6 @@ struct DLL_LINKAGE RandomMapInfo
 	{}
 
 	void setMapLimit(ui32 val) { mapLimit = val; }
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & value;
-		h & mapLimit;
-		h & zoneLimit;
-		h & rarity;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 7
lib/mapObjectConstructors/SObjectSounds.h

@@ -18,13 +18,6 @@ struct SObjectSounds
 	std::vector<AudioPath> ambient;
 	std::vector<AudioPath> visit;
 	std::vector<AudioPath> removal;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & ambient;
-		h & visit;
-		h & removal;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 0 - 5
lib/mapObjectConstructors/ShipyardInstanceConstructor.h

@@ -24,11 +24,6 @@ protected:
 	void initializeObject(CGShipyard * object) const override;
 
 public:
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<AObjectTypeHandler&>(*this);
-		h & parameters;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/mapObjects/CGObjectInstance.cpp

@@ -117,7 +117,7 @@ std::set<int3> CGObjectInstance::getBlockedPos() const
 	return ret;
 }
 
-std::set<int3> CGObjectInstance::getBlockedOffsets() const
+const std::set<int3> & CGObjectInstance::getBlockedOffsets() const
 {
 	return appearance->getBlockedOffsets();
 }

+ 1 - 1
lib/mapObjects/CGObjectInstance.h

@@ -77,7 +77,7 @@ public:
 	bool coveringAt (const int3 & pos) const; //returns true if object covers with picture location (x, y) (h3m pos)
 
 	std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
-	std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
+	const std::set<int3> & getBlockedOffsets() const; //returns set of relative positions blocked by this object
 
 	/// returns true if object is visitable
 	bool isVisitable() const;

+ 12 - 1
lib/mapObjects/CGTownInstance.h

@@ -92,7 +92,18 @@ public:
 		for(auto * bonusingBuilding : bonusingBuildings)
 			bonusingBuilding->town = this;
 		
-		h & town;
+		if (h.saving)
+		{
+			CFaction * faction = town ? town->faction : nullptr;
+			h & faction;
+		}
+		else
+		{
+			CFaction * faction = nullptr;
+			h & faction;
+			town = faction ? faction->town : nullptr;
+		}
+
 		h & townAndVis;
 		BONUS_TREE_DESERIALIZATION_FIX
 

+ 0 - 5
lib/mapObjects/CObjectHandler.h

@@ -22,11 +22,6 @@ public:
 	std::vector<ui32> resVals; //default values of resources in gold
 
 	CObjectHandler();
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & resVals;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 5 - 5
lib/mapObjects/MiscObjects.cpp

@@ -724,19 +724,19 @@ void CGArtifact::pickRandomObject(CRandomGenerator & rand)
 	switch(ID.toEnum())
 	{
 		case MapObjectID::RANDOM_ART:
-			subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
+			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
 			break;
 		case MapObjectID::RANDOM_TREASURE_ART:
-			subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE);
+			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE);
 			break;
 		case MapObjectID::RANDOM_MINOR_ART:
-			subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR);
+			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_MINOR);
 			break;
 		case MapObjectID::RANDOM_MAJOR_ART:
-			subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR);
+			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_MAJOR);
 			break;
 		case MapObjectID::RANDOM_RELIC_ART:
-			subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_RELIC);
+			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_RELIC);
 			break;
 	}
 

+ 1 - 1
lib/mapObjects/ObjectTemplate.h

@@ -80,7 +80,7 @@ public:
 	bool isVisibleAt(si32 X, si32 Y) const;
 	bool isBlockedAt(si32 X, si32 Y) const;
 
-	inline std::set<int3> getBlockedOffsets() const
+	inline const std::set<int3> & getBlockedOffsets() const
 	{
 		return blockedOffsets;
 	};

+ 1 - 1
lib/mapping/CMapHeader.h

@@ -20,7 +20,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class CGObjectInstance;
 enum class EMapFormat : uint8_t;
-using ModCompatibilityInfo = std::map<std::string, CModInfo::VerificationInfo>;
+using ModCompatibilityInfo = std::map<std::string, ModVerificationInfo>;
 
 /// The hero name struct consists of the hero id and the hero name.
 struct DLL_LINKAGE SHeroName

+ 1 - 1
lib/mapping/CMapInfo.cpp

@@ -21,7 +21,7 @@
 
 #include "../campaign/CampaignHandler.h"
 #include "../filesystem/Filesystem.h"
-#include "../serializer/CMemorySerializer.h"
+#include "../serializer/CLoadFile.h"
 #include "../CGeneralTextHandler.h"
 #include "../rmg/CMapGenOptions.h"
 #include "../CCreatureHandler.h"

+ 1 - 1
lib/mapping/CMapService.h

@@ -23,7 +23,7 @@ class CInputStream;
 class IMapLoader;
 class IMapPatcher;
 
-using ModCompatibilityInfo = std::map<std::string, CModInfo::VerificationInfo>;
+using ModCompatibilityInfo = std::map<std::string, ModVerificationInfo>;
 
 /**
  * The map service provides loading of VCMI/H3 map files. It can

+ 1 - 1
lib/mapping/MapFormatJson.cpp

@@ -966,7 +966,7 @@ void CMapLoaderJson::readHeader(const bool complete)
 	{
 		for(auto & mod : header["mods"].Vector())
 		{
-			CModInfo::VerificationInfo info;
+			ModVerificationInfo info;
 			info.version = CModVersion::fromString(mod["version"].String());
 			info.checksum = mod["checksum"].Integer();
 			info.name = mod["name"].String();

+ 112 - 0
lib/modding/ActiveModsInSaveList.cpp

@@ -0,0 +1,112 @@
+/*
+ * ActiveModsInSaveList.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "ActiveModsInSaveList.h"
+
+#include "../VCMI_Lib.h"
+#include "CModInfo.h"
+#include "CModHandler.h"
+#include "ModIncompatibility.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+std::vector<TModID> ActiveModsInSaveList::getActiveMods()
+{
+	return VLC->modh->getActiveMods();
+}
+
+const ModVerificationInfo & ActiveModsInSaveList::getVerificationInfo(TModID mod)
+{
+	return VLC->modh->getModInfo(mod).getVerificationInfo();
+}
+
+void ActiveModsInSaveList::verifyActiveMods(const std::vector<std::pair<TModID, ModVerificationInfo>> & modList)
+{
+	auto searchVerificationInfo = [&modList](const TModID & m) -> const ModVerificationInfo*
+	{
+		for(auto & i : modList)
+			if(i.first == m)
+				return &i.second;
+		return nullptr;
+	};
+
+	std::vector<TModID> missingMods, excessiveMods;
+	ModIncompatibility::ModListWithVersion missingModsResult;
+	ModIncompatibility::ModList excessiveModsResult;
+
+	for(const auto & m : VLC->modh->getActiveMods())
+	{
+		if(searchVerificationInfo(m))
+			continue;
+
+		//TODO: support actual disabling of these mods
+		if(VLC->modh->getModInfo(m).checkModGameplayAffecting())
+			excessiveMods.push_back(m);
+	}
+
+	for(const auto & infoPair : modList)
+	{
+		auto & remoteModId = infoPair.first;
+		auto & remoteModInfo = infoPair.second;
+
+		bool modAffectsGameplay = remoteModInfo.impactsGameplay;
+		//parent mod affects gameplay if child affects too
+		for(const auto & subInfoPair : modList)
+			modAffectsGameplay |= (subInfoPair.second.impactsGameplay && subInfoPair.second.parent == remoteModId);
+
+		if(!vstd::contains(VLC->modh->getAllMods(), remoteModId))
+		{
+			if(modAffectsGameplay)
+				missingMods.push_back(remoteModId); //mod is not installed
+			continue;
+		}
+
+		auto & localModInfo = VLC->modh->getModInfo(remoteModId).getVerificationInfo();
+		modAffectsGameplay |= VLC->modh->getModInfo(remoteModId).checkModGameplayAffecting();
+		bool modVersionCompatible = localModInfo.version.isNull()
+			|| remoteModInfo.version.isNull()
+			|| localModInfo.version.compatible(remoteModInfo.version);
+		bool modLocalyEnabled = vstd::contains(VLC->modh->getActiveMods(), remoteModId);
+
+		if(modVersionCompatible && modAffectsGameplay && modLocalyEnabled)
+			continue;
+
+		if(modAffectsGameplay)
+			missingMods.push_back(remoteModId); //incompatible mod impacts gameplay
+	}
+
+	//filter mods
+	for(auto & m : missingMods)
+	{
+		if(auto * vInfo = searchVerificationInfo(m))
+		{
+			assert(vInfo->parent != m);
+			if(!vInfo->parent.empty() && vstd::contains(missingMods, vInfo->parent))
+				continue;
+			missingModsResult.push_back({vInfo->name, vInfo->version.toString()});
+		}
+	}
+	for(auto & m : excessiveMods)
+	{
+		auto & vInfo = VLC->modh->getModInfo(m).getVerificationInfo();
+		assert(vInfo.parent != m);
+		if(!vInfo.parent.empty() && vstd::contains(excessiveMods, vInfo.parent))
+			continue;
+		excessiveModsResult.push_back(vInfo.name);
+	}
+
+	if(!missingModsResult.empty() || !excessiveModsResult.empty())
+		throw ModIncompatibility(missingModsResult, excessiveModsResult);
+
+	//TODO: support actual enabling of required mods
+}
+
+
+VCMI_LIB_NAMESPACE_END

+ 51 - 0
lib/modding/ActiveModsInSaveList.h

@@ -0,0 +1,51 @@
+/*
+ * ActiveModsInSaveList.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "ModVerificationInfo.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class ActiveModsInSaveList
+{
+	std::vector<TModID> getActiveMods();
+	const ModVerificationInfo & getVerificationInfo(TModID mod);
+
+	/// Checks whether provided mod list is compatible with current VLC and throws on failure
+	void verifyActiveMods(const std::vector<std::pair<TModID, ModVerificationInfo>> & modList);
+public:
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		if(h.saving)
+		{
+			std::vector<TModID> activeMods = getActiveMods();
+			h & activeMods;
+			for(const auto & m : activeMods)
+				h & getVerificationInfo(m);
+		}
+		else
+		{
+			std::vector<TModID> saveActiveMods;
+			h & saveActiveMods;
+
+			std::vector<std::pair<TModID, ModVerificationInfo>> saveModInfos(saveActiveMods.size());
+			for(int i = 0; i < saveActiveMods.size(); ++i)
+			{
+				saveModInfos[i].first = saveActiveMods[i];
+				h & saveModInfos[i].second;
+			}
+
+			verifyActiveMods(saveModInfos);
+		}
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 0 - 82
lib/modding/CModHandler.cpp

@@ -491,88 +491,6 @@ void CModHandler::afterLoad(bool onlyEssential)
 		std::fstream file(CResourceHandler::get()->getResourceName(ResourcePath("config/modSettings.json"))->c_str(), std::ofstream::out | std::ofstream::trunc);
 		file << modSettings.toJson();
 	}
-
-}
-
-void CModHandler::trySetActiveMods(const std::vector<std::pair<TModID, CModInfo::VerificationInfo>> & modList)
-{
-	auto searchVerificationInfo = [&modList](const TModID & m) -> const CModInfo::VerificationInfo*
-	{
-		for(auto & i : modList)
-			if(i.first == m)
-				return &i.second;
-		return nullptr;
-	};
-	
-	std::vector<TModID> missingMods, excessiveMods;
-	ModIncompatibility::ModListWithVersion missingModsResult;
-	ModIncompatibility::ModList excessiveModsResult;
-	
-	for(const auto & m : activeMods)
-	{
-		if(searchVerificationInfo(m))
-			continue;
-
-		//TODO: support actual disabling of these mods
-		if(getModInfo(m).checkModGameplayAffecting())
-			excessiveMods.push_back(m);
-	}
-	
-	for(const auto & infoPair : modList)
-	{
-		auto & remoteModId = infoPair.first;
-		auto & remoteModInfo = infoPair.second;
-		
-		bool modAffectsGameplay = remoteModInfo.impactsGameplay;
-		//parent mod affects gameplay if child affects too
-		for(const auto & subInfoPair : modList)
-			modAffectsGameplay |= (subInfoPair.second.impactsGameplay && subInfoPair.second.parent == remoteModId);
-		
-		if(!allMods.count(remoteModId))
-		{
-			if(modAffectsGameplay)
-				missingMods.push_back(remoteModId); //mod is not installed
-			continue;
-		}
-		
-		auto & localModInfo = getModInfo(remoteModId).getVerificationInfo();
-		modAffectsGameplay |= getModInfo(remoteModId).checkModGameplayAffecting();
-		bool modVersionCompatible = localModInfo.version.isNull()
-			|| remoteModInfo.version.isNull()
-			|| localModInfo.version.compatible(remoteModInfo.version);
-		bool modLocalyEnabled = vstd::contains(activeMods, remoteModId);
-		
-		if(modVersionCompatible && modAffectsGameplay && modLocalyEnabled)
-			continue;
-		
-		if(modAffectsGameplay)
-			missingMods.push_back(remoteModId); //incompatible mod impacts gameplay
-	}
-	
-	//filter mods
-	for(auto & m : missingMods)
-	{
-		if(auto * vInfo = searchVerificationInfo(m))
-		{
-			assert(vInfo->parent != m);
-			if(!vInfo->parent.empty() && vstd::contains(missingMods, vInfo->parent))
-				continue;
-			missingModsResult.push_back({vInfo->name, vInfo->version.toString()});
-		}
-	}
-	for(auto & m : excessiveMods)
-	{
-		auto & vInfo = getModInfo(m).getVerificationInfo();
-		assert(vInfo.parent != m);
-		if(!vInfo.parent.empty() && vstd::contains(excessiveMods, vInfo.parent))
-			continue;
-		excessiveModsResult.push_back(vInfo.name);
-	}
-	
-	if(!missingModsResult.empty() || !excessiveModsResult.empty())
-		throw ModIncompatibility(missingModsResult, excessiveModsResult);
-	
-	//TODO: support actual enabling of required mods
 }
 
 VCMI_LIB_NAMESPACE_END

+ 5 - 32
lib/modding/CModHandler.h

@@ -9,21 +9,22 @@
  */
 #pragma once
 
-#include "CModInfo.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
 class CModHandler;
 class CModIndentifier;
+class CModInfo;
+struct CModVersion;
 class JsonNode;
 class IHandlerBase;
 class CIdentifierStorage;
 class CContentHandler;
+struct ModVerificationInfo;
 class ResourcePath;
 
 using TModID = std::string;
 
-class DLL_LINKAGE CModHandler : boost::noncopyable
+class DLL_LINKAGE CModHandler final : boost::noncopyable
 {
 	std::map <TModID, CModInfo> allMods;
 	std::vector <TModID> activeMods;//active mods, in order in which they were loaded
@@ -50,9 +51,6 @@ class DLL_LINKAGE CModHandler : boost::noncopyable
 
 	CModVersion getModVersion(TModID modName) const;
 
-	/// Attempt to set active mods according to provided list of mods from save, throws on failure
-	void trySetActiveMods(const std::vector<std::pair<TModID, CModInfo::VerificationInfo>> & modList);
-
 public:
 	std::shared_ptr<CContentHandler> content; //(!)Do not serialize FIXME: make private
 
@@ -79,32 +77,7 @@ public:
 	void afterLoad(bool onlyEssential);
 
 	CModHandler();
-	virtual ~CModHandler();
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		if(h.saving)
-		{
-			h & activeMods;
-			for(const auto & m : activeMods)
-				h & getModInfo(m).getVerificationInfo();
-		}
-		else
-		{
-			loadMods();
-			std::vector<TModID> saveActiveMods;
-			h & saveActiveMods;
-			
-			std::vector<std::pair<TModID, CModInfo::VerificationInfo>> saveModInfos(saveActiveMods.size());
-			for(int i = 0; i < saveActiveMods.size(); ++i)
-			{
-				saveModInfos[i].first = saveActiveMods[i];
-				h & saveModInfos[i].second;
-			}
-
-			trySetActiveMods(saveModInfos);
-		}
-	}
+	~CModHandler();
 };
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/modding/CModInfo.cpp

@@ -177,7 +177,7 @@ bool CModInfo::checkModGameplayAffecting() const
 	return *modGameplayAffecting;
 }
 
-const CModInfo::VerificationInfo & CModInfo::getVerificationInfo() const
+const ModVerificationInfo & CModInfo::getVerificationInfo() const
 {
 	return verificationInfo;
 }

+ 3 - 33
lib/modding/CModInfo.h

@@ -10,12 +10,10 @@
 #pragma once
 
 #include "../JsonNode.h"
-#include "CModVersion.h"
+#include "ModVerificationInfo.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-using TModID = std::string;
-
 class DLL_LINKAGE CModInfo
 {
 	/// cached result of checkModGameplayAffecting() call
@@ -30,34 +28,6 @@ public:
 		PASSED
 	};
 	
-	struct VerificationInfo
-	{
-		/// human-readable mod name
-		std::string name;
-		
-		/// version of the mod
-		CModVersion version;
-		
-		/// CRC-32 checksum of the mod
-		ui32 checksum = 0;
-		
-		/// parent mod ID, empty if root-level mod
-		TModID parent;
-		
-		/// for serialization purposes
-		bool impactsGameplay = true;
-		
-		template <typename Handler>
-		void serialize(Handler & h, const int v)
-		{
-			h & name;
-			h & version;
-			h & checksum;
-			h & parent;
-			h & impactsGameplay;
-		}
-	};
-
 	/// identifier, identical to name of folder with mod
 	std::string identifier;
 
@@ -94,7 +64,7 @@ public:
 	/// return true if this mod can affect gameplay, e.g. adds or modifies any game objects
 	bool checkModGameplayAffecting() const;
 	
-	const VerificationInfo & getVerificationInfo() const;
+	const ModVerificationInfo & getVerificationInfo() const;
 
 private:
 	/// true if mod is enabled by user, e.g. in Launcher UI
@@ -103,7 +73,7 @@ private:
 	/// true if mod can be loaded - compatible and has no missing deps
 	bool implicitlyEnabled;
 	
-	VerificationInfo verificationInfo;
+	ModVerificationInfo verificationInfo;
 
 	void loadLocalData(const JsonNode & data);
 };

+ 2 - 0
lib/modding/CModVersion.h

@@ -18,6 +18,8 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+using TModID = std::string;
+
 struct DLL_LINKAGE CModVersion
 {
 	static const int Any = -1;

+ 0 - 12
lib/modding/IdentifierStorage.h

@@ -52,12 +52,6 @@ class DLL_LINKAGE CIdentifierStorage
 		{
 			return id == other.id && scope == other.scope;
 		}
-
-		template <typename Handler> void serialize(Handler &h, const int version)
-		{
-			h & id;
-			h & scope;
-		}
 	};
 
 	std::multimap<std::string, ObjectData> registeredObjects;
@@ -102,12 +96,6 @@ public:
 
 	/// called at the very end of loading to check for any missing ID's
 	void finalize();
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & registeredObjects;
-		h & state;
-	}
 };
 
 VCMI_LIB_NAMESPACE_END

+ 44 - 0
lib/modding/ModVerificationInfo.h

@@ -0,0 +1,44 @@
+/*
+ * ModVerificationInfo.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "CModVersion.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+struct ModVerificationInfo
+{
+	/// human-readable mod name
+	std::string name;
+
+	/// version of the mod
+	CModVersion version;
+
+	/// CRC-32 checksum of the mod
+	ui32 checksum = 0;
+
+	/// parent mod ID, empty if root-level mod
+	TModID parent;
+
+	/// for serialization purposes
+	bool impactsGameplay = true;
+
+	template <typename Handler>
+	void serialize(Handler & h, const int v)
+	{
+		h & name;
+		h & version;
+		h & checksum;
+		h & parent;
+		h & impactsGameplay;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/networkPacks/NetPacksLib.cpp

@@ -858,7 +858,7 @@ void AddQuest::applyGs(CGameState * gs) const
 
 void UpdateArtHandlerLists::applyGs(CGameState * gs) const
 {
-	VLC->arth->allocatedArtifacts = allocatedArtifacts;
+	gs->allocatedArtifacts = allocatedArtifacts;
 }
 
 void UpdateMapEvents::applyGs(CGameState * gs) const

+ 0 - 52
lib/registerTypes/RegisterTypes.cpp

@@ -1,52 +0,0 @@
-/*
- * RegisterTypes.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#define INSTANTIATE_REGISTER_TYPES_HERE
-#include "RegisterTypes.h"
-
-#include "../mapping/CMapInfo.h"
-#include "../StartInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../spells/CSpellHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-// For reference: peak memory usage by gcc during compilation of register type templates
-// registerTypesMapObjects:  1.9 Gb
-// registerTypes2:  2.2 Gb
-//     registerTypesClientPacks1 1.6 Gb
-//     registerTypesClientPacks2 1.6 Gb
-// registerTypesServerPacks:  1.3 Gb
-// registerTypes4:  1.3 Gb
-
-
-#define DEFINE_EXTERNAL_METHOD(METHODNAME) \
-extern template DLL_LINKAGE void METHODNAME<BinaryDeserializer>(BinaryDeserializer & s); \
-extern template DLL_LINKAGE void METHODNAME<BinarySerializer>(BinarySerializer & s); \
-extern template DLL_LINKAGE void METHODNAME<CTypeList>(CTypeList & s); \
-
-//DEFINE_EXTERNAL_METHOD(registerTypesMapObjects)
-DEFINE_EXTERNAL_METHOD(registerTypesMapObjects1)
-DEFINE_EXTERNAL_METHOD(registerTypesMapObjects2)
-DEFINE_EXTERNAL_METHOD(registerTypesClientPacks1)
-DEFINE_EXTERNAL_METHOD(registerTypesClientPacks2)
-DEFINE_EXTERNAL_METHOD(registerTypesServerPacks)
-DEFINE_EXTERNAL_METHOD(registerTypesLobbyPacks)
-
-template void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypes<BinarySerializer>(BinarySerializer & s);
-template void registerTypes<CTypeList>(CTypeList & s);
-
-VCMI_LIB_NAMESPACE_END

+ 6 - 399
lib/registerTypes/RegisterTypes.h

@@ -9,413 +9,20 @@
  */
 #pragma once
 
-#include "../networkPacks/PacksForClient.h"
-#include "../networkPacks/PacksForClientBattle.h"
-#include "../networkPacks/PacksForServer.h"
-#include "../networkPacks/PacksForLobby.h"
-#include "../networkPacks/SetStackEffect.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CCreatureSet.h"
-#include "../CPlayerState.h"
-#include "../CHeroHandler.h"
-#include "../CTownHandler.h"
-#include "../mapObjectConstructors/CRewardableConstructor.h"
-#include "../mapObjectConstructors/CommonConstructors.h"
-#include "../mapObjectConstructors/CBankInstanceConstructor.h"
-#include "../mapObjectConstructors/DwellingInstanceConstructor.h"
-#include "../mapObjectConstructors/HillFortInstanceConstructor.h"
-#include "../mapObjectConstructors/ShipyardInstanceConstructor.h"
-#include "../mapObjects/MapObjects.h"
-#include "../mapObjects/CGCreature.h"
-#include "../mapObjects/CGTownBuilding.h"
-#include "../mapObjects/ObjectTemplate.h"
-#include "../battle/CObstacleInstance.h"
-#include "../bonuses/CBonusSystemNode.h"
-#include "../bonuses/Limiters.h"
-#include "../bonuses/Updaters.h"
-#include "../bonuses/Propagators.h"
-#include "../CStack.h"
+#include "RegisterTypesClientPacks.h"
+#include "RegisterTypesLobbyPacks.h"
+#include "RegisterTypesMapObjects.h"
+#include "RegisterTypesServerPacks.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class BinarySerializer;
-class BinaryDeserializer;
-class CTypeList;
-
-template<typename Serializer>
-void registerTypesMapObjects1(Serializer &s)
-{
-	//////////////////////////////////////////////////////////////////////////
-	// Adventure map objects
-	//////////////////////////////////////////////////////////////////////////
-	s.template registerType<IObjectInterface, CGObjectInstance>();
-
-	// Non-armed objects
-	s.template registerType<CGObjectInstance, CGTeleport>();
-		s.template registerType<CGTeleport, CGMonolith>();
-			s.template registerType<CGMonolith, CGSubterraneanGate>();
-			s.template registerType<CGMonolith, CGWhirlpool>();
-	s.template registerType<CGObjectInstance, CGSignBottle>();
-	s.template registerType<CGObjectInstance, CGKeys>();
-		s.template registerType<CGKeys, CGKeymasterTent>();
-		s.template registerType<CGKeys, CGBorderGuard>(); s.template registerType<IQuestObject, CGBorderGuard>();
-			s.template registerType<CGBorderGuard, CGBorderGate>();
-	s.template registerType<CGObjectInstance, CGBoat>();
-	s.template registerType<CGObjectInstance, CGMagi>();
-	s.template registerType<CGObjectInstance, CGSirens>();
-	s.template registerType<CGObjectInstance, CGShipyard>();
-	s.template registerType<CGObjectInstance, CGDenOfthieves>();
-	s.template registerType<CGObjectInstance, CGLighthouse>();
-	s.template registerType<CGObjectInstance, CGTerrainPatch>();
-	s.template registerType<CGObjectInstance, HillFort>();
-	s.template registerType<CGObjectInstance, CGMarket>();
-		s.template registerType<CGMarket, CGBlackMarket>();
-		s.template registerType<CGMarket, CGUniversity>();
-	s.template registerType<CGObjectInstance, CGHeroPlaceholder>();
-
-	s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();
-
-	// Armed objects
-	s.template registerType<CArmedInstance, CGHeroInstance>(); s.template registerType<CArtifactSet, CGHeroInstance>();
-	s.template registerType<CArmedInstance, CGDwelling>();
-		s.template registerType<CGDwelling, CGTownInstance>();
-	s.template registerType<CArmedInstance, CGPandoraBox>();
-		s.template registerType<CGPandoraBox, CGEvent>();
-	s.template registerType<CArmedInstance, CGCreature>();
-	s.template registerType<CArmedInstance, CGGarrison>();
-	s.template registerType<CArmedInstance, CGArtifact>();
-	s.template registerType<CArmedInstance, CGResource>();
-	s.template registerType<CArmedInstance, CGMine>();
-	s.template registerType<CArmedInstance, CBank>();
-	s.template registerType<CArmedInstance, CGSeerHut>(); s.template registerType<IQuestObject, CGSeerHut>();
-	s.template registerType<CGSeerHut, CGQuestGuard>();
-}
-
-template<typename Serializer>
-void registerTypesMapObjectTypes(Serializer &s)
-{
-	s.template registerType<AObjectTypeHandler, CRewardableConstructor>();
-	s.template registerType<AObjectTypeHandler, CHeroInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, CTownInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, DwellingInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, CBankInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, BoatInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, MarketInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
-	s.template registerType<AObjectTypeHandler, ShipyardInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, HillFortInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, CreatureInstanceConstructor>();
-	s.template registerType<AObjectTypeHandler, ResourceInstanceConstructor>();
-
-#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
-
-	REGISTER_GENERIC_HANDLER(CGObjectInstance);
-	REGISTER_GENERIC_HANDLER(CGArtifact);
-	REGISTER_GENERIC_HANDLER(CGBlackMarket);
-	REGISTER_GENERIC_HANDLER(CGBoat);
-	REGISTER_GENERIC_HANDLER(CGBorderGate);
-	REGISTER_GENERIC_HANDLER(CGBorderGuard);
-	REGISTER_GENERIC_HANDLER(CGCreature);
-	REGISTER_GENERIC_HANDLER(CGDenOfthieves);
-	REGISTER_GENERIC_HANDLER(CGDwelling);
-	REGISTER_GENERIC_HANDLER(CGEvent);
-	REGISTER_GENERIC_HANDLER(CGGarrison);
-	REGISTER_GENERIC_HANDLER(CGHeroPlaceholder);
-	REGISTER_GENERIC_HANDLER(CGHeroInstance);
-	REGISTER_GENERIC_HANDLER(CGKeymasterTent);
-	REGISTER_GENERIC_HANDLER(CGLighthouse);
-	REGISTER_GENERIC_HANDLER(CGTerrainPatch);
-	REGISTER_GENERIC_HANDLER(CGMagi);
-	REGISTER_GENERIC_HANDLER(CGMarket);
-	REGISTER_GENERIC_HANDLER(CGMine);
-	REGISTER_GENERIC_HANDLER(CGObelisk);
-	REGISTER_GENERIC_HANDLER(CGPandoraBox);
-	REGISTER_GENERIC_HANDLER(CGQuestGuard);
-	REGISTER_GENERIC_HANDLER(CGResource);
-	REGISTER_GENERIC_HANDLER(CGSeerHut);
-	REGISTER_GENERIC_HANDLER(CGShipyard);
-	REGISTER_GENERIC_HANDLER(CGSignBottle);
-	REGISTER_GENERIC_HANDLER(CGSirens);
-	REGISTER_GENERIC_HANDLER(CGMonolith);
-	REGISTER_GENERIC_HANDLER(CGSubterraneanGate);
-	REGISTER_GENERIC_HANDLER(CGWhirlpool);
-	REGISTER_GENERIC_HANDLER(CGTownInstance);
-	REGISTER_GENERIC_HANDLER(CGUniversity);
-	REGISTER_GENERIC_HANDLER(HillFort);
-
-#undef REGISTER_GENERIC_HANDLER
-
-	s.template registerType<IUpdater, GrowsWithLevelUpdater>();
-	s.template registerType<IUpdater, TimesHeroLevelUpdater>();
-	s.template registerType<IUpdater, TimesStackLevelUpdater>();
-	s.template registerType<IUpdater, OwnerUpdater>();
-	s.template registerType<IUpdater, ArmyMovementUpdater>();
-
-	s.template registerType<ILimiter, AnyOfLimiter>();
-	s.template registerType<ILimiter, NoneOfLimiter>();
-	s.template registerType<ILimiter, OppositeSideLimiter>();
-	//new types (other than netpacks) must register here
-	//order of type registration is critical for loading old savegames
-}
-
-template<typename Serializer>
-void registerTypesMapObjects2(Serializer &s)
-{
-	//Other object-related
-	s.template registerType<IObjectInterface, CGTownBuilding>();
-		s.template registerType<CGTownBuilding, CTownBonus>();
-		s.template registerType<CGTownBuilding, COPWBonus>();
-		s.template registerType<CGTownBuilding, CTownRewardableBuilding>();
-
-	s.template registerType<CGObjectInstance, CRewardableObject>();
-
-	s.template registerType<CGObjectInstance, CTeamVisited>();
-		s.template registerType<CTeamVisited, CGObelisk>();
-
-	//s.template registerType<CQuest>();
-	//s.template registerType<IQuestObject>();
-
-	//end of objects
-
-	//////////////////////////////////////////////////////////////////////////
-	// Bonus system
-	//////////////////////////////////////////////////////////////////////////
-	//s.template registerType<IPropagator>();
-	s.template registerType<IPropagator, CPropagatorNodeType>();
-
-	// Limiters
-	//s.template registerType<ILimiter>();
-	s.template registerType<ILimiter, AllOfLimiter>();
-	s.template registerType<ILimiter, CCreatureTypeLimiter>();
-	s.template registerType<ILimiter, HasAnotherBonusLimiter>();
-	s.template registerType<ILimiter, CreatureTerrainLimiter>();
-	s.template registerType<ILimiter, FactionLimiter>();
-	s.template registerType<ILimiter, CreatureLevelLimiter>();
-	s.template registerType<ILimiter, CreatureAlignmentLimiter>();
-	s.template registerType<ILimiter, RankRangeLimiter>();
-	s.template registerType<ILimiter, UnitOnHexLimiter>();
-
-//	s.template registerType<CBonusSystemNode>();
-	s.template registerType<CBonusSystemNode, CArtifact>();
-	s.template registerType<CBonusSystemNode, CCreature>();
-	s.template registerType<CBonusSystemNode, CStackInstance>();
-	s.template registerType<CStackInstance, CCommanderInstance>();
-	s.template registerType<CBonusSystemNode, PlayerState>();
-	s.template registerType<CBonusSystemNode, TeamState>();
-	//s.template registerType<CGameState>(); //TODO
-	//s.template registerType<CArmedInstance>();
-	s.template registerType<CBonusSystemNode, CStack>();
-	s.template registerType<CBonusSystemNode, BattleInfo>();
-	//s.template registerType<QuestInfo>();
-	s.template registerType<CBonusSystemNode, CArtifactInstance>();
-
-	//s.template registerType<CObstacleInstance>();
-		s.template registerType<CObstacleInstance, SpellCreatedObstacle>();
-}
-template<typename Serializer>
-void registerTypesClientPacks1(Serializer &s)
-{
-	s.template registerType<CPack, CPackForClient>();
-
-	s.template registerType<CPackForClient, PackageApplied>();
-	s.template registerType<CPackForClient, SystemMessage>();
-	s.template registerType<CPackForClient, PlayerBlocked>();
-	s.template registerType<CPackForClient, PlayerCheated>();
-	s.template registerType<CPackForClient, PlayerStartsTurn>();
-	s.template registerType<CPackForClient, DaysWithoutTown>();
-	s.template registerType<CPackForClient, TurnTimeUpdate>();
-	s.template registerType<CPackForClient, SetResources>();
-	s.template registerType<CPackForClient, SetPrimSkill>();
-	s.template registerType<CPackForClient, SetSecSkill>();
-	s.template registerType<CPackForClient, HeroVisitCastle>();
-	s.template registerType<CPackForClient, ChangeSpells>();
-	s.template registerType<CPackForClient, SetMana>();
-	s.template registerType<CPackForClient, SetMovePoints>();
-	s.template registerType<CPackForClient, FoWChange>();
-	s.template registerType<CPackForClient, SetAvailableHero>();
-	s.template registerType<CPackForClient, GiveBonus>();
-	s.template registerType<CPackForClient, ChangeObjPos>();
-	s.template registerType<CPackForClient, PlayerEndsTurn>();
-	s.template registerType<CPackForClient, PlayerEndsGame>();
-	s.template registerType<CPackForClient, PlayerReinitInterface>();
-	s.template registerType<CPackForClient, RemoveBonus>();
-	s.template registerType<CPackForClient, UpdateArtHandlerLists>();
-	s.template registerType<CPackForClient, UpdateMapEvents>();
-	s.template registerType<CPackForClient, UpdateCastleEvents>();
-	s.template registerType<CPackForClient, ChangeFormation>();
-	s.template registerType<CPackForClient, RemoveObject>();
-	s.template registerType<CPackForClient, TryMoveHero>();
-	s.template registerType<CPackForClient, NewStructures>();
-	s.template registerType<CPackForClient, RazeStructures>();
-	s.template registerType<CPackForClient, SetAvailableCreatures>();
-	s.template registerType<CPackForClient, SetHeroesInTown>();
-	s.template registerType<CPackForClient, HeroRecruited>();
-	s.template registerType<CPackForClient, GiveHero>();
-	s.template registerType<CPackForClient, NewTurn>();
-	s.template registerType<CPackForClient, InfoWindow>();
-	s.template registerType<CPackForClient, SetObjectProperty>();
-	s.template registerType<CPackForClient, AdvmapSpellCast>();
-	s.template registerType<CPackForClient, OpenWindow>();
-	s.template registerType<CPackForClient, NewObject>();
-	s.template registerType<CPackForClient, NewArtifact>();
-	s.template registerType<CPackForClient, AddQuest>();
-	s.template registerType<CPackForClient, SetAvailableArtifacts>();
-	s.template registerType<CPackForClient, CenterView>();
-	s.template registerType<CPackForClient, HeroVisit>();
-	s.template registerType<CPackForClient, SetCommanderProperty>();
-	s.template registerType<CPackForClient, ChangeObjectVisitors>();
-	s.template registerType<CPackForClient, ShowWorldViewEx>();
-	s.template registerType<CPackForClient, PrepareHeroLevelUp>();
-	s.template registerType<CPackForClient, EntitiesChanged>();
-}
-
-template<typename Serializer>
-void registerTypesClientPacks2(Serializer &s)
-{
-	s.template registerType<CPackForClient, BattleStart>();
-	s.template registerType<CPackForClient, BattleNextRound>();
-	s.template registerType<CPackForClient, BattleSetActiveStack>();
-	s.template registerType<CPackForClient, BattleResult>();
-	s.template registerType<CPackForClient, BattleResultAccepted>();
-	s.template registerType<CPackForClient, BattleCancelled>();
-	s.template registerType<CPackForClient, BattleLogMessage>();
-	s.template registerType<CPackForClient, BattleStackMoved>();
-	s.template registerType<CPackForClient, BattleAttack>();
-	s.template registerType<CPackForClient, StartAction>();
-	s.template registerType<CPackForClient, EndAction>();
-	s.template registerType<CPackForClient, BattleSpellCast>();
-	s.template registerType<CPackForClient, SetStackEffect>();
-	s.template registerType<CPackForClient, BattleTriggerEffect>();
-	s.template registerType<CPackForClient, BattleUpdateGateState>();
-	s.template registerType<CPackForClient, BattleSetStackProperty>();
-	s.template registerType<CPackForClient, StacksInjured>();
-	s.template registerType<CPackForClient, BattleResultsApplied>();
-	s.template registerType<CPackForClient, BattleUnitsChanged>();
-	s.template registerType<CPackForClient, BattleObstaclesChanged>();
-	s.template registerType<CPackForClient, CatapultAttack>();
-
-	s.template registerType<CPackForClient, Query>();
-	s.template registerType<Query, HeroLevelUp>();
-	s.template registerType<Query, CommanderLevelUp>();
-	s.template registerType<Query, BlockingDialog>();
-	s.template registerType<Query, GarrisonDialog>();
-	s.template registerType<Query, ExchangeDialog>();
-	s.template registerType<Query, TeleportDialog>();
-	s.template registerType<Query, MapObjectSelectDialog>();
-
-	s.template registerType<CPackForClient, CGarrisonOperationPack>();
-	s.template registerType<CGarrisonOperationPack, ChangeStackCount>();
-	s.template registerType<CGarrisonOperationPack, SetStackType>();
-	s.template registerType<CGarrisonOperationPack, EraseStack>();
-	s.template registerType<CGarrisonOperationPack, SwapStacks>();
-	s.template registerType<CGarrisonOperationPack, InsertNewStack>();
-	s.template registerType<CGarrisonOperationPack, RebalanceStacks>();
-
-	s.template registerType<CPackForClient, CArtifactOperationPack>();
-	s.template registerType<CArtifactOperationPack, PutArtifact>();
-	s.template registerType<CArtifactOperationPack, EraseArtifact>();
-	s.template registerType<CArtifactOperationPack, MoveArtifact>();
-	s.template registerType<CArtifactOperationPack, AssembledArtifact>();
-	s.template registerType<CArtifactOperationPack, DisassembledArtifact>();
-	s.template registerType<CArtifactOperationPack, BulkMoveArtifacts>();
-
-	s.template registerType<CPackForClient, PlayerMessageClient>();
-	s.template registerType<CGarrisonOperationPack, BulkRebalanceStacks>();
-	s.template registerType<CGarrisonOperationPack, BulkSmartRebalanceStacks>();
-}
-
-template<typename Serializer>
-void registerTypesServerPacks(Serializer &s)
-{
-	s.template registerType<CPack, CPackForServer>();
-	s.template registerType<CPackForServer, EndTurn>();
-	s.template registerType<CPackForServer, DismissHero>();
-	s.template registerType<CPackForServer, MoveHero>();
-	s.template registerType<CPackForServer, ArrangeStacks>();
-	s.template registerType<CPackForServer, DisbandCreature>();
-	s.template registerType<CPackForServer, BuildStructure>();
-	s.template registerType<CPackForServer, RecruitCreatures>();
-	s.template registerType<CPackForServer, UpgradeCreature>();
-	s.template registerType<CPackForServer, GarrisonHeroSwap>();
-	s.template registerType<CPackForServer, ExchangeArtifacts>();
-	s.template registerType<CPackForServer, AssembleArtifacts>();
-	s.template registerType<CPackForServer, BuyArtifact>();
-	s.template registerType<CPackForServer, TradeOnMarketplace>();
-	s.template registerType<CPackForServer, SetFormation>();
-	s.template registerType<CPackForServer, HireHero>();
-	s.template registerType<CPackForServer, BuildBoat>();
-	s.template registerType<CPackForServer, QueryReply>();
-	s.template registerType<CPackForServer, MakeAction>();
-	s.template registerType<CPackForServer, DigWithHero>();
-	s.template registerType<CPackForServer, CastAdvSpell>();
-	s.template registerType<CPackForServer, CastleTeleportHero>();
-	s.template registerType<CPackForServer, SaveGame>();
-	s.template registerType<CPackForServer, PlayerMessage>();
-	s.template registerType<CPackForServer, BulkSplitStack>();
-	s.template registerType<CPackForServer, BulkMergeStacks>();
-	s.template registerType<CPackForServer, BulkSmartSplitStack>();
-	s.template registerType<CPackForServer, BulkMoveArmy>();
-	s.template registerType<CPackForServer, BulkExchangeArtifacts>();
-	s.template registerType<CPackForServer, EraseArtifactByClient>();
-	s.template registerType<CPackForServer, GamePause>();
-}
-
-template<typename Serializer>
-void registerTypesLobbyPacks(Serializer &s)
-{
-	s.template registerType<CPack, CPackForLobby>();
-	s.template registerType<CPackForLobby, CLobbyPackToPropagate>();
-	s.template registerType<CPackForLobby, CLobbyPackToServer>();
-
-	// Any client can sent
-	s.template registerType<CLobbyPackToPropagate, LobbyClientConnected>();
-	s.template registerType<CLobbyPackToPropagate, LobbyClientDisconnected>();
-	s.template registerType<CLobbyPackToPropagate, LobbyChatMessage>();
-	// Only host client send
-	s.template registerType<CLobbyPackToPropagate, LobbyGuiAction>();
-	s.template registerType<CLobbyPackToPropagate, LobbyLoadProgress>();
-	s.template registerType<CLobbyPackToPropagate, LobbyEndGame>();
-	s.template registerType<CLobbyPackToPropagate, LobbyStartGame>();
-	s.template registerType<CLobbyPackToPropagate, LobbyChangeHost>();
-	// Only server send
-	s.template registerType<CLobbyPackToPropagate, LobbyUpdateState>();
-	s.template registerType<CLobbyPackToPropagate, LobbyShowMessage>();
-
-	// For client with permissions
-	s.template registerType<CLobbyPackToServer, LobbyChangePlayerOption>();
-	// Only for host client
-	s.template registerType<CLobbyPackToServer, LobbySetMap>();
-	s.template registerType<CLobbyPackToServer, LobbySetCampaign>();
-	s.template registerType<CLobbyPackToServer, LobbySetCampaignMap>();
-	s.template registerType<CLobbyPackToServer, LobbySetCampaignBonus>();
-	s.template registerType<CLobbyPackToServer, LobbySetPlayer>();
-	s.template registerType<CLobbyPackToServer, LobbySetPlayerName>();
-	s.template registerType<CLobbyPackToServer, LobbySetTurnTime>();
-	s.template registerType<CLobbyPackToServer, LobbySetSimturns>();
-	s.template registerType<CLobbyPackToServer, LobbySetDifficulty>();
-	s.template registerType<CLobbyPackToServer, LobbyForceSetPlayer>();
-}
-
 template<typename Serializer>
 void registerTypes(Serializer &s)
 {
-	registerTypesMapObjects1(s);
-	registerTypesMapObjects2(s);
-	registerTypesMapObjectTypes(s);
-	registerTypesClientPacks1(s);
-	registerTypesClientPacks2(s);
+	registerTypesMapObjects(s);
+	registerTypesClientPacks(s);
 	registerTypesServerPacks(s);
 	registerTypesLobbyPacks(s);
 }
 
-#ifndef INSTANTIATE_REGISTER_TYPES_HERE
-
-extern template DLL_LINKAGE void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
-extern template DLL_LINKAGE void registerTypes<BinarySerializer>(BinarySerializer & s);
-extern template DLL_LINKAGE void registerTypes<CTypeList>(CTypeList & s);
-
-#endif
-
-
 VCMI_LIB_NAMESPACE_END

+ 125 - 0
lib/registerTypes/RegisterTypesClientPacks.h

@@ -0,0 +1,125 @@
+/*
+ * RegisterTypesClientPacks.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../networkPacks/PacksForClient.h"
+#include "../networkPacks/PacksForClientBattle.h"
+#include "../networkPacks/SetStackEffect.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+template<typename Serializer>
+void registerTypesClientPacks(Serializer &s)
+{
+	s.template registerType<CPack, CPackForClient>();
+
+	s.template registerType<CPackForClient, PackageApplied>();
+	s.template registerType<CPackForClient, SystemMessage>();
+	s.template registerType<CPackForClient, PlayerBlocked>();
+	s.template registerType<CPackForClient, PlayerCheated>();
+	s.template registerType<CPackForClient, PlayerStartsTurn>();
+	s.template registerType<CPackForClient, DaysWithoutTown>();
+	s.template registerType<CPackForClient, TurnTimeUpdate>();
+	s.template registerType<CPackForClient, SetResources>();
+	s.template registerType<CPackForClient, SetPrimSkill>();
+	s.template registerType<CPackForClient, SetSecSkill>();
+	s.template registerType<CPackForClient, HeroVisitCastle>();
+	s.template registerType<CPackForClient, ChangeSpells>();
+	s.template registerType<CPackForClient, SetMana>();
+	s.template registerType<CPackForClient, SetMovePoints>();
+	s.template registerType<CPackForClient, FoWChange>();
+	s.template registerType<CPackForClient, SetAvailableHero>();
+	s.template registerType<CPackForClient, GiveBonus>();
+	s.template registerType<CPackForClient, ChangeObjPos>();
+	s.template registerType<CPackForClient, PlayerEndsTurn>();
+	s.template registerType<CPackForClient, PlayerEndsGame>();
+	s.template registerType<CPackForClient, PlayerReinitInterface>();
+	s.template registerType<CPackForClient, RemoveBonus>();
+	s.template registerType<CPackForClient, UpdateArtHandlerLists>();
+	s.template registerType<CPackForClient, UpdateMapEvents>();
+	s.template registerType<CPackForClient, UpdateCastleEvents>();
+	s.template registerType<CPackForClient, ChangeFormation>();
+	s.template registerType<CPackForClient, RemoveObject>();
+	s.template registerType<CPackForClient, TryMoveHero>();
+	s.template registerType<CPackForClient, NewStructures>();
+	s.template registerType<CPackForClient, RazeStructures>();
+	s.template registerType<CPackForClient, SetAvailableCreatures>();
+	s.template registerType<CPackForClient, SetHeroesInTown>();
+	s.template registerType<CPackForClient, HeroRecruited>();
+	s.template registerType<CPackForClient, GiveHero>();
+	s.template registerType<CPackForClient, NewTurn>();
+	s.template registerType<CPackForClient, InfoWindow>();
+	s.template registerType<CPackForClient, SetObjectProperty>();
+	s.template registerType<CPackForClient, AdvmapSpellCast>();
+	s.template registerType<CPackForClient, OpenWindow>();
+	s.template registerType<CPackForClient, NewObject>();
+	s.template registerType<CPackForClient, NewArtifact>();
+	s.template registerType<CPackForClient, AddQuest>();
+	s.template registerType<CPackForClient, SetAvailableArtifacts>();
+	s.template registerType<CPackForClient, CenterView>();
+	s.template registerType<CPackForClient, HeroVisit>();
+	s.template registerType<CPackForClient, SetCommanderProperty>();
+	s.template registerType<CPackForClient, ChangeObjectVisitors>();
+	s.template registerType<CPackForClient, ShowWorldViewEx>();
+	s.template registerType<CPackForClient, PrepareHeroLevelUp>();
+	s.template registerType<CPackForClient, EntitiesChanged>();
+	s.template registerType<CPackForClient, BattleStart>();
+	s.template registerType<CPackForClient, BattleNextRound>();
+	s.template registerType<CPackForClient, BattleSetActiveStack>();
+	s.template registerType<CPackForClient, BattleResult>();
+	s.template registerType<CPackForClient, BattleResultAccepted>();
+	s.template registerType<CPackForClient, BattleCancelled>();
+	s.template registerType<CPackForClient, BattleLogMessage>();
+	s.template registerType<CPackForClient, BattleStackMoved>();
+	s.template registerType<CPackForClient, BattleAttack>();
+	s.template registerType<CPackForClient, StartAction>();
+	s.template registerType<CPackForClient, EndAction>();
+	s.template registerType<CPackForClient, BattleSpellCast>();
+	s.template registerType<CPackForClient, SetStackEffect>();
+	s.template registerType<CPackForClient, BattleTriggerEffect>();
+	s.template registerType<CPackForClient, BattleUpdateGateState>();
+	s.template registerType<CPackForClient, BattleSetStackProperty>();
+	s.template registerType<CPackForClient, StacksInjured>();
+	s.template registerType<CPackForClient, BattleResultsApplied>();
+	s.template registerType<CPackForClient, BattleUnitsChanged>();
+	s.template registerType<CPackForClient, BattleObstaclesChanged>();
+	s.template registerType<CPackForClient, CatapultAttack>();
+
+	s.template registerType<CPackForClient, Query>();
+	s.template registerType<Query, HeroLevelUp>();
+	s.template registerType<Query, CommanderLevelUp>();
+	s.template registerType<Query, BlockingDialog>();
+	s.template registerType<Query, GarrisonDialog>();
+	s.template registerType<Query, ExchangeDialog>();
+	s.template registerType<Query, TeleportDialog>();
+	s.template registerType<Query, MapObjectSelectDialog>();
+
+	s.template registerType<CPackForClient, CGarrisonOperationPack>();
+	s.template registerType<CGarrisonOperationPack, ChangeStackCount>();
+	s.template registerType<CGarrisonOperationPack, SetStackType>();
+	s.template registerType<CGarrisonOperationPack, EraseStack>();
+	s.template registerType<CGarrisonOperationPack, SwapStacks>();
+	s.template registerType<CGarrisonOperationPack, InsertNewStack>();
+	s.template registerType<CGarrisonOperationPack, RebalanceStacks>();
+
+	s.template registerType<CPackForClient, CArtifactOperationPack>();
+	s.template registerType<CArtifactOperationPack, PutArtifact>();
+	s.template registerType<CArtifactOperationPack, EraseArtifact>();
+	s.template registerType<CArtifactOperationPack, MoveArtifact>();
+	s.template registerType<CArtifactOperationPack, AssembledArtifact>();
+	s.template registerType<CArtifactOperationPack, DisassembledArtifact>();
+	s.template registerType<CArtifactOperationPack, BulkMoveArtifacts>();
+
+	s.template registerType<CPackForClient, PlayerMessageClient>();
+	s.template registerType<CGarrisonOperationPack, BulkRebalanceStacks>();
+	s.template registerType<CGarrisonOperationPack, BulkSmartRebalanceStacks>();
+}
+
+VCMI_LIB_NAMESPACE_END

+ 62 - 0
lib/registerTypes/RegisterTypesLobbyPacks.h

@@ -0,0 +1,62 @@
+/*
+ * RegisterTypesLobbyPacks.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../networkPacks/PacksForLobby.h"
+#include "../gameState/CGameState.h"
+#include "../campaign/CampaignState.h"
+#include "../mapping/CMapInfo.h"
+#include "../rmg/CMapGenOptions.h"
+#include "../gameState/TavernHeroesPool.h"
+#include "../gameState/CGameStateCampaign.h"
+#include "../mapping/CMap.h"
+#include "../TerrainHandler.h"
+#include "../RiverHandler.h"
+#include "../RoadHandler.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+template<typename Serializer>
+void registerTypesLobbyPacks(Serializer &s)
+{
+	s.template registerType<CPack, CPackForLobby>();
+	s.template registerType<CPackForLobby, CLobbyPackToPropagate>();
+	s.template registerType<CPackForLobby, CLobbyPackToServer>();
+
+	// Any client can sent
+	s.template registerType<CLobbyPackToPropagate, LobbyClientConnected>();
+	s.template registerType<CLobbyPackToPropagate, LobbyClientDisconnected>();
+	s.template registerType<CLobbyPackToPropagate, LobbyChatMessage>();
+	// Only host client send
+	s.template registerType<CLobbyPackToPropagate, LobbyGuiAction>();
+	s.template registerType<CLobbyPackToPropagate, LobbyLoadProgress>();
+	s.template registerType<CLobbyPackToPropagate, LobbyEndGame>();
+	s.template registerType<CLobbyPackToPropagate, LobbyStartGame>();
+	s.template registerType<CLobbyPackToPropagate, LobbyChangeHost>();
+	// Only server send
+	s.template registerType<CLobbyPackToPropagate, LobbyUpdateState>();
+	s.template registerType<CLobbyPackToPropagate, LobbyShowMessage>();
+
+	// For client with permissions
+	s.template registerType<CLobbyPackToServer, LobbyChangePlayerOption>();
+	// Only for host client
+	s.template registerType<CLobbyPackToServer, LobbySetMap>();
+	s.template registerType<CLobbyPackToServer, LobbySetCampaign>();
+	s.template registerType<CLobbyPackToServer, LobbySetCampaignMap>();
+	s.template registerType<CLobbyPackToServer, LobbySetCampaignBonus>();
+	s.template registerType<CLobbyPackToServer, LobbySetPlayer>();
+	s.template registerType<CLobbyPackToServer, LobbySetPlayerName>();
+	s.template registerType<CLobbyPackToServer, LobbySetTurnTime>();
+	s.template registerType<CLobbyPackToServer, LobbySetSimturns>();
+	s.template registerType<CLobbyPackToServer, LobbySetDifficulty>();
+	s.template registerType<CLobbyPackToServer, LobbyForceSetPlayer>();
+}
+
+VCMI_LIB_NAMESPACE_END

+ 137 - 0
lib/registerTypes/RegisterTypesMapObjects.h

@@ -0,0 +1,137 @@
+/*
+ * RegisterTypesMapObjects.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../mapObjectConstructors/CBankInstanceConstructor.h"
+#include "../mapObjects/MapObjects.h"
+#include "../mapObjects/CGCreature.h"
+#include "../mapObjects/CGTownBuilding.h"
+#include "../mapObjects/ObjectTemplate.h"
+#include "../battle/BattleInfo.h"
+#include "../battle/CObstacleInstance.h"
+#include "../bonuses/Limiters.h"
+#include "../bonuses/Updaters.h"
+#include "../bonuses/Propagators.h"
+#include "../CPlayerState.h"
+#include "../CStack.h"
+#include "../CHeroHandler.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+template<typename Serializer>
+void registerTypesMapObjects(Serializer &s)
+{
+	//////////////////////////////////////////////////////////////////////////
+	// Adventure map objects
+	//////////////////////////////////////////////////////////////////////////
+	s.template registerType<IObjectInterface, CGObjectInstance>();
+
+	// Non-armed objects
+	s.template registerType<CGObjectInstance, CGTeleport>();
+		s.template registerType<CGTeleport, CGMonolith>();
+			s.template registerType<CGMonolith, CGSubterraneanGate>();
+			s.template registerType<CGMonolith, CGWhirlpool>();
+	s.template registerType<CGObjectInstance, CGSignBottle>();
+	s.template registerType<CGObjectInstance, CGKeys>();
+		s.template registerType<CGKeys, CGKeymasterTent>();
+		s.template registerType<CGKeys, CGBorderGuard>(); s.template registerType<IQuestObject, CGBorderGuard>();
+			s.template registerType<CGBorderGuard, CGBorderGate>();
+	s.template registerType<CGObjectInstance, CGBoat>();
+	s.template registerType<CGObjectInstance, CGMagi>();
+	s.template registerType<CGObjectInstance, CGSirens>();
+	s.template registerType<CGObjectInstance, CGShipyard>();
+	s.template registerType<CGObjectInstance, CGDenOfthieves>();
+	s.template registerType<CGObjectInstance, CGLighthouse>();
+	s.template registerType<CGObjectInstance, CGTerrainPatch>();
+	s.template registerType<CGObjectInstance, HillFort>();
+	s.template registerType<CGObjectInstance, CGMarket>();
+		s.template registerType<CGMarket, CGBlackMarket>();
+		s.template registerType<CGMarket, CGUniversity>();
+	s.template registerType<CGObjectInstance, CGHeroPlaceholder>();
+
+	s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();
+
+	// Armed objects
+	s.template registerType<CArmedInstance, CGHeroInstance>(); s.template registerType<CArtifactSet, CGHeroInstance>();
+	s.template registerType<CArmedInstance, CGDwelling>();
+		s.template registerType<CGDwelling, CGTownInstance>();
+	s.template registerType<CArmedInstance, CGPandoraBox>();
+		s.template registerType<CGPandoraBox, CGEvent>();
+	s.template registerType<CArmedInstance, CGCreature>();
+	s.template registerType<CArmedInstance, CGGarrison>();
+	s.template registerType<CArmedInstance, CGArtifact>();
+	s.template registerType<CArmedInstance, CGResource>();
+	s.template registerType<CArmedInstance, CGMine>();
+	s.template registerType<CArmedInstance, CBank>();
+	s.template registerType<CArmedInstance, CGSeerHut>(); s.template registerType<IQuestObject, CGSeerHut>();
+	s.template registerType<CGSeerHut, CGQuestGuard>();
+
+	s.template registerType<IUpdater, GrowsWithLevelUpdater>();
+	s.template registerType<IUpdater, TimesHeroLevelUpdater>();
+	s.template registerType<IUpdater, TimesStackLevelUpdater>();
+	s.template registerType<IUpdater, OwnerUpdater>();
+	s.template registerType<IUpdater, ArmyMovementUpdater>();
+
+	s.template registerType<ILimiter, AnyOfLimiter>();
+	s.template registerType<ILimiter, NoneOfLimiter>();
+	s.template registerType<ILimiter, OppositeSideLimiter>();
+	//new types (other than netpacks) must register here
+	//order of type registration is critical for loading old savegames
+
+	//Other object-related
+	s.template registerType<IObjectInterface, CGTownBuilding>();
+		s.template registerType<CGTownBuilding, CTownBonus>();
+		s.template registerType<CGTownBuilding, COPWBonus>();
+		s.template registerType<CGTownBuilding, CTownRewardableBuilding>();
+
+	s.template registerType<CGObjectInstance, CRewardableObject>();
+
+	s.template registerType<CGObjectInstance, CTeamVisited>();
+		s.template registerType<CTeamVisited, CGObelisk>();
+
+	//end of objects
+
+	//////////////////////////////////////////////////////////////////////////
+	// Bonus system
+	//////////////////////////////////////////////////////////////////////////
+	//s.template registerType<IPropagator>();
+	s.template registerType<IPropagator, CPropagatorNodeType>();
+
+	// Limiters
+	//s.template registerType<ILimiter>();
+	s.template registerType<ILimiter, AllOfLimiter>();
+	s.template registerType<ILimiter, CCreatureTypeLimiter>();
+	s.template registerType<ILimiter, HasAnotherBonusLimiter>();
+	s.template registerType<ILimiter, CreatureTerrainLimiter>();
+	s.template registerType<ILimiter, FactionLimiter>();
+	s.template registerType<ILimiter, CreatureLevelLimiter>();
+	s.template registerType<ILimiter, CreatureAlignmentLimiter>();
+	s.template registerType<ILimiter, RankRangeLimiter>();
+	s.template registerType<ILimiter, UnitOnHexLimiter>();
+
+//	s.template registerType<CBonusSystemNode>();
+	s.template registerType<CBonusSystemNode, CArtifact>();
+	s.template registerType<CBonusSystemNode, CCreature>();
+	s.template registerType<CBonusSystemNode, CStackInstance>();
+	s.template registerType<CStackInstance, CCommanderInstance>();
+	s.template registerType<CBonusSystemNode, PlayerState>();
+	s.template registerType<CBonusSystemNode, TeamState>();
+	//s.template registerType<CGameState>(); //TODO
+	//s.template registerType<CArmedInstance>();
+	s.template registerType<CBonusSystemNode, CStack>();
+	s.template registerType<CBonusSystemNode, BattleInfo>();
+	//s.template registerType<QuestInfo>();
+	s.template registerType<CBonusSystemNode, CArtifactInstance>();
+
+	//s.template registerType<CObstacleInstance>();
+		s.template registerType<CObstacleInstance, SpellCreatedObstacle>();
+}
+
+VCMI_LIB_NAMESPACE_END

+ 56 - 0
lib/registerTypes/RegisterTypesServerPacks.h

@@ -0,0 +1,56 @@
+/*
+ * RegisterTypesServerPacks.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../networkPacks/PacksForServer.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class BinarySerializer;
+class BinaryDeserializer;
+class CTypeList;
+
+template<typename Serializer>
+void registerTypesServerPacks(Serializer &s)
+{
+	s.template registerType<CPack, CPackForServer>();
+	s.template registerType<CPackForServer, EndTurn>();
+	s.template registerType<CPackForServer, DismissHero>();
+	s.template registerType<CPackForServer, MoveHero>();
+	s.template registerType<CPackForServer, ArrangeStacks>();
+	s.template registerType<CPackForServer, DisbandCreature>();
+	s.template registerType<CPackForServer, BuildStructure>();
+	s.template registerType<CPackForServer, RecruitCreatures>();
+	s.template registerType<CPackForServer, UpgradeCreature>();
+	s.template registerType<CPackForServer, GarrisonHeroSwap>();
+	s.template registerType<CPackForServer, ExchangeArtifacts>();
+	s.template registerType<CPackForServer, AssembleArtifacts>();
+	s.template registerType<CPackForServer, BuyArtifact>();
+	s.template registerType<CPackForServer, TradeOnMarketplace>();
+	s.template registerType<CPackForServer, SetFormation>();
+	s.template registerType<CPackForServer, HireHero>();
+	s.template registerType<CPackForServer, BuildBoat>();
+	s.template registerType<CPackForServer, QueryReply>();
+	s.template registerType<CPackForServer, MakeAction>();
+	s.template registerType<CPackForServer, DigWithHero>();
+	s.template registerType<CPackForServer, CastAdvSpell>();
+	s.template registerType<CPackForServer, CastleTeleportHero>();
+	s.template registerType<CPackForServer, SaveGame>();
+	s.template registerType<CPackForServer, PlayerMessage>();
+	s.template registerType<CPackForServer, BulkSplitStack>();
+	s.template registerType<CPackForServer, BulkMergeStacks>();
+	s.template registerType<CPackForServer, BulkSmartSplitStack>();
+	s.template registerType<CPackForServer, BulkMoveArmy>();
+	s.template registerType<CPackForServer, BulkExchangeArtifacts>();
+	s.template registerType<CPackForServer, EraseArtifactByClient>();
+	s.template registerType<CPackForServer, GamePause>();
+}
+
+VCMI_LIB_NAMESPACE_END

+ 0 - 33
lib/registerTypes/TypesClientPacks1.cpp

@@ -1,33 +0,0 @@
-/*
- * TypesClientPacks1.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-
-template void registerTypesClientPacks1<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesClientPacks1<BinarySerializer>(BinarySerializer & s);
-template void registerTypesClientPacks1<CTypeList>(CTypeList & s);
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 37
lib/registerTypes/TypesClientPacks2.cpp

@@ -1,37 +0,0 @@
-/*
- * TypesClientPacks2.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../CStack.h"
-#include "../battle/BattleInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-
-template void registerTypesClientPacks2<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesClientPacks2<BinarySerializer>(BinarySerializer & s);
-template void registerTypesClientPacks2<CTypeList>(CTypeList & s);
-
-
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 43
lib/registerTypes/TypesLobbyPacks.cpp

@@ -1,43 +0,0 @@
-/*
- * TypesLobbyPacks.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../mapping/CMapInfo.h"
-#include "../StartInfo.h"
-#include "../gameState/CGameState.h"
-#include "../gameState/CGameStateCampaign.h"
-#include "../gameState/TavernHeroesPool.h"
-#include "../mapping/CMap.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-#include "../RoadHandler.h"
-#include "../RiverHandler.h"
-#include "../TerrainHandler.h"
-#include "../campaign/CampaignState.h"
-#include "../rmg/CMapGenOptions.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-template void registerTypesLobbyPacks<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesLobbyPacks<BinarySerializer>(BinarySerializer & s);
-template void registerTypesLobbyPacks<CTypeList>(CTypeList & s);
-
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 34
lib/registerTypes/TypesMapObjects1.cpp

@@ -1,34 +0,0 @@
-/*
- * TypesMapObjects1.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-template void registerTypesMapObjects1<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesMapObjects1<BinarySerializer>(BinarySerializer & s);
-template void registerTypesMapObjects1<CTypeList>(CTypeList & s);
-
-
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 36
lib/registerTypes/TypesMapObjects2.cpp

@@ -1,36 +0,0 @@
-/*
- * TypesMapObjects2.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../CStack.h"
-#include "../battle/BattleInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-
-template void registerTypesMapObjects2<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesMapObjects2<BinarySerializer>(BinarySerializer & s);
-template void registerTypesMapObjects2<CTypeList>(CTypeList & s);
-
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 32
lib/registerTypes/TypesMapObjects3.cpp

@@ -1,32 +0,0 @@
-/*
- * TypesMapObjects3.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-template void registerTypesMapObjectTypes<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesMapObjectTypes<BinarySerializer>(BinarySerializer & s);
-template void registerTypesMapObjectTypes<CTypeList>(CTypeList & s);
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 32
lib/registerTypes/TypesServerPacks.cpp

@@ -1,32 +0,0 @@
-/*
- * TypesServerPacks.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "RegisterTypes.h"
-
-#include "../StartInfo.h"
-#include "../mapObjects/CObjectHandler.h"
-#include "../CCreatureHandler.h"
-#include "../VCMI_Lib.h"
-#include "../CArtHandler.h"
-#include "../CHeroHandler.h"
-#include "../spells/CSpellHandler.h"
-#include "../CTownHandler.h"
-
-#include "../serializer/BinaryDeserializer.h"
-#include "../serializer/BinarySerializer.h"
-#include "../serializer/CTypeList.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-template void registerTypesServerPacks<BinaryDeserializer>(BinaryDeserializer & s);
-template void registerTypesServerPacks<BinarySerializer>(BinarySerializer & s);
-template void registerTypesServerPacks<CTypeList>(CTypeList & s);
-
-VCMI_LIB_NAMESPACE_END

+ 6 - 85
lib/serializer/BinaryDeserializer.cpp

@@ -9,97 +9,18 @@
  */
 #include "StdInc.h"
 #include "BinaryDeserializer.h"
-
 #include "../registerTypes/RegisterTypes.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-extern template void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
-
-CLoadFile::CLoadFile(const boost::filesystem::path & fname, int minimalVersion)
-	: serializer(this)
-{
-	registerTypes(serializer);
-	openNextFile(fname, minimalVersion);
-}
-
-//must be instantiated in .cpp file for access to complete types of all member fields
-CLoadFile::~CLoadFile() = default;
-
-int CLoadFile::read(void * data, unsigned size)
-{
-	sfile->read(reinterpret_cast<char *>(data), size);
-	return size;
-}
-
-void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalVersion)
-{
-	assert(!serializer.reverseEndianess);
-	assert(minimalVersion <= SERIALIZATION_VERSION);
-
-	try
-	{
-		fName = fname.string();
-		sfile = std::make_unique<std::fstream>(fname.c_str(), std::ios::in | std::ios::binary);
-		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
-
-		if(!(*sfile))
-			THROW_FORMAT("Error: cannot open to read %s!", fName);
-
-		//we can read
-		char buffer[4];
-		sfile->read(buffer, 4);
-		if(std::memcmp(buffer, "VCMI", 4) != 0)
-			THROW_FORMAT("Error: not a VCMI file(%s)!", fName);
-
-		serializer & serializer.fileVersion;
-		if(serializer.fileVersion < minimalVersion)
-			THROW_FORMAT("Error: too old file format (%s)!", fName);
-
-		if(serializer.fileVersion > SERIALIZATION_VERSION)
-		{
-			logGlobal->warn("Warning format version mismatch: found %d when current is %d! (file %s)\n", serializer.fileVersion, SERIALIZATION_VERSION , fName);
-
-			auto * versionptr = reinterpret_cast<char *>(&serializer.fileVersion);
-			std::reverse(versionptr, versionptr + 4);
-			logGlobal->warn("Version number reversed is %x, checking...", serializer.fileVersion);
-
-			if(serializer.fileVersion == SERIALIZATION_VERSION)
-			{
-				logGlobal->warn("%s seems to have different endianness! Entering reversing mode.", fname.string());
-				serializer.reverseEndianess = true;
-			}
-			else
-				THROW_FORMAT("Error: too new file format (%s)!", fName);
-		}
-	}
-	catch(...)
-	{
-		clear(); //if anything went wrong, we delete file and rethrow
-		throw;
-	}
-}
-
-void CLoadFile::reportState(vstd::CLoggerBase * out)
-{
-	out->debug("CLoadFile");
-	if(!!sfile && *sfile)
-		out->debug("\tOpened %s Position: %d", fName, sfile->tellg());
-}
-
-void CLoadFile::clear()
+BinaryDeserializer::BinaryDeserializer(IBinaryReader * r): CLoaderBase(r)
 {
-	sfile = nullptr;
-	fName.clear();
-	serializer.fileVersion = 0;
-}
+	saving = false;
+	fileVersion = 0;
+	smartPointerSerialization = true;
+	reverseEndianess = false;
 
-void CLoadFile::checkMagicBytes(const std::string &text)
-{
-	std::string loaded = text;
-	read((void *)loaded.data(), static_cast<unsigned int>(text.length()));
-	if(loaded != text)
-		throw std::runtime_error("Magic bytes doesn't match!");
+	registerTypes(*this);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 54 - 129
lib/serializer/BinaryDeserializer.h

@@ -9,17 +9,12 @@
  */
 #pragma once
 
-#include <boost/mpl/vector.hpp>
-#include <boost/mpl/for_each.hpp>
-
+#include "CSerializer.h"
 #include "CTypeList.h"
 #include "../mapObjects/CGHeroInstance.h"
-#include "../../Global.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CStackInstance;
-
 class DLL_LINKAGE CLoaderBase
 {
 protected:
@@ -37,41 +32,6 @@ public:
 /// Effectively revesed version of BinarySerializer
 class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 {
-	template<typename Variant, typename Source>
-	struct VariantLoaderHelper
-	{
-		Source & source;
-		std::vector<std::function<Variant()>> funcs;
-
-		template <class V>
-		struct mpl_types_impl;
-
-		template <class... Ts>
-		struct mpl_types_impl<std::variant<Ts...>> {
-			using type = boost::mpl::vector<Ts...>;
-		};
-
-		template <class V>
-		using mpl_types = typename mpl_types_impl<V>::type;
-
-		VariantLoaderHelper(Source & source):
-			source(source)
-		{
-			boost::mpl::for_each<mpl_types<Variant>>(std::ref(*this));
-		}
-
-		template<typename Type>
-		void operator()(Type)
-		{
-			funcs.push_back([&]() -> Variant
-			{
-				Type obj;
-				source.load(obj);
-				return Variant(obj);
-			});
-		}
-	};
-
 	template<typename Ser,typename T>
 	struct LoadIfStackInstance
 	{
@@ -138,40 +98,40 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 		return length;
 	}
 
-	template <typename T> class CPointerLoader;
+	template <typename Type> class CPointerLoader;
 
-	class CBasicPointerLoader
+	class IPointerLoader
 	{
 	public:
-		virtual const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
-		virtual ~CBasicPointerLoader(){}
+		virtual void * loadPtr(CLoaderBase &ar, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
+		virtual ~IPointerLoader() = default;
 
-		template<typename T> static CBasicPointerLoader *getApplier(const T * t=nullptr)
+		template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr)
 		{
-			return new CPointerLoader<T>();
+			return new CPointerLoader<Type>();
 		}
 	};
 
-	template <typename T> class CPointerLoader : public CBasicPointerLoader
+	template <typename Type>
+	class CPointerLoader : public IPointerLoader
 	{
 	public:
-		const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const override //data is pointer to the ACTUAL POINTER
+		void * loadPtr(CLoaderBase &ar, ui32 pid) const override //data is pointer to the ACTUAL POINTER
 		{
 			auto & s = static_cast<BinaryDeserializer &>(ar);
-			T *&ptr = *static_cast<T**>(data);
 
 			//create new object under pointer
-			typedef typename std::remove_pointer<T>::type npT;
-			ptr = ClassObjectCreator<npT>::invoke(); //does new npT or throws for abstract classes
+			Type * ptr = ClassObjectCreator<Type>::invoke(); //does new npT or throws for abstract classes
 			s.ptrAllocated(ptr, pid);
-			//T is most derived known type, it's time to call actual serialize
+
 			assert(s.fileVersion != 0);
 			ptr->serialize(s,s.fileVersion);
-			return &typeid(T);
+
+			return static_cast<void*>(ptr);
 		}
 	};
 
-	CApplier<CBasicPointerLoader> applier;
+	CApplier<IPointerLoader> applier;
 
 	int write(const void * data, unsigned size);
 
@@ -181,17 +141,11 @@ public:
 
 	std::map<ui32, void*> loadedPointers;
 	std::map<ui32, const std::type_info*> loadedPointersTypes;
-	std::map<const void*, std::any> loadedSharedPointers;
+	std::map<const void*, std::shared_ptr<void>> loadedSharedPointers;
 	bool smartPointerSerialization;
 	bool saving;
 
-	BinaryDeserializer(IBinaryReader * r): CLoaderBase(r)
-	{
-		saving = false;
-		fileVersion = 0;
-		smartPointerSerialization = true;
-		reverseEndianess = false;
-	}
+	BinaryDeserializer(IBinaryReader * r);
 
 	template<class T>
 	BinaryDeserializer & operator&(T & t)
@@ -264,14 +218,33 @@ public:
 	template < typename T, typename std::enable_if < std::is_pointer<T>::value, int  >::type = 0 >
 	void load(T &data)
 	{
-		ui8 hlp;
-		load( hlp );
-		if(!hlp)
+		bool isNull;
+		load( isNull );
+		if(isNull)
 		{
 			data = nullptr;
 			return;
 		}
 
+		loadPointerImpl(data);
+	}
+
+	template < typename T, typename std::enable_if < std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int  >::type = 0 >
+	void loadPointerImpl(T &data)
+	{
+		using DataType = std::remove_pointer_t<T>;
+
+		typename DataType::IdentifierType index;
+		load(index);
+
+		auto * constEntity = index.toEntity(VLC);
+		auto * constData = dynamic_cast<const DataType *>(constEntity);
+		data = const_cast<DataType *>(constData);
+	}
+
+	template < typename T, typename std::enable_if < !std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int  >::type = 0 >
+	void loadPointerImpl(T &data)
+	{
 		if(reader->smartVectorMembersSerialization)
 		{
 			typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType; //eg: const CGHeroInstance * => CGHeroInstance
@@ -307,11 +280,10 @@ public:
 				// We already got this pointer
 				// Cast it in case we are loading it to a non-first base pointer
 				assert(loadedPointersTypes.count(pid));
-				data = reinterpret_cast<T>(typeList.castRaw(i->second, loadedPointersTypes.at(pid), &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
+				data = static_cast<T>(i->second);
 				return;
 			}
 		}
-
 		//get type id
 		ui16 tid;
 		load( tid );
@@ -333,8 +305,7 @@ public:
 				data = nullptr;
 				return;
 			}
-			auto typeInfo = app->loadPtr(*this,&data, pid);
-			data = reinterpret_cast<T>(typeList.castRaw((void*)data, typeInfo, &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
+			data = static_cast<T>(app->loadPtr(*this, pid));
 		}
 	}
 
@@ -360,7 +331,7 @@ public:
 		NonConstT *internalPtr;
 		load(internalPtr);
 
-		void *internalPtrDerived = typeList.castToMostDerived(internalPtr);
+		void * internalPtrDerived = static_cast<void*>(internalPtr);
 
 		if(internalPtr)
 		{
@@ -369,35 +340,13 @@ public:
 			{
 				// This pointers is already loaded. The "data" needs to be pointed to it,
 				// so their shared state is actually shared.
-				try
-				{
-					auto actualType = typeList.getTypeInfo(internalPtr);
-					auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
-					if(*actualType == *typeWeNeedToReturn)
-					{
-						// No casting needed, just unpack already stored shared_ptr and return it
-						data = std::any_cast<std::shared_ptr<T>>(itr->second);
-					}
-					else
-					{
-						// We need to perform series of casts
-						auto ret = typeList.castShared(itr->second, actualType, typeWeNeedToReturn);
-						data = std::any_cast<std::shared_ptr<T>>(ret);
-					}
-				}
-				catch(std::exception &e)
-				{
-					logGlobal->error(e.what());
-					logGlobal->error("Failed to cast stored shared ptr. Real type: %s. Needed type %s. FIXME FIXME FIXME", itr->second.type().name(), typeid(std::shared_ptr<T>).name());
-					//TODO scenario with inheritance -> we can have stored ptr to base and load ptr to derived (or vice versa)
-					throw;
-				}
+				data = std::static_pointer_cast<T>(itr->second);
 			}
 			else
 			{
 				auto hlp = std::shared_ptr<NonConstT>(internalPtr);
 				data = hlp;
-				loadedSharedPointers[internalPtrDerived] = typeList.castSharedToMostDerived(hlp);
+				loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<void>(hlp);
 			}
 		}
 		else
@@ -510,17 +459,19 @@ public:
 		this->read((void*)data.c_str(),length);
 	}
 
-	template<typename T0, typename... TN>
-	void load(std::variant<T0, TN...> & data)
+	template<typename... TN>
+	void load(std::variant<TN...> & data)
 	{
-		using TVariant = std::variant<T0, TN...>;
-
-		VariantLoaderHelper<TVariant, BinaryDeserializer> loader(*this);
-
 		si32 which;
 		load( which );
-		assert(which < loader.funcs.size());
-		data = loader.funcs.at(which)();
+		assert(which < sizeof...(TN));
+
+		// Create array of variants that contains all default-constructed alternatives
+		const std::variant<TN...> table[] = { TN{ }... };
+		// use appropriate alternative for result
+		data = table[which];
+		// perform actual load via std::visit dispatch
+		std::visit([&](auto& o) { load(o); }, data);
 	}
 
 	template<typename T>
@@ -579,30 +530,4 @@ public:
 	}
 };
 
-class DLL_LINKAGE CLoadFile : public IBinaryReader
-{
-public:
-	BinaryDeserializer serializer;
-
-	std::string fName;
-	std::unique_ptr<std::fstream> sfile;
-
-	CLoadFile(const boost::filesystem::path & fname, int minimalVersion = SERIALIZATION_VERSION); //throws!
-	virtual ~CLoadFile();
-	int read(void * data, unsigned size) override; //throws!
-
-	void openNextFile(const boost::filesystem::path & fname, int minimalVersion); //throws!
-	void clear();
-	void reportState(vstd::CLoggerBase * out) override;
-
-	void checkMagicBytes(const std::string & text);
-
-	template<class T>
-	CLoadFile & operator>>(T &t)
-	{
-		serializer & t;
-		return * this;
-	}
-};
-
 VCMI_LIB_NAMESPACE_END

+ 4 - 58
lib/serializer/BinarySerializer.cpp

@@ -9,69 +9,15 @@
  */
 #include "StdInc.h"
 #include "BinarySerializer.h"
-
 #include "../registerTypes/RegisterTypes.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-extern template void registerTypes<BinarySerializer>(BinarySerializer & s);
-
-CSaveFile::CSaveFile(const boost::filesystem::path &fname)
-	: serializer(this)
-{
-	registerTypes(serializer);
-	openNextFile(fname);
-}
-
-//must be instantiated in .cpp file for access to complete types of all member fields
-CSaveFile::~CSaveFile() = default;
-
-int CSaveFile::write(const void * data, unsigned size)
-{
-	sfile->write((char *)data,size);
-	return size;
-}
-
-void CSaveFile::openNextFile(const boost::filesystem::path &fname)
-{
-	fName = fname;
-	try
-	{
-		sfile = std::make_unique<std::fstream>(fname.c_str(), std::ios::out | std::ios::binary);
-		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
-
-		if(!(*sfile))
-			THROW_FORMAT("Error: cannot open to write %s!", fname);
-
-		sfile->write("VCMI",4); //write magic identifier
-		serializer & SERIALIZATION_VERSION; //write format version
-	}
-	catch(...)
-	{
-		logGlobal->error("Failed to save to %s", fname.string());
-		clear();
-		throw;
-	}
-}
-
-void CSaveFile::reportState(vstd::CLoggerBase * out)
-{
-	out->debug("CSaveFile");
-	if(sfile.get() && *sfile)
-	{
-		out->debug("\tOpened %s \tPosition: %d", fName, sfile->tellp());
-	}
-}
-
-void CSaveFile::clear()
-{
-	fName.clear();
-	sfile = nullptr;
-}
-
-void CSaveFile::putMagicBytes(const std::string &text)
+BinarySerializer::BinarySerializer(IBinaryWriter * w): CSaverBase(w)
 {
-	write(text.c_str(), static_cast<unsigned int>(text.length()));
+	saving=true;
+	smartPointerSerialization = true;
+	registerTypes(*this);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 23 - 38
lib/serializer/BinarySerializer.h

@@ -9,6 +9,7 @@
  */
 #pragma once
 
+#include "CSerializer.h"
 #include "CTypeList.h"
 #include "../mapObjects/CArmedInstance.h"
 
@@ -114,11 +115,7 @@ public:
 	bool smartPointerSerialization;
 	bool saving;
 
-	BinarySerializer(IBinaryWriter * w): CSaverBase(w)
-	{
-		saving=true;
-		smartPointerSerialization = true;
-	}
+	BinarySerializer(IBinaryWriter * w);
 
 	template<typename Base, typename Derived>
 	void registerType(const Base * b = nullptr, const Derived * d = nullptr)
@@ -174,16 +171,30 @@ public:
 	void save(const T &data)
 	{
 		//write if pointer is not nullptr
-		ui8 hlp = (data!=nullptr);
-		save(hlp);
+		bool isNull = (data == nullptr);
+		save(isNull);
 
 		//if pointer is nullptr then we don't need anything more...
-		if(!hlp)
+		if(data == nullptr)
 			return;
 
+		savePointerImpl(data);
+	}
+
+	template < typename T, typename std::enable_if < std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int  >::type = 0 >
+	void savePointerImpl(const T &data)
+	{
+		auto index = data->getId();
+		save(index);
+	}
+
+	template < typename T, typename std::enable_if < !std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int  >::type = 0 >
+	void savePointerImpl(const T &data)
+	{
+		typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
+
 		if(writer->smartVectorMembersSerialization)
 		{
-			typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
 			typedef typename VectorizedTypeFor<TObjectType>::type VType;
 			typedef typename VectorizedIDType<TObjectType>::type IDType;
 
@@ -207,7 +218,7 @@ public:
 		{
 			// We might have an object that has multiple inheritance and store it via the non-first base pointer.
 			// Therefore, all pointers need to be normalized to the actual object address.
-			auto actualPointer = typeList.castToMostDerived(data);
+			const void * actualPointer = static_cast<const void*>(data);
 			auto i = savedPointers.find(actualPointer);
 			if(i != savedPointers.end())
 			{
@@ -223,13 +234,13 @@ public:
 		}
 
 		//write type identifier
-		ui16 tid = typeList.getTypeID(data);
+		uint16_t tid = CTypeList::getInstance().getTypeID(data);
 		save(tid);
 
 		if(!tid)
 			save(*data); //if type is unregistered simply write all data in a standard way
 		else
-			applier.getApplier(tid)->savePtr(*this, typeList.castToMostDerived(data));  //call serializer specific for our real type
+			applier.getApplier(tid)->savePtr(*this, static_cast<const void*>(data));  //call serializer specific for our real type
 	}
 
 	template < typename T, typename std::enable_if < is_serializeable<BinarySerializer, T>::value, int  >::type = 0 >
@@ -389,30 +400,4 @@ public:
 	}
 };
 
-class DLL_LINKAGE CSaveFile : public IBinaryWriter
-{
-public:
-	BinarySerializer serializer;
-
-	boost::filesystem::path fName;
-	std::unique_ptr<std::fstream> sfile;
-
-	CSaveFile(const boost::filesystem::path &fname); //throws!
-	~CSaveFile();
-	int write(const void * data, unsigned size) override;
-
-	void openNextFile(const boost::filesystem::path &fname); //throws!
-	void clear();
-	void reportState(vstd::CLoggerBase * out) override;
-
-	void putMagicBytes(const std::string &text);
-
-	template<class T>
-	CSaveFile & operator<<(const T &t)
-	{
-		serializer & t;
-		return * this;
-	}
-};
-
 VCMI_LIB_NAMESPACE_END

+ 100 - 0
lib/serializer/CLoadFile.cpp

@@ -0,0 +1,100 @@
+/*
+ * CLoadFile.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "CLoadFile.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+CLoadFile::CLoadFile(const boost::filesystem::path & fname, int minimalVersion)
+	: serializer(this)
+{
+	openNextFile(fname, minimalVersion);
+}
+
+//must be instantiated in .cpp file for access to complete types of all member fields
+CLoadFile::~CLoadFile() = default;
+
+int CLoadFile::read(void * data, unsigned size)
+{
+	sfile->read(reinterpret_cast<char *>(data), size);
+	return size;
+}
+
+void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalVersion)
+{
+	assert(!serializer.reverseEndianess);
+	assert(minimalVersion <= SERIALIZATION_VERSION);
+
+	try
+	{
+		fName = fname.string();
+		sfile = std::make_unique<std::fstream>(fname.c_str(), std::ios::in | std::ios::binary);
+		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
+
+		if(!(*sfile))
+			THROW_FORMAT("Error: cannot open to read %s!", fName);
+
+		//we can read
+		char buffer[4];
+		sfile->read(buffer, 4);
+		if(std::memcmp(buffer, "VCMI", 4) != 0)
+			THROW_FORMAT("Error: not a VCMI file(%s)!", fName);
+
+		serializer & serializer.fileVersion;
+		if(serializer.fileVersion < minimalVersion)
+			THROW_FORMAT("Error: too old file format (%s)!", fName);
+
+		if(serializer.fileVersion > SERIALIZATION_VERSION)
+		{
+			logGlobal->warn("Warning format version mismatch: found %d when current is %d! (file %s)\n", serializer.fileVersion, SERIALIZATION_VERSION , fName);
+
+			auto * versionptr = reinterpret_cast<char *>(&serializer.fileVersion);
+			std::reverse(versionptr, versionptr + 4);
+			logGlobal->warn("Version number reversed is %x, checking...", serializer.fileVersion);
+
+			if(serializer.fileVersion == SERIALIZATION_VERSION)
+			{
+				logGlobal->warn("%s seems to have different endianness! Entering reversing mode.", fname.string());
+				serializer.reverseEndianess = true;
+			}
+			else
+				THROW_FORMAT("Error: too new file format (%s)!", fName);
+		}
+	}
+	catch(...)
+	{
+		clear(); //if anything went wrong, we delete file and rethrow
+		throw;
+	}
+}
+
+void CLoadFile::reportState(vstd::CLoggerBase * out)
+{
+	out->debug("CLoadFile");
+	if(!!sfile && *sfile)
+		out->debug("\tOpened %s Position: %d", fName, sfile->tellg());
+}
+
+void CLoadFile::clear()
+{
+	sfile = nullptr;
+	fName.clear();
+	serializer.fileVersion = 0;
+}
+
+void CLoadFile::checkMagicBytes(const std::string &text)
+{
+	std::string loaded = text;
+	read((void *)loaded.data(), static_cast<unsigned int>(text.length()));
+	if(loaded != text)
+		throw std::runtime_error("Magic bytes doesn't match!");
+}
+
+VCMI_LIB_NAMESPACE_END

+ 42 - 0
lib/serializer/CLoadFile.h

@@ -0,0 +1,42 @@
+/*
+ * CLoadFile.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "BinaryDeserializer.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class DLL_LINKAGE CLoadFile : public IBinaryReader
+{
+public:
+	BinaryDeserializer serializer;
+
+	std::string fName;
+	std::unique_ptr<std::fstream> sfile;
+
+	CLoadFile(const boost::filesystem::path & fname, int minimalVersion = SERIALIZATION_VERSION); //throws!
+	virtual ~CLoadFile();
+	int read(void * data, unsigned size) override; //throws!
+
+	void openNextFile(const boost::filesystem::path & fname, int minimalVersion); //throws!
+	void clear();
+	void reportState(vstd::CLoggerBase * out) override;
+
+	void checkMagicBytes(const std::string & text);
+
+	template<class T>
+	CLoadFile & operator>>(T &t)
+	{
+		serializer & t;
+		return * this;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 0 - 68
lib/serializer/CLoadIntegrityValidator.cpp

@@ -1,68 +0,0 @@
-/*
- * CLoadIntegrityValidator.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#include "StdInc.h"
-#include "CLoadIntegrityValidator.h"
-
-#include "../registerTypes/RegisterTypes.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-CLoadIntegrityValidator::CLoadIntegrityValidator(const boost::filesystem::path &primaryFileName, const boost::filesystem::path &controlFileName, int minimalVersion)
-	: serializer(this), foundDesync(false)
-{
-	registerTypes(serializer);
-	primaryFile = std::make_unique<CLoadFile>(primaryFileName, minimalVersion);
-	controlFile = std::make_unique<CLoadFile>(controlFileName, minimalVersion);
-
-	assert(primaryFile->serializer.fileVersion == controlFile->serializer.fileVersion);
-	serializer.fileVersion = primaryFile->serializer.fileVersion;
-}
-
-int CLoadIntegrityValidator::read( void * data, unsigned size )
-{
-	assert(primaryFile);
-	assert(controlFile);
-
-	if(!size)
-		return size;
-
-	std::vector<ui8> controlData(size);
-	auto ret = primaryFile->read(data, size);
-
-	if(!foundDesync)
-	{
-		controlFile->read(controlData.data(), size);
-		if(std::memcmp(data, controlData.data(), size) != 0)
-		{
-			logGlobal->error("Desync found! Position: %d", primaryFile->sfile->tellg());
-			foundDesync = true;
-			//throw std::runtime_error("Savegame dsynchronized!");
-		}
-	}
-	return ret;
-}
-
-std::unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
-{
-	primaryFile->serializer.loadedPointers = this->serializer.loadedPointers;
-	primaryFile->serializer.loadedPointersTypes = this->serializer.loadedPointersTypes;
-	return std::move(primaryFile);
-}
-
-void CLoadIntegrityValidator::checkMagicBytes(const std::string & text) const
-{
-	assert(primaryFile);
-	assert(controlFile);
-
-	primaryFile->checkMagicBytes(text);
-	controlFile->checkMagicBytes(text);
-}
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 33
lib/serializer/CLoadIntegrityValidator.h

@@ -1,33 +0,0 @@
-/*
- * CLoadIntegrityValidator.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
-
-#include "BinaryDeserializer.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-/// Simple byte-to-byte saves comparator
-class DLL_LINKAGE CLoadIntegrityValidator
-	: public IBinaryReader
-{
-public:
-	BinaryDeserializer serializer;
-	std::unique_ptr<CLoadFile> primaryFile, controlFile;
-	bool foundDesync;
-
-	CLoadIntegrityValidator(const boost::filesystem::path &primaryFileName, const boost::filesystem::path &controlFileName, int minimalVersion = SERIALIZATION_VERSION); //throws!
-
-	int read( void * data, unsigned size) override; //throws!
-	void checkMagicBytes(const std::string & text) const;
-
-	std::unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
-};
-
-VCMI_LIB_NAMESPACE_END

+ 0 - 4
lib/serializer/CMemorySerializer.cpp

@@ -10,8 +10,6 @@
 #include "StdInc.h"
 #include "CMemorySerializer.h"
 
-#include "../registerTypes/RegisterTypes.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
 int CMemorySerializer::read(void * data, unsigned size)
@@ -34,8 +32,6 @@ int CMemorySerializer::write(const void * data, unsigned size)
 
 CMemorySerializer::CMemorySerializer(): iser(this), oser(this), readPos(0)
 {
-	registerTypes(iser);
-	registerTypes(oser);
 	iser.fileVersion = SERIALIZATION_VERSION;
 }
 

+ 72 - 0
lib/serializer/CSaveFile.cpp

@@ -0,0 +1,72 @@
+/*
+ * CSaveFile.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "CSaveFile.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+CSaveFile::CSaveFile(const boost::filesystem::path &fname)
+	: serializer(this)
+{
+	openNextFile(fname);
+}
+
+//must be instantiated in .cpp file for access to complete types of all member fields
+CSaveFile::~CSaveFile() = default;
+
+int CSaveFile::write(const void * data, unsigned size)
+{
+	sfile->write((char *)data,size);
+	return size;
+}
+
+void CSaveFile::openNextFile(const boost::filesystem::path &fname)
+{
+	fName = fname;
+	try
+	{
+		sfile = std::make_unique<std::fstream>(fname.c_str(), std::ios::out | std::ios::binary);
+		sfile->exceptions(std::ifstream::failbit | std::ifstream::badbit); //we throw a lot anyway
+
+		if(!(*sfile))
+			THROW_FORMAT("Error: cannot open to write %s!", fname);
+
+		sfile->write("VCMI",4); //write magic identifier
+		serializer & SERIALIZATION_VERSION; //write format version
+	}
+	catch(...)
+	{
+		logGlobal->error("Failed to save to %s", fname.string());
+		clear();
+		throw;
+	}
+}
+
+void CSaveFile::reportState(vstd::CLoggerBase * out)
+{
+	out->debug("CSaveFile");
+	if(sfile.get() && *sfile)
+	{
+		out->debug("\tOpened %s \tPosition: %d", fName, sfile->tellp());
+	}
+}
+
+void CSaveFile::clear()
+{
+	fName.clear();
+	sfile = nullptr;
+}
+
+void CSaveFile::putMagicBytes(const std::string &text)
+{
+	write(text.c_str(), static_cast<unsigned int>(text.length()));
+}
+
+VCMI_LIB_NAMESPACE_END

+ 42 - 0
lib/serializer/CSaveFile.h

@@ -0,0 +1,42 @@
+/*
+ * CSaveFile.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "BinarySerializer.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class DLL_LINKAGE CSaveFile : public IBinaryWriter
+{
+public:
+	BinarySerializer serializer;
+
+	boost::filesystem::path fName;
+	std::unique_ptr<std::fstream> sfile;
+
+	CSaveFile(const boost::filesystem::path &fname); //throws!
+	~CSaveFile();
+	int write(const void * data, unsigned size) override;
+
+	void openNextFile(const boost::filesystem::path &fname); //throws!
+	void clear();
+	void reportState(vstd::CLoggerBase * out) override;
+
+	void putMagicBytes(const std::string &text);
+
+	template<class T>
+	CSaveFile & operator<<(const T &t)
+	{
+		serializer & t;
+		return * this;
+	}
+};
+
+VCMI_LIB_NAMESPACE_END

+ 24 - 35
lib/serializer/CSerializer.h

@@ -14,8 +14,8 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-const ui32 SERIALIZATION_VERSION = 828;
-const ui32 MINIMAL_SERIALIZATION_VERSION = 828;
+const ui32 SERIALIZATION_VERSION = 830;
+const ui32 MINIMAL_SERIALIZATION_VERSION = 830;
 const std::string SAVEGAME_MAGIC = "VCMISVG";
 
 class CHero;
@@ -149,42 +149,31 @@ struct is_serializeable
 template <typename T> //metafunction returning CGObjectInstance if T is its derivate or T elsewise
 struct VectorizedTypeFor
 {
-	using type = typename
-		//if
-		boost::mpl::eval_if<std::is_same<CGHeroInstance, T>,
-		boost::mpl::identity<CGHeroInstance>,
-		//else if
-		boost::mpl::eval_if<std::is_base_of<CGObjectInstance, T>,
-		boost::mpl::identity<CGObjectInstance>,
-		//else
-		boost::mpl::identity<T>
-		>>::type;
+	using type = std::conditional_t<std::is_base_of_v<CGObjectInstance, T>, CGObjectInstance, T>;
 };
-template <typename U>
+
+template <>
+struct VectorizedTypeFor<CGHeroInstance>
+{
+	using type = CGHeroInstance;
+};
+
+template <typename T>
 struct VectorizedIDType
 {
-	using type = typename
-		//if
-		boost::mpl::eval_if<std::is_same<CArtifact, U>,
-		boost::mpl::identity<ArtifactID>,
-		//else if
-		boost::mpl::eval_if<std::is_same<CCreature, U>,
-		boost::mpl::identity<CreatureID>,
-		//else if
-		boost::mpl::eval_if<std::is_same<CHero, U>,
-		boost::mpl::identity<HeroTypeID>,
-		//else if
-		boost::mpl::eval_if<std::is_same<CArtifactInstance, U>,
-		boost::mpl::identity<ArtifactInstanceID>,
-		//else if
-		boost::mpl::eval_if<std::is_same<CGHeroInstance, U>,
-		boost::mpl::identity<HeroTypeID>,
-		//else if
-		boost::mpl::eval_if<std::is_base_of<CGObjectInstance, U>,
-		boost::mpl::identity<ObjectInstanceID>,
-		//else
-		boost::mpl::identity<si32>
-		>>>>>>::type;
+	using type = std::conditional_t<std::is_base_of_v<CGObjectInstance, T>, ObjectInstanceID, int32_t>;
+};
+
+template <>
+struct VectorizedIDType<CArtifactInstance>
+{
+	using type = ArtifactInstanceID;
+};
+
+template <>
+struct VectorizedIDType<CGHeroInstance>
+{
+	using type = HeroTypeID;
 };
 
 /// Base class for deserializers

+ 0 - 119
lib/serializer/CTypeList.cpp

@@ -14,128 +14,9 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-extern template void registerTypes<CTypeList>(CTypeList & s);
-
-CTypeList typeList;
-
 CTypeList::CTypeList()
 {
 	registerTypes(*this);
 }
 
-CTypeList::TypeInfoPtr CTypeList::registerType(const std::type_info *type)
-{
-	if(auto typeDescr = getTypeDescriptor(type, false))
-		return typeDescr;  //type found, return ptr to structure
-
-	//type not found - add it to the list and return given ID
-	auto newType = std::make_shared<TypeDescriptor>();
-	newType->typeID = static_cast<ui16>(typeInfos.size() + 1);
-	newType->name = type->name();
-	typeInfos[type] = newType;
-
-	return newType;
-}
-
-ui16 CTypeList::getTypeID(const std::type_info *type, bool throws) const
-{
-	auto descriptor = getTypeDescriptor(type, throws);
-	if (descriptor == nullptr)
-	{
-		return 0;
-	}
-	return descriptor->typeID;
-}
-
-CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(ui16 typeID) const
-{
-	auto found = std::find_if(typeInfos.begin(), typeInfos.end(), [typeID](const std::pair<const std::type_info *, TypeInfoPtr> & p) -> bool
-		{
-			return p.second->typeID == typeID;
-		});
-
-	if(found != typeInfos.end())
-	{
-		return found->second;
-	}
-
-	return TypeInfoPtr();
-}
-
-std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
-{
-	if(!strcmp(from->name, to->name))
-		return std::vector<CTypeList::TypeInfoPtr>();
-
-	// Perform a simple BFS in the class hierarchy.
-
-	auto BFS = [&](bool upcast)
-	{
-		std::map<TypeInfoPtr, TypeInfoPtr> previous;
-		std::queue<TypeInfoPtr> q;
-		q.push(to);
-		while(!q.empty())
-		{
-			auto typeNode = q.front();
-			q.pop();
-			for(auto & weakNode : (upcast ? typeNode->parents : typeNode->children) )
-			{
-				auto nodeBase = weakNode.lock();
-				if(!previous.count(nodeBase))
-				{
-					previous[nodeBase] = typeNode;
-					q.push(nodeBase);
-				}
-			}
-		}
-
-		std::vector<TypeInfoPtr> ret;
-
-		if(!previous.count(from))
-			return ret;
-
-		ret.push_back(from);
-		TypeInfoPtr ptr = from;
-		do
-		{
-			ptr = previous.at(ptr);
-			ret.push_back(ptr);
-		} while(ptr != to);
-
-		return ret;
-	};
-
-	// Try looking both up and down.
-	auto ret = BFS(true);
-	if(ret.empty())
-		ret = BFS(false);
-
-	if(ret.empty())
-		THROW_FORMAT("Cannot find relation between types %s and %s. Were they (and all classes between them) properly registered?", from->name % to->name);
-
-	return ret;
-}
-
-std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
-{
-	//This additional if is needed because getTypeDescriptor might fail if type is not registered
-	// (and if casting is not needed, then registereing should no  be required)
-	if(!strcmp(from->name(), to->name()))
-		return std::vector<CTypeList::TypeInfoPtr>();
-
-	return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
-}
-
-CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) const
-{
-	auto i = typeInfos.find(type);
-	if(i != typeInfos.end())
-		return i->second; //type found, return ptr to structure
-
-	if(!throws)
-		return nullptr;
-
-	THROW_FORMAT("Cannot find type descriptor for type %s. Was it registered?", type->name());
-}
-
 VCMI_LIB_NAMESPACE_END

+ 34 - 162
lib/serializer/CTypeList.h

@@ -9,199 +9,72 @@
  */
 #pragma once
 
-#include "CSerializer.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
-struct IPointerCaster
-{
-	virtual std::any castRawPtr(const std::any &ptr) const = 0; // takes From*, returns To*
-	virtual std::any castSharedPtr(const std::any &ptr) const = 0; // takes std::shared_ptr<From>, performs dynamic cast, returns std::shared_ptr<To>
-	virtual std::any castWeakPtr(const std::any &ptr) const = 0; // takes std::weak_ptr<From>, performs dynamic cast, returns std::weak_ptr<To>. The object under poitner must live.
-	//virtual std::any castUniquePtr(const std::any &ptr) const = 0; // takes std::unique_ptr<From>, performs dynamic cast, returns std::unique_ptr<To>
-	virtual ~IPointerCaster() = default;
-};
-
-template <typename From, typename To>
-struct PointerCaster : IPointerCaster
-{
-	virtual std::any castRawPtr(const std::any &ptr) const override // takes void* pointing to From object, performs dynamic cast, returns void* pointing to To object
-	{
-		From * from = (From*)std::any_cast<void*>(ptr);
-		To * ret = static_cast<To*>(from);
-		return (void*)ret;
-	}
-
-	// Helper function performing casts between smart pointers
-	template<typename SmartPt>
-	std::any castSmartPtr(const std::any &ptr) const
-	{
-		try
-		{
-			auto from = std::any_cast<SmartPt>(ptr);
-			auto ret = std::static_pointer_cast<To>(from);
-			return ret;
-		}
-		catch(std::exception &e)
-		{
-			THROW_FORMAT("Failed cast %s -> %s. Given argument was %s. Error message: %s", typeid(From).name() % typeid(To).name() % ptr.type().name() % e.what());
-		}
-	}
-
-	virtual std::any castSharedPtr(const std::any &ptr) const override
-	{
-		return castSmartPtr<std::shared_ptr<From>>(ptr);
-	}
-	virtual std::any castWeakPtr(const std::any &ptr) const override
-	{
-		auto from = std::any_cast<std::weak_ptr<From>>(ptr);
-		return castSmartPtr<std::shared_ptr<From>>(from.lock());
-	}
-};
-
 /// Class that implements basic reflection-like mechanisms
 /// For every type registered via registerType() generates inheritance tree
 /// Rarely used directly - usually used as part of CApplier
-class DLL_LINKAGE CTypeList: public boost::noncopyable
+class CTypeList
 {
-//public:
-	struct TypeDescriptor;
-	using TypeInfoPtr = std::shared_ptr<TypeDescriptor>;
-	using WeakTypeInfoPtr = std::weak_ptr<TypeDescriptor>;
-	struct TypeDescriptor
-	{
-		ui16 typeID;
-		const char *name;
-		std::vector<WeakTypeInfoPtr> children, parents;
-	};
-	using TMutex = boost::shared_mutex;
-	using TUniqueLock = boost::unique_lock<TMutex>;
-	using TSharedLock = boost::shared_lock<TMutex>;
-
-private:
-	mutable TMutex mx;
-
-	std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
-	std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
-
-	/// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
-	/// Throws if there is no link registered.
-	std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
-	std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
-
-	template<std::any(IPointerCaster::*CastingFunction)(const std::any &) const>
-	std::any castHelper(std::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
-	{
-		TSharedLock lock(mx);
-		auto typesSequence = castSequence(fromArg, toArg);
+	std::map<std::string, uint16_t> typeInfos;
 
-		std::any ptr = inputPtr;
-		for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
-		{
-			auto &from = typesSequence[i];
-			auto &to = typesSequence[i + 1];
-			auto castingPair = std::make_pair(from, to);
-			if(!casters.count(castingPair))
-				THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
-
-			const auto & caster = casters.at(castingPair);
-			ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..?
-		}
+	DLL_LINKAGE CTypeList();
 
-		return ptr;
+	template <typename T>
+	const std::type_info & getTypeInfo(const T * t = nullptr) const
+	{
+		if(t)
+			return typeid(*t);
+		else
+			return typeid(T);
 	}
-	CTypeList & operator=(CTypeList &) = delete;
-
-	TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
-	TypeInfoPtr registerType(const std::type_info *type);
 
 public:
-
-	CTypeList();
-
-	template <typename Base, typename Derived>
-	void registerType(const Base * b = nullptr, const Derived * d = nullptr)
+	static CTypeList & getInstance()
 	{
-		TUniqueLock lock(mx);
-		static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
-		static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
-		static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two different types.");
-		auto bt = getTypeInfo(b);
-		auto dt = getTypeInfo(d); //obtain std::type_info
-		auto bti = registerType(bt);
-		auto dti = registerType(dt); //obtain our TypeDescriptor
-
-		// register the relation between classes
-		bti->children.push_back(dti);
-		dti->parents.push_back(bti);
-		casters[std::make_pair(bti, dti)] = std::make_unique<const PointerCaster<Base, Derived>>();
-		casters[std::make_pair(dti, bti)] = std::make_unique<const PointerCaster<Derived, Base>>();
+		static CTypeList registry;
+		return registry;
 	}
 
-	ui16 getTypeID(const std::type_info *type, bool throws = false) const;
-
-	template <typename T>
-	ui16 getTypeID(const T * t = nullptr, bool throws = false) const
+	template<typename T, typename U>
+	void registerType()
 	{
-		return getTypeID(getTypeInfo(t), throws);
+		registerType<T>();
+		registerType<U>();
 	}
 
-	TypeInfoPtr getTypeDescriptor(ui16 typeID) const;
-
-	template<typename TInput>
-	void * castToMostDerived(const TInput * inputPtr) const
+	template<typename T>
+	void registerType()
 	{
-		const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
-		auto derivedType = getTypeInfo(inputPtr);
+		const std::type_info & typeInfo = typeid(T);
 
-		if (strcmp(baseType.name(), derivedType->name()) == 0)
-		{
-			return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
-		}
+		if (typeInfos.count(typeInfo.name()) != 0)
+			return;
 
-		return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
-			const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
-			derivedType));
+		typeInfos[typeInfo.name()] = typeInfos.size() + 1;
 	}
 
-	template<typename TInput>
-	std::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
+	template<typename T>
+	uint16_t getTypeID(T * typePtr)
 	{
-		const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
-		auto derivedType = getTypeInfo(inputPtr.get());
-
-		if (!strcmp(baseType.name(), derivedType->name()))
-			return inputPtr;
+		static_assert(!std::is_pointer_v<T>, "CTypeList does not supports pointers!");
+		static_assert(!std::is_reference_v<T>, "CTypeList does not supports references!");
 
-		return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType);
-	}
+		const std::type_info & typeInfo = getTypeInfo(typePtr);
 
-	void * castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) const
-	{
-		return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
-	}
-	std::any castShared(std::any inputPtr, const std::type_info *from, const std::type_info *to) const
-	{
-		return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
-	}
+		if (typeInfos.count(typeInfo.name()) == 0)
+			return 0;
 
-	template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
-	{
-		if(t)
-			return &typeid(*t);
-		else
-			return &typeid(T);
+		return typeInfos.at(typeInfo.name());
 	}
 };
 
-extern DLL_LINKAGE CTypeList typeList;
-
 /// Wrapper over CTypeList. Allows execution of templated class T for any type
 /// that was resgistered for this applier
 template<typename T>
 class CApplier : boost::noncopyable
 {
-	std::map<ui16, std::unique_ptr<T>> apps;
+	std::map<int32_t, std::unique_ptr<T>> apps;
 
 	template<typename RegisteredType>
 	void addApplier(ui16 ID)
@@ -224,9 +97,8 @@ public:
 	template<typename Base, typename Derived>
 	void registerType(const Base * b = nullptr, const Derived * d = nullptr)
 	{
-		typeList.registerType(b, d);
-		addApplier<Base>(typeList.getTypeID(b));
-		addApplier<Derived>(typeList.getTypeID(d));
+		addApplier<Base>(CTypeList::getInstance().getTypeID<Base>(nullptr));
+		addApplier<Derived>(CTypeList::getInstance().getTypeID<Derived>(nullptr));
 	}
 };
 

+ 0 - 40
lib/serializer/Cast.h

@@ -9,58 +9,18 @@
  */
 #pragma once
 
-#include <typeinfo>
-#include <string>
-#include "CTypeList.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
 
 template<class T, class F>
 inline const T * dynamic_ptr_cast(const F * ptr)
 {
-#ifndef VCMI_APPLE
 	return dynamic_cast<const T *>(ptr);
-#else
-	if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
-	{
-		return static_cast<const T *>(ptr);
-	}
-	try
-	{
-		auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
-		auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
-		typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
-	}
-	catch(...)
-	{
-		return nullptr;
-	}
-	return static_cast<const T *>(ptr);
-#endif
 }
 
 template<class T, class F>
 inline T * dynamic_ptr_cast(F * ptr)
 {
-#ifndef VCMI_APPLE
 	return dynamic_cast<T *>(ptr);
-#else
-	if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
-	{
-		return static_cast<T *>(ptr);
-	}
-	try
-	{
-		auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
-		auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
-		typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
-	}
-	catch(...)
-	{
-		return nullptr;
-	}
-	return static_cast<T *>(ptr);
-#endif
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 4
lib/serializer/Connection.cpp

@@ -10,8 +10,7 @@
 #include "StdInc.h"
 #include "Connection.h"
 
-#include "../registerTypes/RegisterTypes.h"
-#include "../mapping/CMapHeader.h"
+#include "../networkPacks/NetPacksBase.h"
 
 #include <boost/asio.hpp>
 
@@ -45,8 +44,6 @@ void CConnection::init()
 
 	enableSmartPointerSerialization();
 	disableStackSendingByID();
-	registerTypes(iser);
-	registerTypes(oser);
 #ifndef VCMI_ENDIAN_BIG
 	myEndianess = true;
 #else

+ 0 - 42
lib/spells/CSpellHandler.h

@@ -267,39 +267,6 @@ public:
 	void updateFrom(const JsonNode & data);
 	void serializeJson(JsonSerializeFormat & handler);
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & identifier;
-		if (version > 820)
-			h & modScope;
-		h & id;
-		h & level;
-		h & power;
-		h & probabilities;
-		h & attributes;
-		h & combat;
-		h & creatureAbility;
-		h & positiveness;
-		h & counteredSpells;
-		h & rising;
-		h & damage;
-		h & offensive;
-		h & targetType;
-		h & targetCondition;
-		h & iconImmune;
-		h & defaultProbability;
-		h & special;
-		h & castSound;
-		h & iconBook;
-		h & iconEffect;
-		h & iconScenarioBonus;
-		h & iconScroll;
-		h & levels;
-		h & school;
-		h & animationInfo;
-		h & nonMagical;
-		h & onlyOnWaterMap;
-	}
 	friend class CSpellHandler;
 	friend class Graphics;
 	friend class test::CSpellTest;
@@ -384,15 +351,6 @@ public:
 	 */
 	std::vector<bool> getDefaultAllowed() const override;
 
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & objects;
-		if(!h.saving)
-		{
-			afterLoadFinalization();
-		}
-	}
-
 protected:
 	const std::vector<std::string> & getTypeNames() const override;
 	CSpell * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;

+ 1 - 1
mapeditor/mapcontroller.h

@@ -16,7 +16,7 @@
 #include "../lib/modding/CModInfo.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
-using ModCompatibilityInfo = std::map<std::string, CModInfo::VerificationInfo>;
+using ModCompatibilityInfo = std::map<std::string, ModVerificationInfo>;
 class EditorObstaclePlacer;
 VCMI_LIB_NAMESPACE_END
 

+ 8 - 8
server/CGameHandler.cpp

@@ -27,6 +27,7 @@
 #include "../lib/CCreatureSet.h"
 #include "../lib/CGeneralTextHandler.h"
 #include "../lib/CHeroHandler.h"
+#include "../lib/CPlayerState.h"
 #include "../lib/CSoundBase.h"
 #include "../lib/CThreadHelper.h"
 #include "../lib/CTownHandler.h"
@@ -47,20 +48,19 @@
 
 #include "../lib/mapping/CMap.h"
 #include "../lib/mapping/CMapService.h"
+#include "../lib/mapObjects/CGMarket.h"
 #include "../lib/modding/ModIncompatibility.h"
 #include "../lib/networkPacks/StackLocation.h"
 #include "../lib/pathfinder/CPathfinder.h"
 #include "../lib/pathfinder/PathfinderOptions.h"
 #include "../lib/pathfinder/TurnInfo.h"
 
-#include "../lib/registerTypes/RegisterTypes.h"
+#include "../lib/registerTypes/RegisterTypesServerPacks.h"
 
 #include "../lib/rmg/CMapGenOptions.h"
 
-#include "../lib/serializer/CTypeList.h"
-#include "../lib/serializer/Cast.h"
-#include "../lib/serializer/Connection.h"
-#include "../lib/serializer/JsonSerializer.h"
+#include "../lib/serializer/CSaveFile.h"
+#include "../lib/serializer/CLoadFile.h"
 
 #include "../lib/spells/CSpellHandler.h"
 
@@ -463,12 +463,12 @@ void CGameHandler::handleReceivedPack(CPackForServer * pack)
 		PackageApplied applied;
 		applied.player = pack->player;
 		applied.result = succesfullyApplied;
-		applied.packType = typeList.getTypeID(pack);
+		applied.packType = CTypeList::getInstance().getTypeID(pack);
 		applied.requestID = pack->requestID;
 		pack->c->sendPack(&applied);
 	};
 
-	CBaseForGHApply * apply = applier->getApplier(typeList.getTypeID(pack)); //and appropriate applier object
+	CBaseForGHApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //and appropriate applier object
 	if(isBlockedByQueries(pack, pack->player))
 	{
 		sendPackageResponse(false);
@@ -4057,7 +4057,7 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
 void CGameHandler::synchronizeArtifactHandlerLists()
 {
 	UpdateArtHandlerLists uahl;
-	uahl.allocatedArtifacts = VLC->arth->allocatedArtifacts;
+	uahl.allocatedArtifacts = gs->allocatedArtifacts;
 	sendAndApply(&uahl);
 }
 

+ 3 - 3
server/CVCMIServer.cpp

@@ -47,7 +47,7 @@
 #include "../lib/UnlockGuard.h"
 
 // for applier
-#include "../lib/registerTypes/RegisterTypes.h"
+#include "../lib/registerTypes/RegisterTypesLobbyPacks.h"
 
 // UUID generation
 #include <boost/uuid/uuid.hpp>
@@ -485,7 +485,7 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
 
 void CVCMIServer::handleReceivedPack(std::unique_ptr<CPackForLobby> pack)
 {
-	CBaseForServerApply * apply = applier->getApplier(typeList.getTypeID(pack.get()));
+	CBaseForServerApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()));
 	if(apply->applyOnServerBefore(this, pack.get()))
 		addToAnnounceQueue(std::move(pack));
 }
@@ -502,7 +502,7 @@ void CVCMIServer::announcePack(std::unique_ptr<CPackForLobby> pack)
 		c->sendPack(pack.get());
 	}
 
-	applier->getApplier(typeList.getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
+	applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
 }
 
 void CVCMIServer::announceMessage(const std::string & txt)