Browse Source

Serialize identifiers without implicit conversion to int

Ivan Savenko 2 years ago
parent
commit
8f25f1fd4b

+ 1 - 1
lib/CCreatureHandler.cpp

@@ -388,7 +388,7 @@ void CCreature::serializeJson(JsonSerializeFormat & handler)
 	if(handler.updating)
 	if(handler.updating)
 	{
 	{
 		cost.serializeJson(handler, "cost");
 		cost.serializeJson(handler, "cost");
-		handler.serializeInt("faction", faction);//TODO: unify with deferred resolve
+		handler.serializeId("faction", faction);
 	}
 	}
 
 
 	handler.serializeInt("level", level);
 	handler.serializeInt("level", level);

+ 0 - 19
lib/CSkillHandler.cpp

@@ -262,23 +262,4 @@ std::vector<bool> CSkillHandler::getDefaultAllowed() const
 	return allowedSkills;
 	return allowedSkills;
 }
 }
 
 
-si32 CSkillHandler::decodeSkill(const std::string & identifier)
-{
-	auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeMap(), "skill", identifier);
-	if(rawId)
-		return rawId.value();
-	else
-		return -1;
-}
-
-std::string CSkillHandler::encodeSkill(const si32 index)
-{
-	return (*VLC->skillh)[SecondarySkill(index)]->identifier;
-}
-
-std::string CSkillHandler::encodeSkillWithType(const si32 index)
-{
-	return ModUtility::makeFullIdentifier("", "skill", encodeSkill(index));
-}
-
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END

+ 0 - 5
lib/CSkillHandler.h

@@ -111,11 +111,6 @@ public:
 
 
 	std::vector<bool> getDefaultAllowed() const override;
 	std::vector<bool> getDefaultAllowed() const override;
 
 
