feat: extend Advancement
This commit is contained in:
1 parent
fa5603f435
commit
8248b4b51e
1 file changed
+156
@@ -172,3 +172,159 @@ bool parseCriterionJson(const std::string& criterionName, const JsonValue& root,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::itemObtained(ItemId item, int amount) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::ItemObtained;
|
||||||
|
event.item = item;
|
||||||
|
event.amount = amount;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::mobKilled(Species species) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::MobKilled;
|
||||||
|
event.species = species;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::dimensionEntered(DimensionId dimension) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::DimensionEntered;
|
||||||
|
event.dimension = dimension;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::potionBrewed(PotionKind potion) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::PotionBrewed;
|
||||||
|
event.potion = potion;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::villagerTraded(
|
||||||
|
VillagerProfession profession, ItemId purchased) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::VillagerTraded;
|
||||||
|
event.profession = profession;
|
||||||
|
event.item = purchased;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancementCriterion::Event AdvancementCriterion::Event::blockBroken(Block block, ItemId tool) {
|
||||||
|
Event event;
|
||||||
|
event.trigger = Trigger::BlockBroken;
|
||||||
|
event.block = block;
|
||||||
|
event.tool = tool;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdvancementCriterion::accepts(const Event& event) const {
|
||||||
|
if (event.trigger != trigger) return false;
|
||||||
|
if ((matchMask & MatchItem) != 0u && event.item != item) return false;
|
||||||
|
if ((matchMask & MatchBlock) != 0u && event.block != block) return false;
|
||||||
|
if ((matchMask & MatchSpecies) != 0u && event.species != species) return false;
|
||||||
|
if ((matchMask & MatchDimension) != 0u && event.dimension != dimension) return false;
|
||||||
|
if ((matchMask & MatchPotion) != 0u && event.potion != potion) return false;
|
||||||
|
if ((matchMask & MatchProfession) != 0u && event.profession != profession) return false;
|
||||||
|
if ((matchMask & MatchTool) != 0u && event.tool != tool) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AdvancementCriterion* Advancement::findCriterion(const std::string& criterionName) const {
|
||||||
|
for (const AdvancementCriterion& criterion : criteria)
|
||||||
|
if (criterion.name == criterionName) return &criterion;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Advancement::satisfiedBy(const std::vector<std::string>& completed) const {
|
||||||
|
if (criteria.empty()) return false;
|
||||||
|
auto isComplete = [&completed](const std::string& name) {
|
||||||
|
return std::find(completed.begin(), completed.end(), name) != completed.end();
|
||||||
|
};
|
||||||
|
if (requirements.empty()) {
|
||||||
|
for (const AdvancementCriterion& criterion : criteria)
|
||||||
|
if (!isComplete(criterion.name)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const std::vector<std::string>& group : requirements) {
|
||||||
|
bool any = false;
|
||||||
|
for (const std::string& name : group)
|
||||||
|
if (isComplete(name)) any = true;
|
||||||
|
if (!any) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Advancement::danglingRequirements() const {
|
||||||
|
std::vector<std::string> out;
|
||||||
|
for (const std::vector<std::string>& group : requirements)
|
||||||
|
for (const std::string& name : group)
|
||||||
|
if (findCriterion(name) == nullptr) out.push_back(name);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdvancementTree::add(const Advancement& advancement) {
|
||||||
|
if (!advancement.id.valid()) return false;
|
||||||
|
if (nodes.count(advancement.id) > 0u) return false;
|
||||||
|
nodes[advancement.id] = advancement;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvancementTree::clear() { nodes.clear(); }
|
||||||
|
|
||||||
|
const Advancement* AdvancementTree::find(const AdvancementId& id) const {
|
||||||
|
auto found = nodes.find(id);
|
||||||
|
return found == nodes.end() ? nullptr : &found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AdvancementId> AdvancementTree::ids() const {
|
||||||
|
std::vector<AdvancementId> out;
|
||||||
|
out.reserve(nodes.size());
|
||||||
|
for (const auto& node : nodes) out.push_back(node.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AdvancementId> AdvancementTree::roots() const {
|
||||||
|
std::vector<AdvancementId> out;
|
||||||
|
for (const auto& node : nodes)
|
||||||
|
if (node.second.isRoot()) out.push_back(node.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AdvancementId> AdvancementTree::childrenOf(const AdvancementId& id) const {
|
||||||
|
std::vector<AdvancementId> out;
|
||||||
|
for (const auto& node : nodes)
|
||||||
|
if (!node.second.isRoot() && node.second.parent == id) out.push_back(node.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AdvancementTree::depthOf(const AdvancementId& id) const {
|
||||||
|
const Advancement* node = find(id);
|
||||||
|
if (node == nullptr) return -1;
|
||||||
|
int depth = 0;
|
||||||
|
AdvancementId walk = id;
|
||||||
|
for (std::size_t step = 0u; step <= nodes.size(); ++step) {
|
||||||
|
const Advancement* here = find(walk);
|
||||||
|
if (here == nullptr) return -1;
|
||||||
|
if (here->isRoot()) return depth;
|
||||||
|
walk = here->parent;
|
||||||
|
++depth;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdvancementTree::cycleFrom(const AdvancementId& id) const {
|
||||||
|
std::vector<AdvancementId> seen;
|
||||||
|
AdvancementId walk = id;
|
||||||
|
for (;;) {
|
||||||
|
for (const AdvancementId& visited : seen)
|
||||||
|
if (visited == walk) return true;
|
||||||
|
seen.push_back(walk);
|
||||||
|
const Advancement* here = find(walk);
|
||||||
|
if (here == nullptr || here->isRoot()) return false;
|
||||||
|
walk = here->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user