1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Json Serializer should now use identifers storage properly

This commit is contained in:
Ivan Savenko
2023-09-04 22:23:20 +03:00
parent 9735fa6d06
commit b6a1a8f0da
10 changed files with 189 additions and 112 deletions

View File

@@ -115,6 +115,11 @@ std::string HeroTypeID::encode(const si32 index)
return VLC->heroTypes()->getByIndex(index)->getJsonKey(); return VLC->heroTypes()->getByIndex(index)->getJsonKey();
} }
std::string HeroTypeID::entityType()
{
return "hero";
}
const CArtifact * ArtifactIDBase::toArtifact() const const CArtifact * ArtifactIDBase::toArtifact() const
{ {
return dynamic_cast<const CArtifact*>(toArtifact(VLC->artifacts())); return dynamic_cast<const CArtifact*>(toArtifact(VLC->artifacts()));
@@ -125,7 +130,7 @@ const Artifact * ArtifactIDBase::toArtifact(const ArtifactService * service) con
return service->getByIndex(num); return service->getByIndex(num);
} }
si32 ArtifactIDBase::decode(const std::string & identifier) si32 ArtifactID::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "artifact", identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "artifact", identifier);
if(rawId) if(rawId)
@@ -134,11 +139,16 @@ si32 ArtifactIDBase::decode(const std::string & identifier)
return -1; return -1;
} }
std::string ArtifactIDBase::encode(const si32 index) std::string ArtifactID::encode(const si32 index)
{ {
return VLC->artifacts()->getByIndex(index)->getJsonKey(); return VLC->artifacts()->getByIndex(index)->getJsonKey();
} }
std::string ArtifactID::entityType()
{
return "artifact";
}
const CCreature * CreatureIDBase::toCreature() const const CCreature * CreatureIDBase::toCreature() const
{ {
return VLC->creh->objects.at(num); return VLC->creh->objects.at(num);
@@ -149,7 +159,7 @@ const Creature * CreatureIDBase::toCreature(const CreatureService * creatures) c
return creatures->getByIndex(num); return creatures->getByIndex(num);
} }
si32 CreatureIDBase::decode(const std::string & identifier) si32 CreatureID::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "creature", identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "creature", identifier);
if(rawId) if(rawId)
@@ -158,11 +168,16 @@ si32 CreatureIDBase::decode(const std::string & identifier)
return -1; return -1;
} }
std::string CreatureIDBase::encode(const si32 index) std::string CreatureID::encode(const si32 index)
{ {
return VLC->creatures()->getById(CreatureID(index))->getJsonKey(); return VLC->creatures()->getById(CreatureID(index))->getJsonKey();
} }
std::string CreatureID::entityType()
{
return "creature";
}
const CSpell * SpellIDBase::toSpell() const const CSpell * SpellIDBase::toSpell() const
{ {
if(num < 0 || num >= VLC->spellh->objects.size()) if(num < 0 || num >= VLC->spellh->objects.size())
@@ -178,7 +193,7 @@ const spells::Spell * SpellIDBase::toSpell(const spells::Service * service) cons
return service->getByIndex(num); return service->getByIndex(num);
} }
si32 SpellIDBase::decode(const std::string & identifier) si32 SpellID::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "spell", identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "spell", identifier);
if(rawId) if(rawId)
@@ -187,11 +202,16 @@ si32 SpellIDBase::decode(const std::string & identifier)
return -1; return -1;
} }
std::string SpellIDBase::encode(const si32 index) std::string SpellID::encode(const si32 index)
{ {
return VLC->spells()->getByIndex(index)->getJsonKey(); return VLC->spells()->getByIndex(index)->getJsonKey();
} }
std::string SpellID::entityType()
{
return "spell";
}
bool PlayerColor::isValidPlayer() const bool PlayerColor::isValidPlayer() const
{ {
return num >= 0 && num < PLAYER_LIMIT_I; return num >= 0 && num < PLAYER_LIMIT_I;
@@ -217,6 +237,11 @@ std::string PlayerColor::encode(const si32 index)
return GameConstants::PLAYER_COLOR_NAMES[index]; return GameConstants::PLAYER_COLOR_NAMES[index];
} }
std::string PlayerColor::entityType()
{
return "playerColor";
}
si32 FactionID::decode(const std::string & identifier) si32 FactionID::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier);
@@ -236,7 +261,7 @@ std::string FactionID::entityType()
return "faction"; return "faction";
} }
si32 TerrainIdBase::decode(const std::string & identifier) si32 TerrainId::decode(const std::string & identifier)
{ {
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier); auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier);
if(rawId) if(rawId)
@@ -245,12 +270,12 @@ si32 TerrainIdBase::decode(const std::string & identifier)
return static_cast<si32>(TerrainId::NONE); return static_cast<si32>(TerrainId::NONE);
} }
std::string TerrainIdBase::encode(const si32 index) std::string TerrainId::encode(const si32 index)
{ {
return VLC->terrainTypeHandler->getByIndex(index)->getJsonKey(); return VLC->terrainTypeHandler->getByIndex(index)->getJsonKey();
} }
std::string TerrainIdBase::entityType() std::string TerrainId::entityType()
{ {
return "terrain"; return "terrain";
} }

