Browse Source

Added 'Serializeable' base class for classes serializeable by pointer

Ivan Savenko 1 year ago
parent
commit
84bc6c42db
42 changed files with 145 additions and 79 deletions
  1. 2 0
      AI/Nullkiller/AIGateway.h
  2. 5 5
      AI/VCAI/Goals/Explore.cpp
  3. 3 0
      AI/VCAI/VCAI.h
  4. 2 1
      lib/CArtHandler.h
  5. 2 1
      lib/CCreatureSet.h
  6. 1 1
      lib/CGameInfoCallback.cpp
  7. 1 0
      lib/CMakeLists.txt
  8. 13 1
      lib/CPlayerState.h
  9. 2 1
      lib/CRandomGenerator.h
  10. 2 2
      lib/IGameCallback.cpp
  11. 2 1
      lib/StartInfo.h
  12. 4 2
      lib/battle/CObstacleInstance.h
  13. 2 1
      lib/bonuses/Bonus.h
  14. 3 3
      lib/bonuses/CBonusSystemNode.h
  15. 3 2
      lib/bonuses/Limiters.h
  16. 4 2
      lib/bonuses/Propagators.h
  17. 3 2
      lib/bonuses/Updaters.h
  18. 2 1
      lib/campaign/CampaignState.h
  19. 4 5
      lib/gameState/CGameState.cpp
  20. 1 1
      lib/gameState/CGameState.h
  21. 2 1
      lib/gameState/CGameStateCampaign.h
  22. 3 1
      lib/gameState/TavernHeroesPool.h
  23. 2 1
      lib/mapObjectConstructors/CBankInstanceConstructor.h
  24. 2 1
      lib/mapObjects/CGObjectInstance.h
  25. 10 9
      lib/mapObjects/CQuest.h
  26. 4 3
      lib/mapObjects/IObjectInterface.h
  27. 1 1
      lib/mapObjects/MiscObjects.h
  28. 2 1
      lib/mapObjects/ObjectTemplate.h
  29. 3 2
      lib/mapping/CMapHeader.h
  30. 3 1
      lib/mapping/CMapInfo.h
  31. 2 1
      lib/networkPacks/NetPacksBase.h
  32. 3 3
      lib/networkPacks/NetPacksLib.cpp
  33. 2 2
      lib/pathfinder/PathfinderUtil.h
  34. 2 1
      lib/rewardable/Limiter.h
  35. 2 1
      lib/rmg/CMapGenOptions.h
  36. 11 11
      lib/serializer/BinaryDeserializer.h
  37. 3 2
      lib/serializer/BinarySerializer.h
  38. 2 1
      lib/serializer/ESerializationVersion.h
  39. 21 0
      lib/serializer/Serializeable.h
  40. 1 1
      lib/spells/AdventureSpellMechanics.cpp
  41. 2 2
      server/CGameHandler.cpp
  42. 1 1
      server/processors/PlayerMessageProcessor.cpp

+ 2 - 0
AI/Nullkiller/AIGateway.h

@@ -206,6 +206,7 @@ public:
 
 	template<typename Handler> void serializeInternal(Handler & h)
 	{
+#if 0
 		h & nullkiller->memory->knownTeleportChannels;
 		h & nullkiller->memory->knownSubterraneanGates;
 		h & destinationTeleport;
@@ -213,6 +214,7 @@ public:
 		h & nullkiller->memory->alreadyVisited;
 		h & status;
 		h & battlename;
+#endif
 	}
 };
 

+ 5 - 5
AI/VCAI/Goals/Explore.cpp

