瀏覽代碼

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
Konstantin 2 年之前
父節點
當前提交
0540e1531d
共有 2 個文件被更改,包括 115 次插入0 次删除
  1. 113 0
      lib/JsonNode.cpp
  2. 2 0
      lib/JsonNode.h

+ 113 - 0
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)

+ 2 - 0
lib/JsonNode.h

@@ -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);