View File

@@ -200,6 +200,7 @@ public:
///json serialization helpers ///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 entityType();
DLL_LINKAGE static const HeroTypeID NONE; DLL_LINKAGE static const HeroTypeID NONE;
}; };
@@ -243,6 +244,7 @@ public:
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 entityType();
}; };
class TeamID : public Identifier<TeamID> class TeamID : public Identifier<TeamID>
@@ -627,16 +629,17 @@ public:
DLL_LINKAGE const CArtifact * toArtifact() const; DLL_LINKAGE const CArtifact * toArtifact() const;
DLL_LINKAGE const Artifact * toArtifact(const ArtifactService * service) const; DLL_LINKAGE const Artifact * toArtifact(const ArtifactService * service) const;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
}; };
class ArtifactID : public IdentifierWithEnum<ArtifactID, ArtifactIDBase> class ArtifactID : public IdentifierWithEnum<ArtifactID, ArtifactIDBase>
{ {
public: public:
using IdentifierWithEnum<ArtifactID, ArtifactIDBase>::IdentifierWithEnum; using IdentifierWithEnum<ArtifactID, ArtifactIDBase>::IdentifierWithEnum;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
}; };
class CreatureIDBase : public IdentifierBase class CreatureIDBase : public IdentifierBase
@@ -666,16 +669,17 @@ public:
DLL_LINKAGE const CCreature * toCreature() const; DLL_LINKAGE const CCreature * toCreature() const;
DLL_LINKAGE const Creature * toCreature(const CreatureService * creatures) const; DLL_LINKAGE const Creature * toCreature(const CreatureService * creatures) const;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
}; };
class CreatureID : public IdentifierWithEnum<CreatureID, CreatureIDBase> class CreatureID : public IdentifierWithEnum<CreatureID, CreatureIDBase>
{ {
public: public:
using IdentifierWithEnum<CreatureID, CreatureIDBase>::IdentifierWithEnum; using IdentifierWithEnum<CreatureID, CreatureIDBase>::IdentifierWithEnum;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
}; };
class SpellIDBase : public IdentifierBase class SpellIDBase : public IdentifierBase
@@ -783,16 +787,17 @@ public:
DLL_LINKAGE const CSpell * toSpell() const; //deprecated DLL_LINKAGE const CSpell * toSpell() const; //deprecated
DLL_LINKAGE const spells::Spell * toSpell(const spells::Service * service) const; DLL_LINKAGE const spells::Spell * toSpell(const spells::Service * service) const;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
}; };
class SpellID : public IdentifierWithEnum<SpellID, SpellIDBase> class SpellID : public IdentifierWithEnum<SpellID, SpellIDBase>
{ {
public: public:
using IdentifierWithEnum<SpellID, SpellIDBase>::IdentifierWithEnum; using IdentifierWithEnum<SpellID, SpellIDBase>::IdentifierWithEnum;
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
}; };
class BattleFieldInfo; class BattleFieldInfo;
@@ -837,16 +842,16 @@ public:
ROCK, ROCK,
ORIGINAL_REGULAR_TERRAIN_COUNT = ROCK ORIGINAL_REGULAR_TERRAIN_COUNT = ROCK
}; };
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
}; };
class TerrainId : public IdentifierWithEnum<TerrainId, TerrainIdBase> class TerrainId : public IdentifierWithEnum<TerrainId, TerrainIdBase>
{ {
public: public:
using IdentifierWithEnum<TerrainId, TerrainIdBase>::IdentifierWithEnum; using IdentifierWithEnum<TerrainId, TerrainIdBase>::IdentifierWithEnum;
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
}; };
class ObstacleInfo; class ObstacleInfo;

View File

