2016-02-13 09:47:40 +02:00
|
|
|
/*
|
|
|
|
* JsonSerializeFormat.h, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
#include "../JsonNode.h"
|
2023-07-30 19:12:25 +02:00
|
|
|
#include "../modding/IdentifierStorage.h"
|
2023-09-04 21:23:20 +02:00
|
|
|
#include "../modding/ModScope.h"
|
2023-07-05 21:18:30 +02:00
|
|
|
#include "../VCMI_Lib.h"
|
2016-02-13 09:47:40 +02:00
|
|
|
|
2022-07-26 15:07:42 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
2016-02-13 09:47:40 +02:00
|
|
|
class JsonSerializeFormat;
|
2016-11-13 12:38:42 +02:00
|
|
|
class JsonStructSerializer;
|
|
|
|
class JsonArraySerializer;
|
2016-02-13 09:47:40 +02:00
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
class DLL_LINKAGE IInstanceResolver
|
2016-02-13 09:47:40 +02:00
|
|
|
{
|
|
|
|
public:
|
2016-11-13 12:38:42 +02:00
|
|
|
virtual ~IInstanceResolver(){};
|
|
|
|
virtual si32 decode(const std::string & identifier) const = 0;
|
|
|
|
virtual std::string encode(si32 identifier) const = 0;
|
|
|
|
};
|
2016-02-13 09:47:40 +02:00
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
class DLL_LINKAGE JsonSerializeHelper: public boost::noncopyable
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
|
|
|
public:
|
2023-02-11 17:13:21 +02:00
|
|
|
JsonSerializeHelper(JsonSerializeHelper && other) noexcept;
|
2016-11-13 12:38:42 +02:00
|
|
|
virtual ~JsonSerializeHelper();
|
2016-02-13 09:47:40 +02:00
|
|
|
|
|
|
|
JsonSerializeFormat * operator->();
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
protected:
|
2017-07-20 06:08:49 +02:00
|
|
|
JsonSerializeHelper(JsonSerializeFormat * owner_);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
JsonSerializeFormat * owner;
|
2016-11-13 12:38:42 +02:00
|
|
|
private:
|
|
|
|
bool restoreState;
|
|
|
|
};
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
class DLL_LINKAGE JsonStructSerializer: public JsonSerializeHelper
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
|
|
|
public:
|
2023-02-11 17:13:21 +02:00
|
|
|
JsonStructSerializer(JsonStructSerializer && other) noexcept;
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
protected:
|
2017-07-20 06:08:49 +02:00
|
|
|
JsonStructSerializer(JsonSerializeFormat * owner_);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2016-02-13 09:47:40 +02:00
|
|
|
friend class JsonSerializeFormat;
|
2016-11-13 12:38:42 +02:00
|
|
|
friend class JsonArraySerializer;
|
|
|
|
};
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
class DLL_LINKAGE JsonArraySerializer: public JsonSerializeHelper
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
|
|
|
public:
|
2023-02-11 17:13:21 +02:00
|
|
|
JsonArraySerializer(JsonArraySerializer && other) noexcept;
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
JsonStructSerializer enterStruct(const size_t index);
|
2017-07-20 06:08:49 +02:00
|
|
|
JsonArraySerializer enterArray(const size_t index);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
template <typename Container>
|
2017-11-26 23:18:18 +02:00
|
|
|
void syncSize(Container & c, JsonNode::JsonType type = JsonNode::JsonType::DATA_NULL);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
///Anything int64-convertible <-> Json integer
|
|
|
|
template <typename T>
|
|
|
|
void serializeInt(const size_t index, T & value);
|
|
|
|
|
|
|
|
///String <-> Json string
|
|
|
|
void serializeString(const size_t index, std::string & value);
|
|
|
|
|
2023-09-17 22:19:45 +02:00
|
|
|
///vector of anything int-convertible <-> Json vector of integers
|
|
|
|
template<typename T>
|
|
|
|
void serializeArray(std::vector<T> & value)
|
|
|
|
{
|
|
|
|
syncSize(value, JsonNode::JsonType::DATA_STRUCT);
|
|
|
|
|
|
|
|
for(size_t idx = 0; idx < size(); idx++)
|
|
|
|
serializeInt(idx, value[idx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
///vector of strings <-> Json vector of strings
|
|
|
|
void serializeArray(std::vector<std::string> & value)
|
|
|
|
{
|
|
|
|
syncSize(value, JsonNode::JsonType::DATA_STRUCT);
|
|
|
|
|
|
|
|
for(size_t idx = 0; idx < size(); idx++)
|
|
|
|
serializeString(idx, value[idx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
///vector of anything with custom serializing function <-> Json vector of structs
|
2016-11-13 12:38:42 +02:00
|
|
|
template <typename Element>
|
2023-09-17 22:19:45 +02:00
|
|
|
void serializeStruct(std::vector<Element> & value, std::function<void(JsonSerializeFormat&, Element&)> serializer)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2017-11-26 23:18:18 +02:00
|
|
|
syncSize(value, JsonNode::JsonType::DATA_STRUCT);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
for(size_t idx = 0; idx < size(); idx++)
|
|
|
|
{
|
|
|
|
auto s = enterStruct(idx);
|
2023-09-17 22:19:45 +02:00
|
|
|
serializer(*owner, value[idx]);
|
2016-11-13 12:38:42 +02:00
|
|
|
}
|
|
|
|
}
|
2023-09-17 22:19:45 +02:00
|
|
|
|
|
|
|
///vector of serializable <-> Json vector of structs
|
|
|
|
template <typename Element>
|
|
|
|
void serializeStruct(std::vector<Element> & value)
|
|
|
|
{
|
|
|
|
serializeStruct<Element>(value, [](JsonSerializeFormat & h, Element & e){e.serializeJson(h);});
|
|
|
|
}
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
void resize(const size_t newSize);
|
|
|
|
void resize(const size_t newSize, JsonNode::JsonType type);
|
|
|
|
size_t size() const;
|
|
|
|
protected:
|
2017-07-20 06:08:49 +02:00
|
|
|
JsonArraySerializer(JsonSerializeFormat * owner_);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
friend class JsonSerializeFormat;
|
2017-07-20 06:08:49 +02:00
|
|
|
private:
|
|
|
|
const JsonNode * thisNode;
|
|
|
|
|
|
|
|
void serializeInt64(const size_t index, int64_t & value);
|
2016-02-13 09:47:40 +02:00
|
|
|
};
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
class DLL_LINKAGE JsonSerializeFormat: public boost::noncopyable
|
2016-02-13 09:47:40 +02:00
|
|
|
{
|
|
|
|
public:
|
2016-02-14 13:22:46 +02:00
|
|
|
///user-provided callback to resolve string identifier
|
|
|
|
///returns resolved identifier or -1 on error
|
2023-02-11 17:13:21 +02:00
|
|
|
using TDecoder = std::function<si32(const std::string &)>;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
|
|
|
///user-provided callback to get string identifier
|
|
|
|
///may assume that object index is valid
|
2023-02-11 17:13:21 +02:00
|
|
|
using TEncoder = std::function<std::string(si32)>;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2023-02-11 17:13:21 +02:00
|
|
|
using TSerialize = std::function<void(JsonSerializeFormat &)>;
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2016-02-23 15:36:21 +02:00
|
|
|
struct LIC
|
|
|
|
{
|
2023-02-11 17:13:21 +02:00
|
|
|
LIC(const std::vector<bool> & Standard, TDecoder Decoder, TEncoder Encoder);
|
2016-02-23 15:36:21 +02:00
|
|
|
|
|
|
|
const std::vector<bool> & standard;
|
2016-11-13 12:38:42 +02:00
|
|
|
const TDecoder decoder;
|
|
|
|
const TEncoder encoder;
|
2016-02-23 15:36:21 +02:00
|
|
|
std::vector<bool> all, any, none;
|
|
|
|
};
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
struct LICSet
|
|
|
|
{
|
2023-02-11 17:13:21 +02:00
|
|
|
LICSet(const std::set<si32> & Standard, TDecoder Decoder, TEncoder Encoder);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
const std::set<si32> & standard;
|
|
|
|
const TDecoder decoder;
|
|
|
|
const TEncoder encoder;
|
|
|
|
std::set<si32> all, any, none;
|
|
|
|
};
|
|
|
|
|
2016-02-14 13:22:46 +02:00
|
|
|
const bool saving;
|
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
|
|
|
const bool updating;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
|
|
|
JsonSerializeFormat() = delete;
|
2016-02-13 09:47:40 +02:00
|
|
|
virtual ~JsonSerializeFormat() = default;
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
virtual const JsonNode & getCurrent() = 0;
|
2016-02-13 14:22:26 +02:00
|
|
|
|
2016-02-13 09:47:40 +02:00
|
|
|
JsonStructSerializer enterStruct(const std::string & fieldName);
|
2016-11-13 12:38:42 +02:00
|
|
|
JsonArraySerializer enterArray(const std::string & fieldName);
|
2016-02-13 09:47:40 +02:00
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///Anything comparable <-> Json bool
|
2016-02-23 15:36:21 +02:00
|
|
|
template <typename T>
|
2016-11-13 12:38:42 +02:00
|
|
|
void serializeBool(const std::string & fieldName, T & value, const T trueValue, const T falseValue, const T defaultValue)
|
2016-02-23 15:36:21 +02:00
|
|
|
{
|
2016-11-13 12:38:42 +02:00
|
|
|
boost::logic::tribool temp(boost::logic::indeterminate);
|
|
|
|
|
|
|
|
if(value == defaultValue)
|
|
|
|
;//leave as indeterminate
|
|
|
|
else if(value == trueValue)
|
|
|
|
temp = true;
|
|
|
|
else if(value == falseValue)
|
|
|
|
temp = false;
|
|
|
|
|
|
|
|
serializeInternal(fieldName, temp);
|
2016-02-23 15:36:21 +02:00
|
|
|
if(!saving)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
|
|
|
if(boost::logic::indeterminate(temp))
|
|
|
|
value = defaultValue;
|
|
|
|
else
|
|
|
|
value = temp ? trueValue : falseValue;
|
|
|
|
}
|
2016-02-23 15:36:21 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///bool <-> Json bool
|
|
|
|
void serializeBool(const std::string & fieldName, bool & value);
|
2017-07-20 06:08:49 +02:00
|
|
|
void serializeBool(const std::string & fieldName, bool & value, const bool defaultValue);
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///tribool <-> Json bool
|
|
|
|
void serializeBool(const std::string & fieldName, boost::logic::tribool & value)
|
|
|
|
{
|
|
|
|
serializeInternal(fieldName, value);
|
|
|
|
};
|
2016-02-23 15:36:21 +02:00
|
|
|
|
|
|
|
/** @brief Restrictive ("anyOf") simple serialization of Logical identifier condition, simple deserialization (allOf=anyOf)
|
2016-02-14 13:22:46 +02:00
|
|
|
*
|
|
|
|
* @param fieldName
|
|
|
|
* @param decoder resolve callback, should report errors itself and do not throw
|
|
|
|
* @param encoder encode callback, should report errors itself and do not throw
|
|
|
|
* @param value target value, must be resized properly
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
virtual void serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) = 0;
|
|
|
|
|
2016-02-23 15:36:21 +02:00
|
|
|
/** @brief Complete serialization of Logical identifier condition
|
|
|
|
*/
|
|
|
|
virtual void serializeLIC(const std::string & fieldName, LIC & value) = 0;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
/** @brief Complete serialization of Logical identifier condition. (Special version)
|
|
|
|
* Assumes that all values are allowed by default, and standard contains them
|
|
|
|
*/
|
|
|
|
virtual void serializeLIC(const std::string & fieldName, LICSet & value) = 0;
|
|
|
|
|
|
|
|
///String <-> Json string
|
|
|
|
virtual void serializeString(const std::string & fieldName, std::string & value) = 0;
|
|
|
|
|
|
|
|
///si32-convertible enum <-> Json string enum
|
2016-02-14 13:22:46 +02:00
|
|
|
template <typename T>
|
2016-11-13 12:38:42 +02:00
|
|
|
void serializeEnum(const std::string & fieldName, T & value, const std::vector<std::string> & enumMap)
|
2016-02-14 13:22:46 +02:00
|
|
|
{
|
2023-04-16 19:42:56 +02:00
|
|
|
doSerializeInternal<T, T, si32>(fieldName, value, std::nullopt, enumMap);
|
2016-02-14 13:22:46 +02:00
|
|
|
};
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///si32-convertible enum <-> Json string enum
|
|
|
|
template <typename T, typename U>
|
|
|
|
void serializeEnum(const std::string & fieldName, T & value, const U & defaultValue, const std::vector<std::string> & enumMap)
|
|
|
|
{
|
|
|
|
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, enumMap);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename U, typename C>
|
|
|
|
void serializeEnum(const std::string & fieldName, T & value, const U & defaultValue, const C & enumMap)
|
|
|
|
{
|
|
|
|
std::vector<std::string> enumMapCopy;
|
|
|
|
|
|
|
|
std::copy(std::begin(enumMap), std::end(enumMap), std::back_inserter(enumMapCopy));
|
|
|
|
|
|
|
|
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, enumMapCopy);
|
|
|
|
};
|
|
|
|
|
|
|
|
///Anything double-convertible <-> Json double
|
2016-02-14 13:22:46 +02:00
|
|
|
template <typename T>
|
2016-11-13 12:38:42 +02:00
|
|
|
void serializeFloat(const std::string & fieldName, T & value)
|
2016-02-14 13:22:46 +02:00
|
|
|
{
|
2023-04-16 19:42:56 +02:00
|
|
|
doSerializeInternal<T, T, double>(fieldName, value, std::nullopt);
|
2016-02-14 13:22:46 +02:00
|
|
|
};
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///Anything double-convertible <-> Json double
|
|
|
|
template <typename T, typename U>
|
|
|
|
void serializeFloat(const std::string & fieldName, T & value, const U & defaultValue)
|
|
|
|
{
|
|
|
|
doSerializeInternal<T, U, double>(fieldName, value, defaultValue);
|
|
|
|
};
|
|
|
|
|
|
|
|
///Anything int64-convertible <-> Json integer
|
2018-03-09 20:11:20 +02:00
|
|
|
///no default value
|
2016-11-13 12:38:42 +02:00
|
|
|
template <typename T>
|
|
|
|
void serializeInt(const std::string & fieldName, T & value)
|
|
|
|
{
|
2023-04-16 19:42:56 +02:00
|
|
|
doSerializeInternal<T, T, si64>(fieldName, value, std::nullopt);
|
2016-11-13 12:38:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
///Anything int64-convertible <-> Json integer
|
2018-03-09 20:11:20 +02:00
|
|
|
///custom default value
|
2016-11-13 12:38:42 +02:00
|
|
|
template <typename T, typename U>
|
|
|
|
void serializeInt(const std::string & fieldName, T & value, const U & defaultValue)
|
|
|
|
{
|
|
|
|
doSerializeInternal<T, U, si64>(fieldName, value, defaultValue);
|
|
|
|
};
|
|
|
|
|
2018-03-09 20:11:20 +02:00
|
|
|
///Anything int64-convertible <-> Json integer
|
2023-04-16 19:42:56 +02:00
|
|
|
///default value is std::nullopt
|
|
|
|
template<typename T>
|
|
|
|
void serializeInt(const std::string & fieldName, std::optional<T> & value)
|
2018-03-09 20:11:20 +02:00
|
|
|
{
|
|
|
|
dispatchOptional<T, si64>(fieldName, value);
|
|
|
|
};
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///si32-convertible identifier <-> Json string
|
|
|
|
template <typename T, typename U>
|
|
|
|
void serializeId(const std::string & fieldName, T & value, const U & defaultValue, const TDecoder & decoder, const TEncoder & encoder)
|
|
|
|
{
|
|
|
|
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, decoder, encoder);
|
|
|
|
}
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
///si32-convertible identifier <-> Json string
|
2018-03-09 20:11:20 +02:00
|
|
|
template <typename T, typename U, typename E = T>
|
2017-07-20 06:08:49 +02:00
|
|
|
void serializeId(const std::string & fieldName, T & value, const U & defaultValue)
|
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2017-07-20 06:08:49 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///si32-convertible identifier vector <-> Json array of string
|
2018-03-09 20:11:20 +02:00
|
|
|
template <typename T, typename E = T>
|
2017-07-20 06:08:49 +02:00
|
|
|
void serializeIdArray(const std::string & fieldName, std::vector<T> & value)
|
2016-02-22 01:37:19 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
if (saving)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
std::vector<std::string> fieldValue;
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
for(const T & vitem : value)
|
2023-09-04 21:23:20 +02:00
|
|
|
fieldValue.push_back(E::encode(vitem));
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
serializeInternal(fieldName, fieldValue);
|
|
|
|
}
|
|
|
|
else
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
std::vector<std::string> fieldValue;
|
|
|
|
serializeInternal(fieldName, fieldValue);
|
|
|
|
|
|
|
|
value.resize(fieldValue.size());
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
for(size_t i = 0; i < fieldValue.size(); ++i)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), E::entityType(), fieldValue[i], [&value, i](int32_t index){
|
|
|
|
value[i] = T(index);
|
|
|
|
});
|
2016-11-13 12:38:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///si32-convertible identifier set <-> Json array of string
|
2017-07-20 06:08:49 +02:00
|
|
|
template <typename T, typename U = T>
|
|
|
|
void serializeIdArray(const std::string & fieldName, std::set<T> & value)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
if (saving)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
std::vector<std::string> fieldValue;
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
for(const T & vitem : value)
|
2023-09-04 21:23:20 +02:00
|
|
|
fieldValue.push_back(U::encode(vitem));
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
serializeInternal(fieldName, fieldValue);
|
|
|
|
}
|
|
|
|
else
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
std::vector<std::string> fieldValue;
|
|
|
|
serializeInternal(fieldName, fieldValue);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
for(size_t i = 0; i < fieldValue.size(); ++i)
|
2016-11-13 12:38:42 +02:00
|
|
|
{
|
2023-09-04 21:23:20 +02:00
|
|
|
VLC->identifiers()->requestIdentifier(ModScope::scopeGame(), U::entityType(), fieldValue[i], [&value](int32_t index){
|
|
|
|
value.insert(T(index));
|
|
|
|
});
|
2016-11-13 12:38:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///si32-convertible instance identifier <-> Json string
|
|
|
|
template <typename T>
|
|
|
|
void serializeInstance(const std::string & fieldName, T & value, const T & defaultValue)
|
|
|
|
{
|
|
|
|
const TDecoder decoder = std::bind(&IInstanceResolver::decode, instanceResolver, _1);
|
2023-09-04 21:23:20 +02:00
|
|
|
const TEncoder encoder = std::bind(&IInstanceResolver::encode, instanceResolver, _1);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
serializeId<T>(fieldName, value, defaultValue, decoder, encoder);
|
2016-02-22 01:37:19 +02:00
|
|
|
}
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
///any serializable object <-> Json struct
|
|
|
|
template <typename T>
|
|
|
|
void serializeStruct(const std::string & fieldName, T & value)
|
|
|
|
{
|
|
|
|
auto guard = enterStruct(fieldName);
|
|
|
|
value.serializeJson(*this);
|
|
|
|
}
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2023-04-16 19:42:56 +02:00
|
|
|
virtual void serializeRaw(const std::string & fieldName, JsonNode & value, const std::optional<std::reference_wrapper<const JsonNode>> defaultValue) = 0;
|
2017-07-20 06:08:49 +02:00
|
|
|
|
|
|
|
protected:
|
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
|
|
|
JsonSerializeFormat(const IInstanceResolver * instanceResolver_, const bool saving_, const bool updating_);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
///bool <-> Json bool, indeterminate is default
|
|
|
|
virtual void serializeInternal(const std::string & fieldName, boost::logic::tribool & value) = 0;
|
|
|
|
|
|
|
|
///Numeric Id <-> String Id
|
2023-04-16 19:42:56 +02:00
|
|
|
virtual void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const TDecoder & decoder, const TEncoder & encoder) = 0;
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
///Numeric Id vector <-> String Id vector
|
|
|
|
virtual void serializeInternal(const std::string & fieldName, std::vector<si32> & value, const TDecoder & decoder, const TEncoder & encoder) = 0;
|
|
|
|
|
|
|
|
///Numeric <-> Json double
|
2023-04-16 19:42:56 +02:00
|
|
|
virtual void serializeInternal(const std::string & fieldName, double & value, const std::optional<double> & defaultValue) = 0;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///Numeric <-> Json integer
|
2023-04-16 19:42:56 +02:00
|
|
|
virtual void serializeInternal(const std::string & fieldName, si64 & value, const std::optional<si64> & defaultValue) = 0;
|
2016-02-14 13:22:46 +02:00
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
///Enum/Numeric <-> Json string enum
|
2023-04-16 19:42:56 +02:00
|
|
|
virtual void serializeInternal(const std::string & fieldName, si32 & value, const std::optional<si32> & defaultValue, const std::vector<std::string> & enumMap) = 0;
|
2016-02-22 01:37:19 +02:00
|
|
|
|
2023-09-04 21:23:20 +02:00
|
|
|
///String vector <-> Json string vector
|
|
|
|
virtual void serializeInternal(const std::string & fieldName, std::vector<std::string> & value) = 0;
|
|
|
|
|
2017-07-20 06:08:49 +02:00
|
|
|
virtual void pop() = 0;
|
|
|
|
virtual void pushStruct(const std::string & fieldName) = 0;
|
|
|
|
virtual void pushArray(const std::string & fieldName) = 0;
|
|
|
|
virtual void pushArrayElement(const size_t index) = 0;
|
2018-03-09 20:11:20 +02:00
|
|
|
virtual void pushField(const std::string & fieldName) = 0;
|
2017-07-20 06:08:49 +02:00
|
|
|
|
|
|
|
virtual void resizeCurrent(const size_t newSize, JsonNode::JsonType type){};
|
|
|
|
|
|
|
|
virtual void serializeInternal(std::string & value) = 0;
|
|
|
|
virtual void serializeInternal(int64_t & value) = 0;
|
|
|
|
|
2016-02-13 09:47:40 +02:00
|
|
|
private:
|
2016-11-13 12:38:42 +02:00
|
|
|
const IInstanceResolver * instanceResolver;
|
|
|
|
|
2023-04-16 19:42:56 +02:00
|
|
|
template<typename VType, typename DVType, typename IType, typename... Args>
|
|
|
|
void doSerializeInternal(const std::string & fieldName, VType & value, const std::optional<DVType> & defaultValue, Args... args)
|
2018-03-09 20:11:20 +02:00
|
|
|
{
|
2023-04-16 19:42:56 +02:00
|
|
|
const std::optional<IType> tempDefault = defaultValue ? std::optional<IType>(static_cast<IType>(defaultValue.value())) : std::nullopt;
|
2023-04-17 23:11:16 +02:00
|
|
|
auto temp = static_cast<IType>(value);
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
serializeInternal(fieldName, temp, tempDefault, args...);
|
|
|
|
|
|
|
|
if(!saving)
|
|
|
|
value = static_cast<VType>(temp);
|
2018-03-09 20:11:20 +02:00
|
|
|
}
|
|
|
|
|
2023-04-16 19:42:56 +02:00
|
|
|
template<typename VType, typename IType, typename... Args>
|
|
|
|
void dispatchOptional(const std::string & fieldName, std::optional<VType> & value, Args... args)
|
2018-03-09 20:11:20 +02:00
|
|
|
{
|
|
|
|
if(saving)
|
|
|
|
{
|
|
|
|
if(value)
|
|
|
|
{
|
2023-04-17 23:11:16 +02:00
|
|
|
auto temp = static_cast<IType>(value.value());
|
2018-03-09 20:11:20 +02:00
|
|
|
pushField(fieldName);
|
|
|
|
serializeInternal(temp, args...);
|
|
|
|
pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pushField(fieldName);
|
|
|
|
|
|
|
|
if(getCurrent().getType() == JsonNode::JsonType::DATA_NULL)
|
|
|
|
{
|
2023-04-16 19:42:56 +02:00
|
|
|
value = std::nullopt;
|
2018-03-09 20:11:20 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IType temp = IType();
|
|
|
|
serializeInternal(temp, args...);
|
2023-04-16 19:42:56 +02:00
|
|
|
value = std::make_optional(temp);
|
2018-03-09 20:11:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pop();
|
|
|
|
}
|
|
|
|
}
|
2016-11-13 12:38:42 +02:00
|
|
|
|
|
|
|
friend class JsonSerializeHelper;
|
2016-02-13 09:47:40 +02:00
|
|
|
friend class JsonStructSerializer;
|
2016-11-13 12:38:42 +02:00
|
|
|
friend class JsonArraySerializer;
|
2016-02-13 09:47:40 +02:00
|
|
|
};
|
|
|
|
|
2016-11-13 12:38:42 +02:00
|
|
|
template <typename Container>
|
|
|
|
void JsonArraySerializer::syncSize(Container & c, JsonNode::JsonType type)
|
|
|
|
{
|
2017-07-20 06:08:49 +02:00
|
|
|
if(owner->saving)
|
2016-11-13 12:38:42 +02:00
|
|
|
resize(c.size(), type);
|
|
|
|
else
|
|
|
|
c.resize(size());
|
|
|
|
}
|
2017-07-20 06:08:49 +02:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void JsonArraySerializer::serializeInt(const size_t index, T & value)
|
|
|
|
{
|
2023-04-17 23:11:16 +02:00
|
|
|
auto temp = static_cast<int64_t>(value);
|
2017-07-20 06:08:49 +02:00
|
|
|
|
|
|
|
serializeInt64(index, temp);
|
|
|
|
|
2020-10-01 10:38:06 +02:00
|
|
|
if (!owner->saving)
|
2017-07-20 06:08:49 +02:00
|
|
|
value = static_cast<T>(temp);
|
|
|
|
};
|
2022-07-26 15:07:42 +02:00
|
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|