test: extend coverage of testAdvancement
This commit is contained in:
1 parent
1530c4701e
commit
30b64ccfaa
1 file changed
+159
@@ -313,3 +313,162 @@ VF_TEST(aParentLoopIsReportedInsteadOfWalkedForever) {
|
||||
CHECK_EQ(tree.size(), static_cast<std::size_t>(0));
|
||||
}
|
||||
|
||||
VF_TEST(criteriaOnlyAcceptTheEventsTheyDescribe) {
|
||||
AdvancementCriterion anyKill;
|
||||
anyKill.trigger = Trigger::MobKilled;
|
||||
CHECK(anyKill.accepts(Event::mobKilled(Species::Pig)));
|
||||
CHECK(anyKill.accepts(Event::mobKilled(Species::Creeper)));
|
||||
CHECK(!anyKill.accepts(Event::itemObtained(ItemId::Stick)));
|
||||
|
||||
AdvancementCriterion creepersOnly = anyKill;
|
||||
creepersOnly.matchMask = AdvancementCriterion::MatchSpecies;
|
||||
creepersOnly.species = Species::Creeper;
|
||||
CHECK(creepersOnly.accepts(Event::mobKilled(Species::Creeper)));
|
||||
CHECK(!creepersOnly.accepts(Event::mobKilled(Species::Pig)));
|
||||
|
||||
AdvancementCriterion minedWithIron;
|
||||
minedWithIron.trigger = Trigger::BlockBroken;
|
||||
minedWithIron.matchMask = AdvancementCriterion::MatchBlock | AdvancementCriterion::MatchTool;
|
||||
minedWithIron.block = Block::DiamondOre;
|
||||
minedWithIron.tool = ItemId::IronPickaxe;
|
||||
CHECK(minedWithIron.accepts(Event::blockBroken(Block::DiamondOre, ItemId::IronPickaxe)));
|
||||
CHECK(!minedWithIron.accepts(Event::blockBroken(Block::DiamondOre, ItemId::StonePickaxe)));
|
||||
CHECK(!minedWithIron.accepts(Event::blockBroken(Block::CoalOre, ItemId::IronPickaxe)));
|
||||
|
||||
AdvancementCriterion brewed;
|
||||
brewed.trigger = Trigger::PotionBrewed;
|
||||
brewed.matchMask = AdvancementCriterion::MatchPotion;
|
||||
brewed.potion = PotionKind::Swiftness;
|
||||
CHECK(brewed.accepts(Event::potionBrewed(PotionKind::Swiftness)));
|
||||
CHECK(!brewed.accepts(Event::potionBrewed(PotionKind::Healing)));
|
||||
CHECK(!brewed.accepts(Event::dimensionEntered(DimensionId::End)));
|
||||
|
||||
for (int i = 0; i < static_cast<int>(Trigger::Count); ++i) {
|
||||
Trigger trigger = static_cast<Trigger>(i);
|
||||
Trigger reparsed = Trigger::Count;
|
||||
CHECK(parseAdvancementTriggerName(advancementTriggerName(trigger), reparsed));
|
||||
CHECK(reparsed == trigger);
|
||||
}
|
||||
Trigger unknown = Trigger::Count;
|
||||
CHECK(!parseAdvancementTriggerName("telekinesis", unknown));
|
||||
}
|
||||
|
||||
VF_TEST(oneUnreadableAdvancementDoesNotCostTheRest) {
|
||||
DataPack pack = contentPack();
|
||||
pack.addFile("data/voxelforge/advancements/broken.json",
|
||||
R"json({"criteria": {"x": {"trigger": "telekinesis"}}})json");
|
||||
pack.addFile("data/voxelforge/advancements/empty.json", R"json({"criteria": {}})json");
|
||||
pack.addFile("data/voxelforge/advancements/ghost.json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained",
|
||||
"item": "voxelforge:cheese"}}})json");
|
||||
pack.addFile("data/voxelforge/advancements/mismatch.json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained"}},
|
||||
"requirements": [["y"]]})json");
|
||||
|
||||
std::vector<DataPackError> errors;
|
||||
AdvancementTree tree = loadTree(pack, errors);
|
||||
CHECK_EQ(errors.size(), static_cast<std::size_t>(4));
|
||||
CHECK_EQ(tree.size(), static_cast<std::size_t>(4));
|
||||
CHECK(tree.find(id("voxelforge:root")) != nullptr);
|
||||
CHECK(tree.find(id("voxelforge:broken")) == nullptr);
|
||||
for (const DataPackError& failure : errors) {
|
||||
CHECK(failure.file.find("data/voxelforge/advancements/") == 0u);
|
||||
CHECK(!failure.reason.empty());
|
||||
}
|
||||
}
|
||||
|
||||
VF_TEST(advancementDocumentsAreCheckedFieldByField) {
|
||||
Advancement parsed;
|
||||
std::string problem;
|
||||
const char* const rejected[] = {
|
||||
R"json([])json",
|
||||
R"json({})json",
|
||||
R"json({"criteria": {}})json",
|
||||
R"json({"criteria": {"x": {}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained", "count": 0}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained", "item": "NOT AN ID"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "mobKilled", "species": "dragon"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "dimensionEntered", "dimension": "attic"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "potionBrewed", "potion": "coffee"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "villagerTraded", "profession": "banker"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "blockBroken", "block": "voxelforge:cheese"}}})json",
|
||||
R"json({"parent": "BAD ID", "criteria": {"x": {"trigger": "itemObtained"}}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained"}}, "requirements": [[]]})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained"}},
|
||||
"rewards": {"experience": -1}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained"}},
|
||||
"rewards": {"recipes": ["NOT AN ID"]}})json",
|
||||
R"json({"criteria": {"x": {"trigger": "itemObtained"}}, "display": "a string"})json",
|
||||
};
|
||||
for (const char* text : rejected) {
|
||||
JsonParseResult document = parseJson(text);
|
||||
CHECK(document.ok);
|
||||
CHECK(!parseAdvancementJson(document.root, "voxelforge", parsed, problem));
|
||||
CHECK(!problem.empty());
|
||||
}
|
||||
|
||||
JsonParseResult minimal =
|
||||
parseJson(R"json({"criteria": {"x": {"trigger": "itemObtained"}}})json");
|
||||
CHECK(parseAdvancementJson(minimal.root, "voxelforge", parsed, problem));
|
||||
CHECK(parsed.isRoot());
|
||||
CHECK(!parsed.hidden);
|
||||
CHECK_EQ(parsed.criteria.size(), static_cast<std::size_t>(1));
|
||||
CHECK_EQ(parsed.criteria[0].matchMask, 0u);
|
||||
CHECK_EQ(parsed.criteria[0].requiredCount, 1);
|
||||
CHECK(parsed.reward.empty());
|
||||
|
||||
// A bare namespace default applies to every id inside the document.
|
||||
JsonParseResult defaulted = parseJson(
|
||||
R"json({"parent": "root", "criteria": {"x": {"trigger": "itemObtained",
|
||||
"item": "stick"}}, "rewards": {"recipes": ["torch"]}})json");
|
||||
CHECK(parseAdvancementJson(defaulted.root, "extras", parsed, problem));
|
||||
CHECK(parsed.parent == ResourceId("extras", "root"));
|
||||
CHECK(parsed.criteria[0].item == ItemId::Stick);
|
||||
CHECK(parsed.reward.recipes[0] == ResourceId("extras", "torch"));
|
||||
}
|
||||
|
||||
VF_TEST(oneMiningRunFeedsBothTheAdvancementTreeAndTheStatSheet) {
|
||||
DataPackMeta meta;
|
||||
meta.name = "mining";
|
||||
DataPack pack(meta);
|
||||
pack.addFile("data/voxelforge/advancements/quarry.json",
|
||||
R"json({"display": {"title": "Quarry"},
|
||||
"criteria": {"stone": {"trigger": "blockBroken",
|
||||
"block": "voxelforge:stone", "count": 5}},
|
||||
"rewards": {"experience": 15}})json");
|
||||
|
||||
std::vector<DataPackError> errors;
|
||||
AdvancementTree tree = loadTree(pack, errors);
|
||||
CHECK(errors.empty());
|
||||
AdvancementProgress progress(tree);
|
||||
|
||||
Scoreboard board;
|
||||
ScoreObjective mined;
|
||||
mined.name = "mined";
|
||||
mined.criterion = ScoreObjective::Criterion::Statistic;
|
||||
mined.statKind = StatKind::BlocksBroken;
|
||||
mined.statSubject = static_cast<int>(Block::Stone);
|
||||
CHECK(board.addObjective(mined));
|
||||
|
||||
const AdvancementId quarry = id("voxelforge:quarry");
|
||||
for (int strike = 1; strike <= 4; ++strike) {
|
||||
progress.notify(Event::blockBroken(Block::Stone, ItemId::IronPickaxe), strike * 10);
|
||||
board.stats("foksiu").addBlockBroken(Block::Stone);
|
||||
CHECK_EQ(board.score("mined", "foksiu"), strike);
|
||||
CHECK(!progress.granted(quarry));
|
||||
}
|
||||
|
||||
std::vector<AdvancementId> granted =
|
||||
progress.notify(Event::blockBroken(Block::Stone, ItemId::IronPickaxe), 50);
|
||||
board.stats("foksiu").addBlockBroken(Block::Stone);
|
||||
CHECK_EQ(granted.size(), static_cast<std::size_t>(1));
|
||||
CHECK(progress.granted(quarry));
|
||||
CHECK_EQ(progress.totalExperience(), 15);
|
||||
CHECK_EQ(board.score("mined", "foksiu"), 5);
|
||||
CHECK_EQ(board.stats("foksiu").blocksBroken(Block::Stone), 5);
|
||||
|
||||
// Breaking something else moves the sheet but not this advancement.
|
||||
board.stats("foksiu").addBlockBroken(Block::Dirt, 3);
|
||||
CHECK_EQ(board.score("mined", "foksiu"), 5);
|
||||
CHECK_EQ(board.stats("foksiu").total(StatKind::BlocksBroken), 8);
|
||||
}
|
||||
Reference in new issue
Block a user