@@ -65,35 +65,6 @@ void CTreasureInfo::serializeJson(JsonSerializeFormat & handler)
namespace rmg namespace rmg
{ {
//FIXME: This is never used, instead TerrainID is used
class TerrainEncoder
{
public:
static si32 decode(const std::string & identifier)
{
return *VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "terrain", identifier);
}
static std::string encode(const si32 index)
{
return VLC->terrainTypeHandler->getByIndex(index)->getJsonKey();
}
};
class ZoneEncoder
{
public:
static si32 decode(const std::string & json)
{
return std::stoi(json);
}
static std::string encode(si32 id)
{
return std::to_string(id);
}
};
const TRmgTemplateZoneId ZoneOptions::NO_ZONE = -1; const TRmgTemplateZoneId ZoneOptions::NO_ZONE = -1;
ZoneOptions::CTownInfo::CTownInfo() ZoneOptions::CTownInfo::CTownInfo()
@@ -508,8 +479,24 @@ void ZoneConnection::serializeJson(JsonSerializeFormat & handler)
"random" "random"
}; };
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("a", zoneA, -1); if (handler.saving)
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("b", zoneB, -1); {
std::string zoneNameA = std::to_string(zoneA);
std::string zoneNameB = std::to_string(zoneB);
handler.serializeString("a", zoneNameA);
handler.serializeString("b", zoneNameB);
}
else
{
std::string zoneNameA;
std::string zoneNameB;
handler.serializeString("a", zoneNameA);
handler.serializeString("b", zoneNameB);
zoneA = std::stoi(zoneNameA);
zoneB = std::stoi(zoneNameB);
}
handler.serializeInt("guard", guardStrength, 0); handler.serializeInt("guard", guardStrength, 0);
handler.serializeEnum("type", connectionType, connectionTypes); handler.serializeEnum("type", connectionType, connectionTypes);
handler.serializeEnum("road", hasRoad, roadOptions); handler.serializeEnum("road", hasRoad, roadOptions);

View File