@@ -53,7 +53,7 @@ namespace Goals
 		{
 			int3 tile = int3(0, 0, ourPos.z);
 
-			const auto & slice = (*(ts->fogOfWarMap))[ourPos.z];
+			const auto & slice = ts->fogOfWarMap[ourPos.z];
 
 			for(tile.x = ourPos.x - scanRadius; tile.x <= ourPos.x + scanRadius; tile.x++)
 			{
@@ -81,13 +81,13 @@ namespace Goals
 
 			foreach_tile_pos([&](const int3 & pos)
 			{
-				if((*(ts->fogOfWarMap))[pos.z][pos.x][pos.y])
+				if(ts->fogOfWarMap[pos.z][pos.x][pos.y])
 				{
 					bool hasInvisibleNeighbor = false;
 
 					foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
 					{
-						if(!(*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y])
+						if(!ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y])
 						{
 							hasInvisibleNeighbor = true;
 						}
@@ -171,7 +171,7 @@ namespace Goals
 			{
 				foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
 				{
-					if((*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y])
+					if(ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y])
 					{
 						out.push_back(neighbour);
 					}
@@ -184,7 +184,7 @@ namespace Goals
 			int ret = 0;
 			int3 npos = int3(0, 0, pos.z);
 
-			const auto & slice = (*(ts->fogOfWarMap))[pos.z];
+			const auto & slice = ts->fogOfWarMap[pos.z];
 
 			for(npos.x = pos.x - sightRadius; npos.x <= pos.x + sightRadius; npos.x++)
 			{

+ 3 - 0
AI/VCAI/VCAI.h

@@ -303,6 +303,8 @@ public:
 
 	template<typename Handler> void serializeInternal(Handler & h)
 	{
+#if 0
+// serialization of client-side data is broken and not performed at the moment
 		h & knownTeleportChannels;
 		h & knownSubterraneanGates;
 		h & destinationTeleport;
@@ -358,6 +360,7 @@ public:
 		h & heroesUnableToExplore;
 
 		//myCB is restored after load by init call
+#endif
 	}
 };
 

+ 2 - 1
lib/CArtHandler.h

@@ -16,6 +16,7 @@
 #include "bonuses/CBonusSystemNode.h"
 #include "GameConstants.h"
 #include "IHandlerBase.h"
+#include "serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -187,7 +188,7 @@ struct DLL_LINKAGE ArtSlotInfo
 	}
 };
 
-class DLL_LINKAGE CArtifactSet
+class DLL_LINKAGE CArtifactSet : public virtual Serializeable
 {
 public:
 	using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;

+ 2 - 1
lib/CCreatureSet.h

@@ -11,6 +11,7 @@
 
 #include "bonuses/Bonus.h"
 #include "bonuses/CBonusSystemNode.h"
+#include "serializer/Serializeable.h"
 #include "GameConstants.h"
 #include "CArtHandler.h"
 #include "CArtifactInstance.h"
@@ -208,7 +209,7 @@ namespace NArmyFormation
 	static const std::vector<std::string> names{ "wide", "tight" };
 }
 
-class DLL_LINKAGE CCreatureSet : public IArmyDescriptor //seven combined creatures
+class DLL_LINKAGE CCreatureSet : public IArmyDescriptor, public virtual Serializeable //seven combined creatures
 {
 	CCreatureSet(const CCreatureSet &) = delete;
 	CCreatureSet &operator=(const CCreatureSet&);

+ 1 - 1
lib/CGameInfoCallback.cpp

@@ -553,7 +553,7 @@ std::shared_ptr<const boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::ge
 		for(tile.x = 0; tile.x < width; tile.x++)
 			for(tile.y = 0; tile.y < height; tile.y++)
 			{
-				if ((*team->fogOfWarMap)[tile.z][tile.x][tile.y])
+				if (team->fogOfWarMap[tile.z][tile.x][tile.y])
 					(*ptr)[tile.z][tile.x][tile.y] = &gs->map->getTile(tile);
 				else
 					(*ptr)[tile.z][tile.x][tile.y] = nullptr;

+ 1 - 0
lib/CMakeLists.txt

@@ -602,6 +602,7 @@ set(lib_MAIN_HEADERS
 	serializer/JsonUpdater.h
 	serializer/Cast.h
 	serializer/ESerializationVersion.h
+	serializer/Serializeable.h
 
 	spells/AbilityCaster.h
 	spells/AdventureSpellMechanics.h

+ 13 - 1
lib/CPlayerState.h

@@ -128,7 +128,7 @@ public:
 	TeamID id; //position in gameState::teams
 	std::set<PlayerColor> players; // members of this team
 	//TODO: boost::array, bool if possible
-	std::unique_ptr<boost::multi_array<ui8, 3>> fogOfWarMap; //[z][x][y] true - visible, false - hidden
+	boost::multi_array<ui8, 3> fogOfWarMap; //[z][x][y] true - visible, false - hidden
 
 	TeamState();
 
@@ -136,6 +136,18 @@ public:
 	{
 		h & id;
 		h & players;
+		if (h.version < Handler::Version::REMOVE_FOG_OF_WAR_POINTER)
+		{
+			struct Helper : public Serializeable
+			{
+				void serialize(Handler &h)
+				{}
+			};
+			Helper helper;
+			auto ptrHelper = &helper;
+			h & ptrHelper;
+		}
+
 		h & fogOfWarMap;
 		h & static_cast<CBonusSystemNode&>(*this);
 	}

+ 2 - 1
lib/CRandomGenerator.h

@@ -11,6 +11,7 @@
 #pragma once
 
 #include <vstd/RNG.h>
+#include "serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -27,7 +28,7 @@ using TRandI = std::function<int()>;
 /// The random generator randomly generates integers and real numbers("doubles") between
 /// a given range. This is a header only class and mainly a wrapper for
 /// convenient usage of the standard random API. An instance of this RNG is not thread safe.
-class DLL_LINKAGE CRandomGenerator : public vstd::RNG, boost::noncopyable
+class DLL_LINKAGE CRandomGenerator : public vstd::RNG, boost::noncopyable, public Serializeable
 {
 public:
 	/// Seeds the generator by default with the product of the current time in milliseconds and the

+ 2 - 2
lib/IGameCallback.cpp

@@ -103,8 +103,8 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3> & tiles,
 				if(distance <= radious)
 				{
 					if(!player
-						|| (mode == ETileVisibility::HIDDEN  && (*team->fogOfWarMap)[pos.z][xd][yd] == 0)
-						|| (mode == ETileVisibility::REVEALED && (*team->fogOfWarMap)[pos.z][xd][yd] == 1)
+						|| (mode == ETileVisibility::HIDDEN  && team->fogOfWarMap[pos.z][xd][yd] == 0)
+						|| (mode == ETileVisibility::REVEALED && team->fogOfWarMap[pos.z][xd][yd] == 1)
 					)
 						tiles.insert(int3(xd,yd,pos.z));
 				}

+ 2 - 1
lib/StartInfo.h

@@ -15,6 +15,7 @@
 #include "TurnTimerInfo.h"
 #include "ExtraOptionsInfo.h"
 #include "campaign/CampaignConstants.h"
+#include "serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -107,7 +108,7 @@ enum class EStartMode : int32_t
 };
 
 /// Struct which describes the difficulty, the turn time,.. of a heroes match.
-struct DLL_LINKAGE StartInfo
+struct DLL_LINKAGE StartInfo : public Serializeable
 {
 	EStartMode mode;
 	ui8 difficulty; //0=easy; 4=impossible

+ 4 - 2
lib/battle/CObstacleInstance.h

@@ -9,9 +9,11 @@
  */
 #pragma once
 #include "BattleHex.h"
+
+#include "../constants/EntityIdentifiers.h"
 #include "../filesystem/ResourcePath.h"
 #include "../networkPacks/BattleChanges.h"
-#include "../constants/EntityIdentifiers.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -20,7 +22,7 @@ class ObstacleChanges;
 class JsonSerializeFormat;
 class SpellID;
 
-struct DLL_LINKAGE CObstacleInstance
+struct DLL_LINKAGE CObstacleInstance : public Serializeable
 {
 	enum EObstacleType : ui8
 	{

+ 2 - 1
lib/bonuses/Bonus.h

@@ -13,6 +13,7 @@
 #include "BonusCustomTypes.h"
 #include "../constants/VariantIdentifier.h"
 #include "../constants/EntityIdentifiers.h"
+#include "../serializer/Serializeable.h"
 #include "../MetaString.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -55,7 +56,7 @@ public:
 #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
 
 /// Struct for handling bonuses of several types. Can be transferred to any hero
-struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
+struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Serializeable
 {
 	BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values
 	si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK

+ 3 - 3
lib/bonuses/CBonusSystemNode.h

@@ -9,11 +9,11 @@
  */
 #pragma once
 
-#include "GameConstants.h"
-
 #include "BonusList.h"
 #include "IBonusBearer.h"
 
+#include "../serializer/Serializeable.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 using TNodes = std::set<CBonusSystemNode *>;
@@ -21,7 +21,7 @@ using TCNodes = std::set<const CBonusSystemNode *>;
 using TNodesVector = std::vector<CBonusSystemNode *>;
 using TCNodesVector = std::vector<const CBonusSystemNode *>;
 
-class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public boost::noncopyable
+class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public virtual Serializeable, public boost::noncopyable
 {
 public:
 	enum ENodeTypes

+ 3 - 2
lib/bonuses/Limiters.h

@@ -10,8 +10,9 @@
 
 #include "Bonus.h"
 
-#include "../GameConstants.h"
 #include "../battle/BattleHex.h"
+#include "../serializer/Serializeable.h"
+#include "../constants/Enumerations.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -27,7 +28,7 @@ struct BonusLimitationContext
 	const BonusList & stillUndecided;
 };
 
-class DLL_LINKAGE ILimiter
+class DLL_LINKAGE ILimiter : public Serializeable
 {
 public:
 	enum class EDecision : uint8_t {ACCEPT, DISCARD, NOT_SURE};

+ 4 - 2
lib/bonuses/Propagators.h

@@ -12,11 +12,13 @@
 #include "Bonus.h"
 #include "CBonusSystemNode.h"
 
+#include "../serializer/Serializeable.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 extern DLL_LINKAGE const std::map<std::string, TPropagatorPtr> bonusPropagatorMap;
 
-class DLL_LINKAGE IPropagator
+class DLL_LINKAGE IPropagator : public Serializeable
 {
 public:
 	virtual ~IPropagator() = default;
@@ -42,4 +44,4 @@ public:
 	}
 };
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 3 - 2
lib/bonuses/Updaters.h

@@ -10,6 +10,7 @@
 #pragma once
 
 #include "Bonus.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -17,7 +18,7 @@ extern DLL_LINKAGE const std::map<std::string, TUpdaterPtr> bonusUpdaterMap;
 
 // observers for updating bonuses based on certain events (e.g. hero gaining level)
 
-class DLL_LINKAGE IUpdater
+class DLL_LINKAGE IUpdater : public Serializeable
 {
 public:
 	virtual ~IUpdater() = default;
@@ -114,4 +115,4 @@ public:
 	JsonNode toJsonNode() const override;
 };
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 2 - 1
lib/campaign/CampaignState.h

@@ -12,6 +12,7 @@
 #include "../GameConstants.h"
 #include "../MetaString.h"
 #include "../filesystem/ResourcePath.h"
+#include "../serializer/Serializeable.h"
 #include "../CGeneralTextHandler.h"
 #include "CampaignConstants.h"
 #include "CampaignScenarioPrologEpilog.h"
@@ -214,7 +215,7 @@ struct DLL_LINKAGE CampaignScenario
 };
 
 /// Class that represents loaded campaign information
-class DLL_LINKAGE Campaign : public CampaignHeader
+class DLL_LINKAGE Campaign : public CampaignHeader, public Serializeable
 {
 	friend class CampaignHandler;
 

+ 4 - 5
lib/gameState/CGameState.cpp

@@ -693,8 +693,8 @@ void CGameState::initFogOfWar()
 	for(auto & elem : teams)
 	{
 		auto & fow = elem.second.fogOfWarMap;
-		fow->resize(boost::extents[layers][map->width][map->height]);
-		std::fill(fow->data(), fow->data() + fow->num_elements(), 0);
+		fow.resize(boost::extents[layers][map->width][map->height]);
+		std::fill(fow.data(), fow.data() + fow.num_elements(), 0);
 
 		for(CGObjectInstance *obj : map->objects)
 		{
@@ -704,7 +704,7 @@ void CGameState::initFogOfWar()
 			getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadius(), ETileVisibility::HIDDEN, obj->tempOwner);
 			for(const int3 & tile : tiles)
 			{
-				(*elem.second.fogOfWarMap)[tile.z][tile.x][tile.y] = 1;
+				elem.second.fogOfWarMap[tile.z][tile.x][tile.y] = 1;
 			}
 		}
 	}
@@ -1326,7 +1326,7 @@ bool CGameState::isVisible(int3 pos, const std::optional<PlayerColor> & player)
 	if(player->isSpectator())
 		return true;
 
-	return (*getPlayerTeam(*player)->fogOfWarMap)[pos.z][pos.x][pos.y];
+	return getPlayerTeam(*player)->fogOfWarMap[pos.z][pos.x][pos.y];
 }
 
 bool CGameState::isVisible(const CGObjectInstance * obj, const std::optional<PlayerColor> & player) const
@@ -1957,7 +1957,6 @@ bool RumorState::update(int id, int extra)
 TeamState::TeamState()
 {
 	setNodeType(TEAM);
-	fogOfWarMap = std::make_unique<boost::multi_array<ui8, 3>>();
 }
 
 CRandomGenerator & CGameState::getRandomGenerator()

+ 1 - 1
lib/gameState/CGameState.h

@@ -79,7 +79,7 @@ class BattleInfo;
 
 DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
 
-class DLL_LINKAGE CGameState : public CNonConstInfoCallback
+class DLL_LINKAGE CGameState : public CNonConstInfoCallback, public Serializeable
 {
 	friend class CGameStateCampaign;
 

+ 2 - 1
lib/gameState/CGameStateCampaign.h

@@ -11,6 +11,7 @@
 
 #include "../GameConstants.h"
 #include "../campaign/CampaignConstants.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -28,7 +29,7 @@ struct CampaignHeroReplacement
 	std::vector<ArtifactPosition> transferrableArtifacts;
 };
 
-class CGameStateCampaign
+class CGameStateCampaign : public Serializeable
 {
 	CGameState * gameState;
 

+ 3 - 1
lib/gameState/TavernHeroesPool.h

@@ -11,6 +11,8 @@
 
 #include "../GameConstants.h"
 #include "TavernSlot.h"
+#include "../serializer/Serializeable.h"
+
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -21,7 +23,7 @@ class CHeroClass;
 class CGameState;
 class CSimpleArmy;
 
-class DLL_LINKAGE TavernHeroesPool
+class DLL_LINKAGE TavernHeroesPool : public Serializeable
 {
 	struct TavernSlot
 	{

+ 2 - 1
lib/mapObjectConstructors/CBankInstanceConstructor.h

@@ -16,10 +16,11 @@
 #include "../ResourceSet.h"
 #include "../json/JsonNode.h"
 #include "../mapObjects/CBank.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-struct BankConfig
+struct BankConfig : public Serializeable
 {
 	ui32 chance = 0; //chance for this level being chosen
 	std::vector<CStackBasicDescriptor> guards; //creature ID, amount

+ 2 - 1
lib/mapObjects/CGObjectInstance.h

@@ -10,10 +10,11 @@
 #pragma once
 
 #include "IObjectInterface.h"
+
+#include "../bonuses/BonusEnum.h"
 #include "../constants/EntityIdentifiers.h"
 #include "../filesystem/ResourcePath.h"
 #include "../int3.h"
-#include "../bonuses/BonusEnum.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 

+ 10 - 9
lib/mapObjects/CQuest.h

@@ -12,6 +12,7 @@
 #include "CRewardableObject.h"
 #include "../ResourceSet.h"
 #include "../MetaString.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -36,7 +37,7 @@ enum class EQuestMission {
 	HOTA_REACH_DATE = 13,
 };
 
-class DLL_LINKAGE CQuest final
+class DLL_LINKAGE CQuest final : public Serializeable
 {
 public:
 
@@ -74,13 +75,13 @@ public:
 	CQuest(); //TODO: Remove constructor
 
 	static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army);
-	virtual bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not
-	virtual void getVisitText(IGameCallback * cb, MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
-	virtual void getCompletionText(IGameCallback * cb, MetaString &text) const;
-	virtual void getRolloverText (IGameCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry
-	virtual void completeQuest(IGameCallback *, const CGHeroInstance * h) const;
-	virtual void addTextReplacements(IGameCallback * cb, MetaString &out, std::vector<Component> & components) const;
-	virtual void addKillTargetReplacements(MetaString &out) const;
+	bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not
+	void getVisitText(IGameCallback * cb, MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
+	void getCompletionText(IGameCallback * cb, MetaString &text) const;
+	void getRolloverText (IGameCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry
+	void completeQuest(IGameCallback *, const CGHeroInstance * h) const;
+	void addTextReplacements(IGameCallback * cb, MetaString &out, std::vector<Component> & components) const;
+	void addKillTargetReplacements(MetaString &out) const;
 	void defineQuestName();
 
 	bool operator== (const CQuest & quest) const
@@ -114,7 +115,7 @@ public:
 	void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName);
 };
 
-class DLL_LINKAGE IQuestObject
+class DLL_LINKAGE IQuestObject : public virtual Serializeable
 {
 public:
 	CQuest * quest = new CQuest();

+ 4 - 3
lib/mapObjects/IObjectInterface.h

@@ -9,10 +9,11 @@
  */
 #pragma once
 
+#include "../GameCallbackHolder.h"
+#include "../constants/EntityIdentifiers.h"
 #include "../networkPacks/EInfoWindowMode.h"
 #include "../networkPacks/ObjProperty.h"
-#include "../constants/EntityIdentifiers.h"
-#include "../GameCallbackHolder.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -29,7 +30,7 @@ class int3;
 class MetaString;
 class PlayerColor;
 
-class DLL_LINKAGE IObjectInterface : public GameCallbackHolder
+class DLL_LINKAGE IObjectInterface : public GameCallbackHolder, public virtual Serializeable
 {
 public:
 	using GameCallbackHolder::GameCallbackHolder;

+ 1 - 1
lib/mapObjects/MiscObjects.h

@@ -185,7 +185,7 @@ protected:
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 };
 
-struct DLL_LINKAGE TeleportChannel
+struct DLL_LINKAGE TeleportChannel : public Serializeable
 {
 	enum EPassability {UNKNOWN, IMPASSABLE, PASSABLE};
 

+ 2 - 1
lib/mapObjects/ObjectTemplate.h

@@ -12,6 +12,7 @@
 #include "../GameConstants.h"
 #include "../int3.h"
 #include "../filesystem/ResourcePath.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -20,7 +21,7 @@ class CLegacyConfigParser;
 class JsonNode;
 class int3;
 
-class DLL_LINKAGE ObjectTemplate
+class DLL_LINKAGE ObjectTemplate : public Serializeable
 {
 	enum EBlockMapBits
 	{

+ 3 - 2
lib/mapping/CMapHeader.h

@@ -13,7 +13,8 @@
 #include "../constants/EntityIdentifiers.h"
 #include "../constants/Enumerations.h"
 #include "../constants/VariantIdentifier.h"
-#include "../modding/CModInfo.h"
+#include "../modding/ModVerificationInfo.h"
+#include "../serializer/Serializeable.h"
 #include "../LogicalExpression.h"
 #include "../int3.h"
 #include "../MetaString.h"
@@ -202,7 +203,7 @@ enum class EMapDifficulty : uint8_t
 };
 
 /// The map header holds information about loss/victory condition,map format, version, players, height, width,...
-class DLL_LINKAGE CMapHeader
+class DLL_LINKAGE CMapHeader: public Serializeable
 {
 	void setupEvents();
 public:

+ 3 - 1
lib/mapping/CMapInfo.h

@@ -9,6 +9,8 @@
  */
 #pragma once
 
+#include "../serializer/Serializeable.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 struct StartInfo;
@@ -21,7 +23,7 @@ class ResourcePath;
  * A class which stores the count of human players and all players, the filename,
  * scenario options, the map header information,...
  */
-class DLL_LINKAGE CMapInfo
+class DLL_LINKAGE CMapInfo : public Serializeable
 {
 public:
 	std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign

+ 2 - 1
lib/networkPacks/NetPacksBase.h

@@ -10,6 +10,7 @@
 #pragma once
 
 #include "../constants/EntityIdentifiers.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -18,7 +19,7 @@ class CConnection;
 
 class ICPackVisitor;
 
-struct DLL_LINKAGE CPack
+struct DLL_LINKAGE CPack : public Serializeable
 {
 	/// Pointer to connection that pack received from
 	/// Only set & used on server

+ 3 - 3
lib/networkPacks/NetPacksLib.cpp

@@ -963,7 +963,7 @@ void FoWChange::applyGs(CGameState *gs)
 	TeamState * team = gs->getPlayerTeam(player);
 	auto & fogOfWarMap = team->fogOfWarMap;
 	for(const int3 & t : tiles)
-		(*fogOfWarMap)[t.z][t.x][t.y] = mode != ETileVisibility::HIDDEN;
+		fogOfWarMap[t.z][t.x][t.y] = mode != ETileVisibility::HIDDEN;
 
 	if (mode == ETileVisibility::HIDDEN) //do not hide too much
 	{
@@ -986,7 +986,7 @@ void FoWChange::applyGs(CGameState *gs)
 			}
 		}
 		for(const int3 & t : tilesRevealed) //probably not the most optimal solution ever
-			(*fogOfWarMap)[t.z][t.x][t.y] = 1;
+			fogOfWarMap[t.z][t.x][t.y] = 1;
 	}
 }
 
@@ -1325,7 +1325,7 @@ void TryMoveHero::applyGs(CGameState *gs)
 
 	auto & fogOfWarMap = gs->getPlayerTeam(h->getOwner())->fogOfWarMap;
 	for(const int3 & t : fowRevealed)
-		(*fogOfWarMap)[t.z][t.x][t.y] = 1;
+		fogOfWarMap[t.z][t.x][t.y] = 1;
 }
 
 void NewStructures::applyGs(CGameState *gs)

+ 2 - 2
lib/pathfinder/PathfinderUtil.h

@@ -19,13 +19,13 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 namespace PathfinderUtil
 {
-	using FoW = std::unique_ptr<boost::multi_array<ui8, 3>>;
+	using FoW = boost::multi_array<ui8, 3>;
 	using ELayer = EPathfindingLayer;
 
 	template<EPathfindingLayer::Type layer>
 	EPathAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, const FoW & fow, const PlayerColor player, const CGameState * gs)
 	{
-		if(!(*fow)[pos.z][pos.x][pos.y])
+		if(!fow[pos.z][pos.x][pos.y])
 			return EPathAccessibility::BLOCKED;
 
 		switch(layer)

+ 2 - 1
lib/rewardable/Limiter.h

@@ -12,6 +12,7 @@
 
 #include "../GameConstants.h"
 #include "../ResourceSet.h"
+#include "../serializer/Serializeable.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -26,7 +27,7 @@ using LimitersList = std::vector<std::shared_ptr<Rewardable::Limiter>>;
 
 /// Limiters of rewards. Rewards will be granted to hero only if he satisfies requirements
 /// Note: for this is only a test - it won't remove anything from hero (e.g. artifacts or creatures)
-struct DLL_LINKAGE Limiter final
+struct DLL_LINKAGE Limiter final : public Serializeable
 {
 	/// day of week, unused if 0, 1-7 will test for current day of week
 	si32 dayOfWeek;

+ 2 - 1
lib/rmg/CMapGenOptions.h

@@ -11,6 +11,7 @@
 #pragma once
 
 #include "../GameConstants.h"
+#include "../serializer/Serializeable.h"
 #include "CRmgTemplate.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -26,7 +27,7 @@ enum class EPlayerType
 
 /// The map gen options class holds values about general map generation settings
 /// e.g. the size of the map, the count of players,...
-class DLL_LINKAGE CMapGenOptions
+class DLL_LINKAGE CMapGenOptions : public Serializeable
 {
 public:
 	/// The player settings class maps the player color, starting town and human player flag.

+ 11 - 11
lib/serializer/BinaryDeserializer.h

@@ -119,7 +119,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 	class IPointerLoader
 	{
 	public:
-		virtual void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
+		virtual Serializeable * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
 		virtual ~IPointerLoader() = default;
 
 		template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr)
@@ -132,7 +132,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 	class CPointerLoader : public IPointerLoader
 	{
 	public:
-		void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const override //data is pointer to the ACTUAL POINTER
+		Serializeable * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const override //data is pointer to the ACTUAL POINTER
 		{
 			auto & s = static_cast<BinaryDeserializer &>(ar);
 
@@ -142,7 +142,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
 
 			ptr->serialize(s);
 
-			return static_cast<void*>(ptr);
+			return static_cast<Serializeable*>(ptr);
 		}
 	};
 
@@ -157,8 +157,8 @@ public:
 	Version version;
 
 	std::vector<std::string> loadedStrings;
-	std::map<ui32, void*> loadedPointers;
-	std::map<const void*, std::shared_ptr<void>> loadedSharedPointers;
+	std::map<ui32, Serializeable*> loadedPointers;
+	std::map<const Serializeable*, std::shared_ptr<Serializeable>> loadedSharedPointers;
 	IGameCallback * cb = nullptr;
 	bool smartPointerSerialization;
 	bool saving;
@@ -355,7 +355,7 @@ public:
 			{
 				// We already got this pointer
 				// Cast it in case we are loading it to a non-first base pointer
-				data = static_cast<T>(i->second);
+				data = dynamic_cast<T>(i->second);
 				return;
 			}
 		}
@@ -380,15 +380,15 @@ public:
 				data = nullptr;
 				return;
 			}
-			data = static_cast<T>(app->loadPtr(*this, cb, pid));
+			data = dynamic_cast<T>(app->loadPtr(*this, cb, pid));
 		}
 	}
 
 	template <typename T>
-	void ptrAllocated(const T *ptr, ui32 pid)
+	void ptrAllocated(T *ptr, ui32 pid)
 	{
 		if(smartPointerSerialization && pid != 0xffffffff)
-			loadedPointers[pid] = (void*)ptr; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
+			loadedPointers[pid] = const_cast<Serializeable*>(dynamic_cast<const Serializeable*>(ptr)); //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
 	}
 
 	template<typename Base, typename Derived> void registerType(const Base * b = nullptr, const Derived * d = nullptr)
@@ -403,7 +403,7 @@ public:
 		NonConstT *internalPtr;
 		load(internalPtr);
 
-		void * internalPtrDerived = static_cast<void*>(internalPtr);
+		Serializeable * internalPtrDerived = static_cast<Serializeable*>(internalPtr);
 
 		if(internalPtr)
 		{
@@ -418,7 +418,7 @@ public:
 			{
 				auto hlp = std::shared_ptr<NonConstT>(internalPtr);
 				data = hlp;
-				loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<void>(hlp);
+				loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<Serializeable>(hlp);
 			}
 		}
 		else

+ 3 - 2
lib/serializer/BinarySerializer.h

@@ -12,6 +12,7 @@
 #include "CSerializer.h"
 #include "CTypeList.h"
 #include "ESerializationVersion.h"
+#include "Serializeable.h"
 #include "../mapObjects/CArmedInstance.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -114,7 +115,7 @@ public:
 	using Version = ESerializationVersion;
 
 	std::map<std::string, uint32_t> savedStrings;
-	std::map<const void*, ui32> savedPointers;
+	std::map<const Serializeable*, ui32> savedPointers;
 
 	const Version version = Version::CURRENT;
 	bool smartPointerSerialization;
@@ -268,7 +269,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.
-			const void * actualPointer = static_cast<const void*>(data);
+			const Serializeable * actualPointer = static_cast<const Serializeable*>(data);
 			auto i = savedPointers.find(actualPointer);
 			if(i != savedPointers.end())
 			{

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -46,6 +46,7 @@ enum class ESerializationVersion : int32_t
 
 	COMPACT_STRING_SERIALIZATION,
 	COMPACT_INTEGER_SERIALIZATION,
+	REMOVE_FOG_OF_WAR_POINTER,
 
-	CURRENT = COMPACT_INTEGER_SERIALIZATION
+	CURRENT = REMOVE_FOG_OF_WAR_POINTER
 };

+ 21 - 0
lib/serializer/Serializeable.h

@@ -0,0 +1,21 @@
+/*
+ * Serializeable.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
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+// Tag class that acts as base for all classes that can be serialized by pointer
+class Serializeable
+{
+public:
+    virtual ~Serializeable() = default;
+};
+
+VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/spells/AdventureSpellMechanics.cpp

@@ -735,7 +735,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
 		{
 			ObjectPosInfo posInfo(obj);
 
-			if((*fowMap)[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
+			if(fowMap[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
 				pack.objectPositions.push_back(posInfo);
 		}
 	}

+ 2 - 2
server/CGameHandler.cpp

@@ -884,11 +884,11 @@ void CGameHandler::onNewTurn()
 				// find all hidden tiles
 				const auto & fow = getPlayerTeam(player)->fogOfWarMap;
 
-				auto shape = fow->shape();
+				auto shape = fow.shape();
 				for(size_t z = 0; z < shape[0]; z++)
 					for(size_t x = 0; x < shape[1]; x++)
 						for(size_t y = 0; y < shape[2]; y++)
-							if (!(*fow)[z][x][y])
+							if (!fow[z][x][y])
 								fw.tiles.insert(int3(x, y, z));
 
 				sendAndApply (&fw);

+ 1 - 1
server/processors/PlayerMessageProcessor.cpp

@@ -367,7 +367,7 @@ void PlayerMessageProcessor::cheatMapReveal(PlayerColor player, bool reveal)
 	for(int z = 0; z < mapSize.z; z++)
 		for(int x = 0; x < mapSize.x; x++)
 			for(int y = 0; y < mapSize.y; y++)
-				if(!(*fowMap)[z][x][y] || fc.mode == ETileVisibility::HIDDEN)
+				if(!fowMap[z][x][y] || fc.mode == ETileVisibility::HIDDEN)
 					hlp_tab[lastUnc++] = int3(x, y, z);
 
 	fc.tiles.insert(hlp_tab, hlp_tab + lastUnc);