1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +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();
}
std::string HeroTypeID::entityType()
{
return "hero";
}
const CArtifact * ArtifactIDBase::toArtifact() const
{
return dynamic_cast<const CArtifact*>(toArtifact(VLC->artifacts()));
@ -125,7 +130,7 @@ const Artifact * ArtifactIDBase::toArtifact(const ArtifactService * service) con
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);
if(rawId)
@ -134,11 +139,16 @@ si32 ArtifactIDBase::decode(const std::string & identifier)
return -1;
}
std::string ArtifactIDBase::encode(const si32 index)
std::string ArtifactID::encode(const si32 index)
{
return VLC->artifacts()->getByIndex(index)->getJsonKey();
}
std::string ArtifactID::entityType()
{
return "artifact";
}
const CCreature * CreatureIDBase::toCreature() const
{
return VLC->creh->objects.at(num);
@ -149,7 +159,7 @@ const Creature * CreatureIDBase::toCreature(const CreatureService * creatures) c
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);
if(rawId)
@ -158,11 +168,16 @@ si32 CreatureIDBase::decode(const std::string & identifier)
return -1;
}
std::string CreatureIDBase::encode(const si32 index)
std::string CreatureID::encode(const si32 index)
{
return VLC->creatures()->getById(CreatureID(index))->getJsonKey();
}
std::string CreatureID::entityType()
{
return "creature";
}
const CSpell * SpellIDBase::toSpell() const
{
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);
}
si32 SpellIDBase::decode(const std::string & identifier)
si32 SpellID::decode(const std::string & identifier)
{
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "spell", identifier);
if(rawId)
@ -187,11 +202,16 @@ si32 SpellIDBase::decode(const std::string & identifier)
return -1;
}
std::string SpellIDBase::encode(const si32 index)
std::string SpellID::encode(const si32 index)
{
return VLC->spells()->getByIndex(index)->getJsonKey();
}
std::string SpellID::entityType()
{
return "spell";
}
bool PlayerColor::isValidPlayer() const
{
return num >= 0 && num < PLAYER_LIMIT_I;
@ -199,15 +219,15 @@ bool PlayerColor::isValidPlayer() const
bool PlayerColor::isSpectator() const
{
return num == SPECTATOR.num;
}
std::string PlayerColor::toString() const
{
return encode(num);
}
si32 PlayerColor::decode(const std::string & identifier)
return num == SPECTATOR.num;
}
std::string PlayerColor::toString() const
{
return encode(num);
}
si32 PlayerColor::decode(const std::string & identifier)
{
return vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, identifier);
}
@ -217,6 +237,11 @@ std::string PlayerColor::encode(const si32 index)
return GameConstants::PLAYER_COLOR_NAMES[index];
}
std::string PlayerColor::entityType()
{
return "playerColor";
}
si32 FactionID::decode(const std::string & identifier)
{
auto rawId = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), entityType(), identifier);
@ -236,7 +261,7 @@ std::string FactionID::entityType()
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);
if(rawId)
@ -245,12 +270,12 @@ si32 TerrainIdBase::decode(const std::string & identifier)
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();
}
std::string TerrainIdBase::entityType()
std::string TerrainId::entityType()
{
return "terrain";
}

View File

@ -200,6 +200,7 @@ public:
///json serialization helpers
static si32 decode(const std::string & identifier);
static std::string encode(const si32 index);
static std::string entityType();
DLL_LINKAGE static const HeroTypeID NONE;
};
@ -236,16 +237,17 @@ public:
static const PlayerColor NEUTRAL; //255
static const PlayerColor PLAYER_LIMIT; //player limit per map
bool isValidPlayer() const; //valid means < PLAYER_LIMIT (especially non-neutral)
bool isSpectator() const;
std::string toString() const;
static si32 decode(const std::string& identifier);
static std::string encode(const si32 index);
};
class TeamID : public Identifier<TeamID>
bool isValidPlayer() const; //valid means < PLAYER_LIMIT (especially non-neutral)
bool isSpectator() const;
std::string toString() const;
static si32 decode(const std::string& identifier);
static std::string encode(const si32 index);
static std::string entityType();
};
class TeamID : public Identifier<TeamID>
{
public:
using Identifier<TeamID>::Identifier;
@ -627,16 +629,17 @@ public:
DLL_LINKAGE const CArtifact * toArtifact() 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>
{
public:
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
@ -666,16 +669,17 @@ public:
DLL_LINKAGE const CCreature * toCreature() 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>
{
public:
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
@ -783,16 +787,17 @@ public:
DLL_LINKAGE const CSpell * toSpell() const; //deprecated
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>
{
public:
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;
@ -837,16 +842,16 @@ public:
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>
{
public:
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;

View File

@ -65,35 +65,6 @@ void CTreasureInfo::serializeJson(JsonSerializeFormat & handler)
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;
ZoneOptions::CTownInfo::CTownInfo()
@ -508,8 +479,24 @@ void ZoneConnection::serializeJson(JsonSerializeFormat & handler)
"random"
};
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("a", zoneA, -1);
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("b", zoneB, -1);
if (handler.saving)
{
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.serializeEnum("type", connectionType, connectionTypes);
handler.serializeEnum("road", hasRoad, roadOptions);

View File

@ -107,6 +107,20 @@ void JsonDeserializer::serializeInternal(const std::string & fieldName, si32 & v
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)
{
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, 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, std::vector<std::string> & value) override;
void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override;

View File

@ -11,6 +11,7 @@
#include "../JsonNode.h"
#include "../modding/IdentifierStorage.h"
#include "../modding/ModScope.h"
#include "../VCMI_Lib.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -271,36 +272,57 @@ public:
template <typename T, typename U, typename E = T>
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
template <typename T, typename E = T>
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)
{
si32 item = static_cast<si32>(vitem);
temp.push_back(item);
}
fieldValue.push_back(E::encode(vitem));
serializeInternal(fieldName, fieldValue);
}
serializeInternal(fieldName, temp, &E::decode, &E::encode);
if(!saving)
else
{
value.clear();
value.reserve(temp.size());
std::vector<std::string> fieldValue;
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);
value.push_back(vitem);
VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), E::entityType(), fieldValue[i], [&value, i](int32_t index){
value[i] = T(index);
});
}
}
}
@ -309,28 +331,25 @@ public:
template <typename T, typename U = T>
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)
{
si32 item = static_cast<si32>(vitem);
temp.push_back(item);
}
fieldValue.push_back(U::encode(vitem));
serializeInternal(fieldName, fieldValue);
}
serializeInternal(fieldName, temp, &U::decode, &U::encode);
if(!saving)
else
{
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);
value.insert(vitem);
VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), U::entityType(), fieldValue[i], [&value](int32_t index){
value.insert(T(index));
});
}
}
}
@ -340,9 +359,9 @@ public:
void serializeInstance(const std::string & fieldName, T & value, const T & defaultValue)
{
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
@ -376,6 +395,9 @@ protected:
///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;
///String vector <-> Json string vector
virtual void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) = 0;
virtual void pop() = 0;
virtual void pushStruct(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)
{
JsonNode jsonElement(JsonNode::JsonType::DATA_STRING);
jsonElement.String() = encoder(rawId);
data.push_back(std::move(jsonElement));
JsonNode jsonElement(JsonNode::JsonType::DATA_STRING);
jsonElement.String() = encoder(rawId);
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, 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, std::vector<std::string> & value) override;
void serializeInternal(std::string & 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)
{
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, 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, std::vector<std::string> & value) override;
void serializeInternal(std::string & value) override;
void serializeInternal(int64_t & value) override;