-	///json serialization helpers
-	static si32 decodeSkill(const std::string & identifier);
-	static std::string encodeSkill(const si32 index);
-	static std::string encodeSkillWithType(const si32 index);
-
 	template <typename Handler> void serialize(Handler & h, const int version)
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 	{
 		h & objects;
 		h & objects;

+ 1 - 1
lib/battle/Unit.cpp

@@ -218,7 +218,7 @@ int Unit::getRawSurrenderCost() const
 void UnitInfo::serializeJson(JsonSerializeFormat & handler)
 void UnitInfo::serializeJson(JsonSerializeFormat & handler)
 {
 {
 	handler.serializeInt("count", count);
 	handler.serializeInt("count", count);
-	handler.serializeId("type", type, CreatureID::NONE);
+	handler.serializeId("type", type, CreatureID(CreatureID::NONE));
 	handler.serializeInt("side", side);
 	handler.serializeInt("side", side);
 	handler.serializeInt("position", position);
 	handler.serializeInt("position", position);
 	handler.serializeBool("summoned", summoned);
 	handler.serializeBool("summoned", summoned);

+ 4 - 4
lib/mapObjects/CQuest.cpp

@@ -392,15 +392,15 @@ void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fi
 		
 		
 		if(missionType == "Hero")
 		if(missionType == "Hero")
 		{
 		{
-			ui32 temp;
-			handler.serializeId<ui32, ui32, HeroTypeID>("hero", temp, 0);
+			HeroTypeID temp;
+			handler.serializeId("hero", temp, HeroTypeID::NONE);
 			mission.heroes.emplace_back(temp);
 			mission.heroes.emplace_back(temp);
 		}
 		}
 		
 		
 		if(missionType == "Player")
 		if(missionType == "Player")
 		{
 		{
-			ui32 temp;
-			handler.serializeId<ui32, ui32, PlayerColor>("player", temp, PlayerColor::NEUTRAL);
+			PlayerColor temp;
+			handler.serializeId("player", temp, PlayerColor::NEUTRAL);
 			mission.players.emplace_back(temp);
 			mission.players.emplace_back(temp);
 		}
 		}
 	}
 	}

+ 1 - 1
lib/rewardable/Limiter.cpp

@@ -249,7 +249,7 @@ void Rewardable::Limiter::serializeJson(JsonSerializeFormat & handler)
 		std::vector<std::pair<SecondarySkill, si32>> fieldValue(secondary.begin(), secondary.end());
 		std::vector<std::pair<SecondarySkill, si32>> fieldValue(secondary.begin(), secondary.end());
 		a.serializeStruct<std::pair<SecondarySkill, si32>>(fieldValue, [](JsonSerializeFormat & h, std::pair<SecondarySkill, si32> & e)
 		a.serializeStruct<std::pair<SecondarySkill, si32>>(fieldValue, [](JsonSerializeFormat & h, std::pair<SecondarySkill, si32> & e)
 		{
 		{
-			h.serializeId("skill", e.first, SecondarySkill{}, VLC->skillh->decodeSkill, VLC->skillh->encodeSkill);
+			h.serializeId("skill", e.first, SecondarySkill(SecondarySkill::NONE));
 			h.serializeId("level", e.second, 0, [](const std::string & i){return vstd::find_pos(NSecondarySkill::levels, i);}, [](si32 i){return NSecondarySkill::levels.at(i);});
 			h.serializeId("level", e.second, 0, [](const std::string & i){return vstd::find_pos(NSecondarySkill::levels, i);}, [](si32 i){return NSecondarySkill::levels.at(i);});
 		});
 		});
 		a.syncSize(fieldValue);
 		a.syncSize(fieldValue);

+ 4 - 4
lib/serializer/CSerializer.h

@@ -53,14 +53,14 @@ struct VectorizedObjectInfo
 /// Base class for serializers capable of reading or writing data
 /// Base class for serializers capable of reading or writing data
 class DLL_LINKAGE CSerializer
 class DLL_LINKAGE CSerializer
 {
 {
-	template<typename T>
-	static si32 idToNumber(const T &t, typename std::enable_if<std::is_convertible<T,si32>::value>::type * dummy = nullptr)
+	template<typename Numeric, std::enable_if_t<std::is_arithmetic_v<Numeric>, bool> = true>
+	static int32_t idToNumber(const Numeric &t)
 	{
 	{
 		return t;
 		return t;
 	}
 	}
 
 
-	template<typename T, typename NT>
-	static NT idToNumber(const IdentifierBase &t)
+	template<typename IdentifierType, std::enable_if_t<std::is_base_of_v<IdentifierBase, IdentifierType>, bool> = true>
+	static int32_t idToNumber(const IdentifierType &t)
 	{
 	{
 		return t.getNum();
 		return t.getNum();
 	}
 	}

+ 28 - 9
lib/serializer/JsonSerializeFormat.h

@@ -295,14 +295,16 @@ public:
 	}
 	}
 
 
 	///si32-convertible identifier <-> Json string
 	///si32-convertible identifier <-> Json string
-	template <typename T, typename U, typename E = T>
-	void serializeId(const std::string & fieldName, T & value, const U & defaultValue)
+	template <typename IdentifierType, typename IdentifierTypeBase = IdentifierType>
+	void serializeId(const std::string & fieldName, IdentifierType & value, const IdentifierTypeBase & defaultValue = IdentifierType::NONE)
 	{
 	{
+		static_assert(std::is_base_of_v<IdentifierBase, IdentifierType>, "This method can only serialize Identifier classes!");
+
 		if (saving)
 		if (saving)
 		{
 		{
 			if (value != defaultValue)
 			if (value != defaultValue)
 			{
 			{
-				std::string fieldValue = E::encode(value);
+				std::string fieldValue = IdentifierType::encode(value.getNum());
 				serializeString(fieldName, fieldValue);
 				serializeString(fieldName, fieldValue);
 			}
 			}
 		}
 		}
@@ -313,13 +315,13 @@ public:
 
 
 			if (!fieldValue.empty())
 			if (!fieldValue.empty())
 			{
 			{
-				VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), E::entityType(), fieldValue, [&value](int32_t index){
-					value = T(index);
+				VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), IdentifierType::entityType(), fieldValue, [&value](int32_t index){
+					value = IdentifierType(index);
 				});
 				});
 			}
 			}
 			else
 			else
 			{
 			{
-				value = T(defaultValue);
+				value = IdentifierType(defaultValue);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -333,7 +335,7 @@ public:
 			std::vector<std::string> fieldValue;
 			std::vector<std::string> fieldValue;
 
 
 			for(const T & vitem : value)
 			for(const T & vitem : value)
-				fieldValue.push_back(E::encode(vitem));
+				fieldValue.push_back(E::encode(vitem.getNum()));
 
 
 			serializeInternal(fieldName, fieldValue);
 			serializeInternal(fieldName, fieldValue);
 		}
 		}
@@ -362,7 +364,7 @@ public:
 			std::vector<std::string> fieldValue;
 			std::vector<std::string> fieldValue;
 
 
 			for(const T & vitem : value)
 			for(const T & vitem : value)
-				fieldValue.push_back(U::encode(vitem));
+				fieldValue.push_back(U::encode(vitem.getNum()));
 
 
 			serializeInternal(fieldName, fieldValue);
 			serializeInternal(fieldName, fieldValue);
 		}
 		}
@@ -387,7 +389,24 @@ public:
 		const TDecoder decoder = std::bind(&IInstanceResolver::decode, instanceResolver, _1);
 		const TDecoder decoder = std::bind(&IInstanceResolver::decode, instanceResolver, _1);
 		const TEncoder encoder = std::bind(&IInstanceResolver::encode, instanceResolver, _1);
 		const TEncoder encoder = std::bind(&IInstanceResolver::encode, instanceResolver, _1);
 
 
-		serializeId<T>(fieldName, value, defaultValue, decoder, encoder);
+		if (saving)
+		{
+			if (value != defaultValue)
+			{
+				std::string fieldValue = encoder(value.getNum());
+				serializeString(fieldName, fieldValue);
+			}
+		}
+		else
+		{
+			std::string fieldValue;
+			serializeString(fieldName, fieldValue);
+
+			if (!fieldValue.empty())
+				value = T(decoder(fieldValue));
+			else
+				value = T(defaultValue);
+		}
 	}
 	}
 
 
 	///any serializable object <-> Json struct
 	///any serializable object <-> Json struct