1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

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

This commit is contained in:
Tomasz Zieliński
2023-07-05 20:53:00 +02:00
parent 50bed178ca
commit 9f2bfbc1d8
5 changed files with 53 additions and 38 deletions

View File

@@ -33,6 +33,7 @@
#include "StringConstants.h" #include "StringConstants.h"
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "CModHandler.h"//todo: remove #include "CModHandler.h"//todo: remove
#include "TerrainHandler.h" //TODO: remove
#include "BattleFieldHandler.h" #include "BattleFieldHandler.h"
#include "ObstacleHandler.h" #include "ObstacleHandler.h"
@@ -203,7 +204,7 @@ const FactionID FactionID::NEUTRAL = FactionID(9);
si32 FactionID::decode(const std::string & identifier) 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) if(rawId)
return rawId.value(); return rawId.value();
else else
@@ -215,6 +216,31 @@ std::string FactionID::encode(const si32 index)
return VLC->factions()->getByIndex(index)->getJsonKey(); 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) std::ostream & operator<<(std::ostream & os, const EActionType actionType)
{ {
static const std::map<EActionType, std::string> actionTypeToString = static const std::map<EActionType, std::string> actionTypeToString =

View File

@@ -459,11 +459,19 @@ class FactionID : public BaseForID<FactionID, int32_t>
DLL_LINKAGE static const FactionID CONFLUX; DLL_LINKAGE static const FactionID CONFLUX;
DLL_LINKAGE static const FactionID NEUTRAL; 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 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 class BuildingID
{ {

View File

@@ -353,38 +353,13 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
if(terrainTypeLikeZone == NO_ZONE) if(terrainTypeLikeZone == NO_ZONE)
{ {
JsonNode node; handler.serializeIdArray<TerrainId, TerrainID>("terrainTypes", terrainTypes, std::set<TerrainId>());
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.serializeBool("townsAreSameType", townsAreSameType, false); handler.serializeBool("townsAreSameType", townsAreSameType, false);
handler.serializeIdArray<FactionID, FactionID>("allowedMonsters", monsterTypes, std::set<FactionID>()); handler.serializeIdArray<FactionID>("allowedMonsters", monsterTypes, std::set<FactionID>());
handler.serializeIdArray<FactionID, FactionID>("allowedTowns", townTypes, std::set<FactionID>()); handler.serializeIdArray<FactionID>("allowedTowns", townTypes, std::set<FactionID>());
handler.serializeIdArray<FactionID, FactionID>("bannedTowns", bannedTownTypes, std::set<FactionID>()); handler.serializeIdArray<FactionID>("bannedTowns", bannedTownTypes, std::set<FactionID>());
{ {
//TODO: add support for std::map to serializeEnum //TODO: add support for std::map to serializeEnum

View File

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

View File

@@ -334,6 +334,8 @@ public:
} }
///si32-convertible identifier set <-> Json array of string ///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> template <typename T, typename U = T>
void serializeIdArray(const std::string & fieldName, std::set<T> & value, const std::set<T> & defaultValue) 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); si32 item = static_cast<si32>(vitem);
temp.push_back(item); temp.push_back(item);
} }
serializeInternal(fieldName, temp, &U::decode, &U::encode);
} }
serializeInternal(fieldName, temp, &U::decode, &U::encode);
if(!saving) if(!saving)
{ {
if(temp.empty()) JsonNode node;
serializeRaw(fieldName, node, std::nullopt);
if(node.Vector().empty())
{ {
value = defaultValue; value = defaultValue;
} }
@@ -361,10 +365,12 @@ public:
{ {
value.clear(); value.clear();
for(const si32 item : temp) for(const auto & id : node.Vector())
{ {
T vitem = static_cast<T>(item); VLC->modh->identifiers.requestIdentifier(U::scope(), id, [&value](int32_t identifier)
value.insert(vitem); {
value.emplace(identifier);
});
} }
} }
} }