feat: add NamedDimension and parseDimensionName
This commit is contained in:
1 parent
0372ea134a
commit
fa5603f435
1 file changed
+174
@@ -0,0 +1,174 @@
|
|||||||
|
#include "vf/Advancement.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "vf/Command.h"
|
||||||
|
#include "vf/PotionCatalog.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct NamedDimension {
|
||||||
|
const char* name;
|
||||||
|
DimensionId id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Kept in step with DimensionConfig::nameOf, which Dimension.cpp cannot hand
|
||||||
|
// back a parser for without dragging every world generator into the link.
|
||||||
|
const NamedDimension dimensionNames[] = {
|
||||||
|
{"overworld", DimensionId::Overworld},
|
||||||
|
{"nether", DimensionId::Nether},
|
||||||
|
{"end", DimensionId::End},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool parseDimensionName(const std::string& text, DimensionId& out) {
|
||||||
|
for (const NamedDimension& entry : dimensionNames) {
|
||||||
|
if (text == entry.name) {
|
||||||
|
out = entry.id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parsePotionName(const std::string& text, PotionKind& out) {
|
||||||
|
const PotionCatalog& catalog = potionCatalog();
|
||||||
|
for (const PotionEntry& entry : catalog.entries()) {
|
||||||
|
if (text == entry.name) {
|
||||||
|
out = entry.kind;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseProfessionName(const std::string& text, VillagerProfession& out) {
|
||||||
|
for (int i = 0; i < static_cast<int>(VillagerProfession::Count); ++i) {
|
||||||
|
VillagerProfession profession = static_cast<VillagerProfession>(i);
|
||||||
|
if (text == villagerProfessionName(profession)) {
|
||||||
|
out = profession;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readOptionalResource(const JsonValue& owner, const std::string& key,
|
||||||
|
const std::string& defaultSpace, ResourceId& out, bool& present,
|
||||||
|
std::string& problem) {
|
||||||
|
const JsonValue* field = owner.find(key);
|
||||||
|
present = false;
|
||||||
|
if (field == nullptr) return true;
|
||||||
|
if (!field->isString()) {
|
||||||
|
problem = "\"" + key + "\" must be a string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ResourceId::parse(field->stringValue(), defaultSpace, out)) {
|
||||||
|
problem = "\"" + key + "\" is not a valid resource id: " + field->stringValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
present = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readResourceList(const JsonValue& owner, const std::string& key,
|
||||||
|
const std::string& defaultSpace, std::vector<ResourceId>& out,
|
||||||
|
std::string& problem) {
|
||||||
|
const JsonValue* list = owner.find(key);
|
||||||
|
if (list == nullptr) return true;
|
||||||
|
if (!list->isArray()) {
|
||||||
|
problem = "\"" + key + "\" must be an array of resource ids";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const JsonValue& element : list->elements()) {
|
||||||
|
ResourceId id;
|
||||||
|
if (!element.isString() || !ResourceId::parse(element.stringValue(), defaultSpace, id)) {
|
||||||
|
problem = "\"" + key + "\" holds something that is not a resource id";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.push_back(id);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseCriterionJson(const std::string& criterionName, const JsonValue& root,
|
||||||
|
const std::string& defaultSpace, AdvancementCriterion& out,
|
||||||
|
std::string& problem) {
|
||||||
|
if (!root.isObject()) {
|
||||||
|
problem = "criterion \"" + criterionName + "\" must be an object";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const JsonValue* trigger = root.find("trigger");
|
||||||
|
if (trigger == nullptr || !trigger->isString() ||
|
||||||
|
!parseAdvancementTriggerName(trigger->stringValue(), out.trigger)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\" needs a known \"trigger\"";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.name = criterionName;
|
||||||
|
out.requiredCount = static_cast<int>(root.intOr("count", 1));
|
||||||
|
if (out.requiredCount < 1) {
|
||||||
|
problem = "criterion \"" + criterionName + "\" needs a count of at least 1";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceId id;
|
||||||
|
bool present = false;
|
||||||
|
if (!readOptionalResource(root, "item", defaultSpace, id, present, problem)) return false;
|
||||||
|
if (present) {
|
||||||
|
if (!resolveItemId(id, out.item)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": no such item " + id.text();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchItem;
|
||||||
|
}
|
||||||
|
if (!readOptionalResource(root, "block", defaultSpace, id, present, problem)) return false;
|
||||||
|
if (present) {
|
||||||
|
if (!resolveBlockId(id, out.block)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": no such block " + id.text();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchBlock;
|
||||||
|
}
|
||||||
|
if (!readOptionalResource(root, "tool", defaultSpace, id, present, problem)) return false;
|
||||||
|
if (present) {
|
||||||
|
if (!resolveItemId(id, out.tool)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": no such tool " + id.text();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchTool;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const JsonValue* species = root.find("species")) {
|
||||||
|
if (!species->isString() || !parseSpeciesName(species->stringValue(), out.species)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": unknown species";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchSpecies;
|
||||||
|
}
|
||||||
|
if (const JsonValue* dimension = root.find("dimension")) {
|
||||||
|
if (!dimension->isString() ||
|
||||||
|
!parseDimensionName(dimension->stringValue(), out.dimension)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": unknown dimension";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchDimension;
|
||||||
|
}
|
||||||
|
if (const JsonValue* potion = root.find("potion")) {
|
||||||
|
if (!potion->isString() || !parsePotionName(potion->stringValue(), out.potion)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": unknown potion";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchPotion;
|
||||||
|
}
|
||||||
|
if (const JsonValue* profession = root.find("profession")) {
|
||||||
|
if (!profession->isString() ||
|
||||||
|
!parseProfessionName(profession->stringValue(), out.profession)) {
|
||||||
|
problem = "criterion \"" + criterionName + "\": unknown villager profession";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.matchMask |= AdvancementCriterion::MatchProfession;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user