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

Serialize Enitity classes by their ID

Ivan Savenko 1 жил өмнө
parent
commit
c7676bde53

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

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

+ 19 - 1
lib/serializer/BinaryDeserializer.h

@@ -258,6 +258,25 @@ public:
 				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)
+	{
 		ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id)
 		if(smartPointerSerialization)
 		{
@@ -273,7 +292,6 @@ public:
 				return;
 			}
 		}
-
 		//get type id
 		ui16 tid;
 		load( tid );

+ 13 - 0
lib/serializer/BinarySerializer.h

@@ -203,6 +203,19 @@ public:
 				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)
+	{
 		if(smartPointerSerialization)
 		{
 			// We might have an object that has multiple inheritance and store it via the non-first base pointer.

+ 0 - 18
lib/serializer/CSerializer.h

@@ -164,24 +164,6 @@ struct VectorizedIDType
 	using type = std::conditional_t<std::is_base_of_v<CGObjectInstance, T>, ObjectInstanceID, int32_t>;
 };
 
-template <>
-struct VectorizedIDType<CArtifact>
-{
-	using type = ArtifactID;
-};
-
-template <>
-struct VectorizedIDType<CCreature>
-{
-	using type = CreatureID;
-};
-
-template <>
-struct VectorizedIDType<CHero>
-{
-	using type = HeroTypeID;
-};
-
 template <>
 struct VectorizedIDType<CArtifactInstance>
 {