mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
vcmi: allows parsing selectors from JSON
Supports anyOf, allOf, noneOf, and all selectors from Selector namespace. Can be useful to define selectors in JSON when required
This commit is contained in:
parent
f13a934c47
commit
0540e1531d
113
lib/JsonNode.cpp
113
lib/JsonNode.cpp
@ -969,6 +969,119 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
CSelector JsonUtils::parseSelector(const JsonNode & ability)
|
||||
{
|
||||
CSelector ret = Selector::all;
|
||||
|
||||
// Recursive parsers for anyOf, allOf, noneOf
|
||||
const auto * value = &ability["allOf"];
|
||||
if(value->isVector())
|
||||
{
|
||||
for(const auto & andN : value->Vector())
|
||||
ret = ret.And(parseSelector(andN));
|
||||
}
|
||||
|
||||
value = &ability["anyOf"];
|
||||
if(value->isVector())
|
||||
{
|
||||
CSelector base = Selector::none;
|
||||
for(const auto & andN : value->Vector())
|
||||
base.Or(parseSelector(andN));
|
||||
|
||||
ret = ret.And(base);
|
||||
}
|
||||
|
||||
value = &ability["noneOf"];
|
||||
if(value->isVector())
|
||||
{
|
||||
CSelector base = Selector::all;
|
||||
for(const auto & andN : value->Vector())
|
||||
base.And(parseSelector(andN));
|
||||
|
||||
ret = ret.And(base.Not());
|
||||
}
|
||||
|
||||
// Actual selector parser
|
||||
value = &ability["type"];
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusNameMap.find(value->String());
|
||||
if(it != bonusNameMap.end())
|
||||
ret = ret.And(Selector::type()(it->second));
|
||||
}
|
||||
value = &ability["subtype"];
|
||||
if(!value->isNull())
|
||||
{
|
||||
TBonusSubtype subtype;
|
||||
resolveIdentifier(subtype, ability, "subtype");
|
||||
ret = ret.And(Selector::subtype()(subtype));
|
||||
}
|
||||
value = &ability["sourceType"];
|
||||
Bonus::BonusSource src = Bonus::OTHER; //Fixes for GCC false maybe-uninitialized
|
||||
si32 id = 0;
|
||||
auto sourceIDRelevant = false;
|
||||
auto sourceTypeRelevant = false;
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusSourceMap.find(value->String());
|
||||
if(it != bonusSourceMap.end())
|
||||
{
|
||||
src = it->second;
|
||||
sourceTypeRelevant = true;
|
||||
}
|
||||
|
||||
}
|
||||
value = &ability["sourceID"];
|
||||
if(!value->isNull())
|
||||
{
|
||||
sourceIDRelevant = true;
|
||||
resolveIdentifier(id, ability, "sourceID");
|
||||
}
|
||||
|
||||
if(sourceIDRelevant && sourceTypeRelevant)
|
||||
ret = ret.And(Selector::source(src, id));
|
||||
else if(sourceTypeRelevant)
|
||||
ret = ret.And(Selector::sourceTypeSel(src));
|
||||
|
||||
|
||||
value = &ability["targetSourceType"];
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusSourceMap.find(value->String());
|
||||
if(it != bonusSourceMap.end())
|
||||
ret = ret.And(Selector::targetSourceType()(it->second));
|
||||
}
|
||||
value = &ability["valueType"];
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusValueMap.find(value->String());
|
||||
if(it != bonusValueMap.end())
|
||||
ret = ret.And(Selector::valueType(it->second));
|
||||
}
|
||||
CAddInfo info;
|
||||
value = &ability["addInfo"];
|
||||
if(!value->isNull())
|
||||
{
|
||||
resolveAddInfo(info, ability["addInfo"]);
|
||||
ret = ret.And(Selector::info()(info));
|
||||
}
|
||||
value = &ability["effectRange"];
|
||||
if(value->isString())
|
||||
{
|
||||
auto it = bonusLimitEffect.find(value->String());
|
||||
if(it != bonusLimitEffect.end())
|
||||
ret = ret.And(Selector::effectRange()(it->second));
|
||||
}
|
||||
value = &ability["lastsTurns"];
|
||||
if(value->isNumber())
|
||||
ret = ret.And(Selector::turns(value->Integer()));
|
||||
value = &ability["lastsDays"];
|
||||
if(value->isNumber())
|
||||
ret = ret.And(Selector::days(value->Integer()));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//returns first Key with value equal to given one
|
||||
template<class Key, class Val>
|
||||
Key reverseMapFirst(const Val & val, const std::map<Key, Val> & map)
|
||||
|
@ -17,6 +17,7 @@ typedef std::map <std::string, JsonNode> JsonMap;
|
||||
typedef std::vector <JsonNode> JsonVector;
|
||||
|
||||
struct Bonus;
|
||||
class CSelector;
|
||||
class ResourceID;
|
||||
class CAddInfo;
|
||||
class ILimiter;
|
||||
@ -175,6 +176,7 @@ namespace JsonUtils
|
||||
DLL_LINKAGE std::shared_ptr<Bonus> parseBuildingBonus(const JsonNode &ability, BuildingID building, std::string description);
|
||||
DLL_LINKAGE bool parseBonus(const JsonNode &ability, Bonus *placement);
|
||||
DLL_LINKAGE std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter);
|
||||
DLL_LINKAGE CSelector parseSelector(const JsonNode &ability);
|
||||
DLL_LINKAGE void resolveIdentifier(si32 &var, const JsonNode &node, std::string name);
|
||||
DLL_LINKAGE void resolveIdentifier(const JsonNode &node, si32 &var);
|
||||
DLL_LINKAGE void resolveAddInfo(CAddInfo & var, const JsonNode & node);
|
||||
|
Loading…
Reference in New Issue
Block a user