@@ -107,6 +107,20 @@ void JsonDeserializer::serializeInternal(const std::string & fieldName, si32 & v
value = rawValue; value = rawValue;
} }
void JsonDeserializer::serializeInternal(const std::string & fieldName, std::vector<std::string> & value)
{
const JsonVector & data = currentObject->operator[](fieldName).Vector();
value.clear();
value.reserve(data.size());
for(const JsonNode& elem : data)
{
std::string rawId = elem.String();
value.push_back(rawId);
}
}
void JsonDeserializer::serializeInternal(std::string & value) void JsonDeserializer::serializeInternal(std::string & value)
{ {
value = currentObject->String(); value = currentObject->String();

View File

@@ -33,6 +33,7 @@ protected:
void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override; void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;

View File

@@ -11,6 +11,7 @@
#include "../JsonNode.h" #include "../JsonNode.h"
#include "../modding/IdentifierStorage.h" #include "../modding/IdentifierStorage.h"
#include "../modding/ModScope.h"
#include "../VCMI_Lib.h" #include "../VCMI_Lib.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -271,36 +272,57 @@ public:
template <typename T, typename U, typename E = T> template <typename T, typename U, typename E = T>
void serializeId(const std::string & fieldName, T & value, const U & defaultValue) void serializeId(const std::string & fieldName, T & value, const U & defaultValue)
{ {
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, &E::decode, &E::encode); if (saving)
{
if (value != defaultValue)
{
std::string fieldValue = E::encode(value);
serializeString(fieldName, fieldValue);
}
}
else
{
std::string fieldValue;
serializeString(fieldName, fieldValue);
if (!fieldValue.empty())
{
VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), E::entityType(), fieldValue, [&value](int32_t index){
value = T(index);
});
}
else
{
value = T(defaultValue);
}
}
} }
///si32-convertible identifier vector <-> Json array of string ///si32-convertible identifier vector <-> Json array of string
template <typename T, typename E = T> template <typename T, typename E = T>
void serializeIdArray(const std::string & fieldName, std::vector<T> & value) void serializeIdArray(const std::string & fieldName, std::vector<T> & value)
{ {
std::vector<si32> temp; if (saving)
if(saving)
{ {
temp.reserve(value.size()); std::vector<std::string> fieldValue;
for(const T & vitem : value) for(const T & vitem : value)
{ fieldValue.push_back(E::encode(vitem));
si32 item = static_cast<si32>(vitem);
temp.push_back(item); serializeInternal(fieldName, fieldValue);
}
} }
else
serializeInternal(fieldName, temp, &E::decode, &E::encode);
if(!saving)
{ {
value.clear(); std::vector<std::string> fieldValue;
value.reserve(temp.size()); serializeInternal(fieldName, fieldValue);
for(const si32 item : temp) value.resize(fieldValue.size());
for(size_t i = 0; i < fieldValue.size(); ++i)
{ {
T vitem = static_cast<T>(item); VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), E::entityType(), fieldValue[i], [&value, i](int32_t index){
value.push_back(vitem); value[i] = T(index);
});
} }
} }
} }
@@ -309,28 +331,25 @@ public:
template <typename T, typename U = T> template <typename T, typename U = T>
void serializeIdArray(const std::string & fieldName, std::set<T> & value) void serializeIdArray(const std::string & fieldName, std::set<T> & value)
{ {
std::vector<si32> temp; if (saving)
if(saving)
{ {
temp.reserve(value.size()); std::vector<std::string> fieldValue;
for(const T & vitem : value) for(const T & vitem : value)
{ fieldValue.push_back(U::encode(vitem));
si32 item = static_cast<si32>(vitem);
temp.push_back(item); serializeInternal(fieldName, fieldValue);
}
} }
else
serializeInternal(fieldName, temp, &U::decode, &U::encode);
if(!saving)
{ {
value.clear(); std::vector<std::string> fieldValue;
serializeInternal(fieldName, fieldValue);
for(const si32 item : temp) for(size_t i = 0; i < fieldValue.size(); ++i)
{ {
T vitem = static_cast<T>(item); VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), U::entityType(), fieldValue[i], [&value](int32_t index){
value.insert(vitem); value.insert(T(index));
});
} }
} }
} }
@@ -340,9 +359,9 @@ public:
void serializeInstance(const std::string & fieldName, T & value, const T & defaultValue) void serializeInstance(const std::string & fieldName, T & value, const T & defaultValue)
{ {
const TDecoder decoder = std::bind(&IInstanceResolver::decode, instanceResolver, _1); const TDecoder decoder = std::bind(&IInstanceResolver::decode, instanceResolver, _1);
const TEncoder endoder = std::bind(&IInstanceResolver::encode, instanceResolver, _1); const TEncoder encoder = std::bind(&IInstanceResolver::encode, instanceResolver, _1);
serializeId<T>(fieldName, value, defaultValue, decoder, endoder); serializeId<T>(fieldName, value, defaultValue, decoder, encoder);
} }
///any serializable object <-> Json struct ///any serializable object <-> Json struct
@@ -376,6 +395,9 @@ protected:
///Enum/Numeric <-> Json string enum ///Enum/Numeric <-> Json string enum
virtual void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) = 0; virtual void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) = 0;
///String vector <-> Json string vector
virtual void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) = 0;
virtual void pop() = 0; virtual void pop() = 0;
virtual void pushStruct(const std::string & fieldName) = 0; virtual void pushStruct(const std::string & fieldName) = 0;
virtual void pushArray(const std::string & fieldName) = 0; virtual void pushArray(const std::string & fieldName) = 0;

View File

@@ -63,9 +63,25 @@ void JsonSerializer::serializeInternal(const std::string & fieldName, std::vecto
for(const si32 rawId : value) for(const si32 rawId : value)
{ {
JsonNode jsonElement(JsonNode::JsonType::DATA_STRING); JsonNode jsonElement(JsonNode::JsonType::DATA_STRING);
jsonElement.String() = encoder(rawId); jsonElement.String() = encoder(rawId);
data.push_back(std::move(jsonElement)); data.push_back(std::move(jsonElement));
}
}
void JsonSerializer::serializeInternal(const std::string & fieldName, std::vector<std::string> & value)
{
if(value.empty())
return;
JsonVector & data = currentObject->operator[](fieldName).Vector();
data.reserve(value.size());
for(const auto & rawId : value)
{
JsonNode jsonElement(JsonNode::JsonType::DATA_STRING);
jsonElement.String() = rawId;
data.push_back(std::move(jsonElement));
} }
} }

View File

@@ -32,6 +32,7 @@ protected:
void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override; void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;

View File

@@ -61,6 +61,11 @@ void JsonUpdater::serializeInternal(const std::string & fieldName, std::vector<s
// } // }
} }
void JsonUpdater::serializeInternal(const std::string & fieldName, std::vector<std::string> & value)
{
// TODO
}
void JsonUpdater::serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) void JsonUpdater::serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue)
{ {
const JsonNode & data = currentObject->operator[](fieldName); const JsonNode & data = currentObject->operator[](fieldName);

View File

@@ -37,6 +37,7 @@ protected:
void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override; void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override; void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) override;
void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override; void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) override;
void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) override;
void serializeInternal(std::string & value) override; void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override; void serializeInternal(int64_t & value) override;