Quellcode durchsuchen

Improve serialization of IDs from mods, so they are resolved correctly after all mods are loaded.

Tomasz Zieliński vor 2 Jahren
Ursprung
Commit
9f2bfbc1d8

+ 27 - 1
lib/GameConstants.cpp

@@ -33,6 +33,7 @@
 #include "StringConstants.h"
 #include "CGeneralTextHandler.h"
 #include "CModHandler.h"//todo: remove
+#include "TerrainHandler.h" //TODO: remove
 #include "BattleFieldHandler.h"
 #include "ObstacleHandler.h"
 
@@ -203,7 +204,7 @@ const FactionID FactionID::NEUTRAL = FactionID(9);
 
 si32 FactionID::decode(const std::string & identifier)
 {
-	auto rawId = VLC->modh->identifiers.getIdentifier(CModHandler::scopeGame(), "faction", identifier);
+	auto rawId = VLC->modh->identifiers.getIdentifier(CModHandler::scopeGame(), scope(), identifier);
 	if(rawId)
 		return rawId.value();
 	else
@@ -215,6 +216,31 @@ std::string FactionID::encode(const si32 index)
 	return VLC->factions()->getByIndex(index)->getJsonKey();
 }
 
+std::string FactionID::scope()
+{
+	return "faction";
+}
+
+
+si32 TerrainID::decode(const std::string & identifier)
+{
+	auto rawId = VLC->modh->identifiers.getIdentifier(CModHandler::scopeGame(), scope(), identifier);
+	if(rawId)
+		return rawId.value();
+	else
+		return static_cast<si32>(ETerrainId::NONE);
+}
+
+std::string TerrainID::encode(const si32 index)
+{
+	return VLC->terrainTypeHandler->getByIndex(index)->getJsonKey();
+}
+
+std::string TerrainID::scope()
+{
+	return "terrain";
+}
+
 std::ostream & operator<<(std::ostream & os, const EActionType actionType)
 {
 	static const std::map<EActionType, std::string> actionTypeToString =

+ 10 - 2
lib/GameConstants.h

@@ -459,11 +459,19 @@ class FactionID : public BaseForID<FactionID, int32_t>
 	DLL_LINKAGE static const FactionID CONFLUX;
 	DLL_LINKAGE static const FactionID NEUTRAL;
 
-	///json serialization helpers
-	static si32 decode(const std::string & identifier);
+	static si32 decode(const std::string& identifier);
 	static std::string encode(const si32 index);
+	static std::string scope();
 };
 
+class TerrainID
+{
+	//Dummy class used only for serialization
+public:
+	static si32 decode(const std::string & identifier);
+	static std::string encode(const si32 index);
+	static std::string scope();
+};
 
 class BuildingID
 {

+ 4 - 29
lib/rmg/CRmgTemplate.cpp

@@ -353,38 +353,13 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
 
 	if(terrainTypeLikeZone == NO_ZONE)
 	{
-		JsonNode node;
-		if(handler.saving)
-		{
-			node.setType(JsonNode::JsonType::DATA_VECTOR);
-			for(const auto & ttype : terrainTypes)
-			{
-				JsonNode n;
-				n.String() = VLC->terrainTypeHandler->getById(ttype)->getJsonKey();
-				node.Vector().push_back(n);
-			}
-		}
-		handler.serializeRaw("terrainTypes", node, std::nullopt);
-		if(!handler.saving)
-		{
-			if(!node.Vector().empty())
-			{
-				terrainTypes.clear();
-				for(const auto & ttype : node.Vector())
-				{
-					VLC->modh->identifiers.requestIdentifier("terrain", ttype, [this](int32_t identifier)
-					{
-						terrainTypes.emplace(identifier);
-					});
-				}
-			}
-		}
+		handler.serializeIdArray<TerrainId, TerrainID>("terrainTypes", terrainTypes, std::set<TerrainId>());
 	}
 
 	handler.serializeBool("townsAreSameType", townsAreSameType, false);
-	handler.serializeIdArray<FactionID, FactionID>("allowedMonsters", monsterTypes, std::set<FactionID>());
-	handler.serializeIdArray<FactionID, FactionID>("allowedTowns", townTypes, std::set<FactionID>());
-	handler.serializeIdArray<FactionID, FactionID>("bannedTowns", bannedTownTypes, std::set<FactionID>());
+	handler.serializeIdArray<FactionID>("allowedMonsters", monsterTypes, std::set<FactionID>());
+	handler.serializeIdArray<FactionID>("allowedTowns", townTypes, std::set<FactionID>());
+	handler.serializeIdArray<FactionID>("bannedTowns", bannedTownTypes, std::set<FactionID>());
 
 	{
 		//TODO: add support for std::map to serializeEnum

+ 1 - 1
lib/rmg/modificators/TerrainPainter.cpp

@@ -82,7 +82,7 @@ void TerrainPainter::initTerrainType()
 							if ((terrain->isSurface() && !zone.isUnderground()) ||
 								(terrain->isUnderground() && zone.isUnderground()))
 							{
-								terrainTypes.insert(terrain->getId());
+								terrainTypes.insert(TerrainId(terrain->getId()));
 							}
 						}
 					}

+ 11 - 5
lib/serializer/JsonSerializeFormat.h

@@ -334,6 +334,8 @@ public:
 	}
 
 	///si32-convertible identifier set <-> Json array of string
+	///Type U is only used for code & decode
+	///TODO: Auto deduce U based on T?
 	template <typename T, typename U = T>
 	void serializeIdArray(const std::string & fieldName, std::set<T> & value, const std::set<T> & defaultValue)
 	{
@@ -348,12 +350,14 @@ public:
 				si32 item = static_cast<si32>(vitem);
 				temp.push_back(item);
 			}
+			serializeInternal(fieldName, temp, &U::decode, &U::encode);
 		}
 
-		serializeInternal(fieldName, temp, &U::decode, &U::encode);
 		if(!saving)
 		{
-			if(temp.empty())
+			JsonNode node;
+			serializeRaw(fieldName, node, std::nullopt);
+			if(node.Vector().empty())
 			{
 				value = defaultValue;
 			}
@@ -361,10 +365,12 @@ public:
 			{
 				value.clear();
 
-				for(const si32 item : temp)
+				for(const auto & id : node.Vector())
 				{
-					T vitem = static_cast<T>(item);
-					value.insert(vitem);
+					VLC->modh->identifiers.requestIdentifier(U::scope(), id, [&value](int32_t identifier)
+					{
+						value.emplace(identifier);
+					});
 				}
 			}
 		}