feat(vf): extend DataPack
This commit is contained in:
1 parent
c87eafd189
commit
4602896f82
1 file changed
+98
@@ -154,3 +154,101 @@ struct BlockTag {
|
|||||||
bool contains(const ResourceId& member) const;
|
bool contains(const ResourceId& member) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Tags by id, with references between them flattened on demand.
|
||||||
|
class TagRegistry {
|
||||||
|
public:
|
||||||
|
// Applies replace/append semantics against what is already registered.
|
||||||
|
void define(const BlockTag& tag);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
bool has(const ResourceId& id) const;
|
||||||
|
const BlockTag* find(const ResourceId& id) const;
|
||||||
|
std::vector<ResourceId> ids() const;
|
||||||
|
std::size_t size() const { return tags.size(); }
|
||||||
|
|
||||||
|
// Flattens nested references into plain members, in declaration order and
|
||||||
|
// without duplicates. False when a reference cycles or names an unknown
|
||||||
|
// tag; `problem` then says which.
|
||||||
|
bool resolve(const ResourceId& id, std::vector<ResourceId>& out) const;
|
||||||
|
bool resolve(const ResourceId& id, std::vector<ResourceId>& out, std::string& problem) const;
|
||||||
|
|
||||||
|
// True when the flattened tag holds `member`.
|
||||||
|
bool contains(const ResourceId& id, const ResourceId& member) const;
|
||||||
|
// True when following references from `id` comes back to a tag already on
|
||||||
|
// the path.
|
||||||
|
bool hasCycle(const ResourceId& id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<ResourceId, BlockTag> tags;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Loads any number of packs into one merged view. Packs are applied in order of
|
||||||
|
// meta().priority, insertion order breaking ties; a later pack overwrites a
|
||||||
|
// resource an earlier one defined, except for tags, which append unless the
|
||||||
|
// later tag sets "replace".
|
||||||
|
class DataPackLoader {
|
||||||
|
public:
|
||||||
|
void addPack(DataPack pack);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Parses every pack.json and every data/**/**.json, then interprets the
|
||||||
|
// known folders. Returns true when nothing was rejected; either way the
|
||||||
|
// resources that did load are available.
|
||||||
|
bool load();
|
||||||
|
|
||||||
|
const std::vector<DataPackError>& errors() const { return problems; }
|
||||||
|
const std::vector<DataPack>& packs() const { return loaded; }
|
||||||
|
// Pack names in the order they were applied.
|
||||||
|
std::vector<std::string> applyOrder() const;
|
||||||
|
|
||||||
|
const std::map<ResourceId, RecipeData>& recipes() const { return recipeSet; }
|
||||||
|
const std::map<ResourceId, LootTable>& lootTables() const { return lootSet; }
|
||||||
|
const TagRegistry& blockTags() const { return blockTagSet; }
|
||||||
|
const TagRegistry& itemTags() const { return itemTagSet; }
|
||||||
|
|
||||||
|
const RecipeData* recipe(const ResourceId& id) const;
|
||||||
|
const LootTable* lootTable(const ResourceId& id) const;
|
||||||
|
|
||||||
|
// Every parsed document that lived under data/<space>/<folder>/, keyed by
|
||||||
|
// resource id. Advancement.h reads its own folder back out of here.
|
||||||
|
const std::map<ResourceId, JsonValue>* documentsIn(const std::string& folder) const;
|
||||||
|
|
||||||
|
// Registers every loaded recipe with an existing registry, on top of the
|
||||||
|
// built in ones. Returns how many were added.
|
||||||
|
int applyTo(CraftingRegistry& registry) const;
|
||||||
|
|
||||||
|
// Rolls a loaded table through the existing loot roller.
|
||||||
|
LootRoll roll(const ResourceId& table, const LootContext& context) const;
|
||||||
|
|
||||||
|
// Flattened tag members resolved against the block and item palettes.
|
||||||
|
// Members that name nothing in the palette are dropped.
|
||||||
|
bool blocksInTag(const ResourceId& tag, std::vector<Block>& out) const;
|
||||||
|
bool itemsInTag(const ResourceId& tag, std::vector<ItemId>& out) const;
|
||||||
|
|
||||||
|
void reportError(const std::string& pack, const std::string& file, const std::string& reason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadPack(DataPack& pack);
|
||||||
|
void ingest(DataPack& pack, const std::string& file, const std::string& folder,
|
||||||
|
const ResourceId& id, const JsonValue& root);
|
||||||
|
|
||||||
|
std::vector<DataPack> loaded;
|
||||||
|
std::vector<DataPackError> problems;
|
||||||
|
std::vector<std::string> order;
|
||||||
|
std::map<std::string, std::map<ResourceId, JsonValue>> folders;
|
||||||
|
std::map<ResourceId, RecipeData> recipeSet;
|
||||||
|
std::map<ResourceId, LootTable> lootSet;
|
||||||
|
TagRegistry blockTagSet;
|
||||||
|
TagRegistry itemTagSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parsers for the individual document kinds, exposed so a caller can read one
|
||||||
|
// document without building a pack around it. `problem` is filled on failure.
|
||||||
|
bool parseRecipeJson(const JsonValue& root, const std::string& defaultSpace, RecipeData& out,
|
||||||
|
std::string& problem);
|
||||||
|
bool parseLootTableJson(const JsonValue& root, const std::string& defaultSpace, LootTable& out,
|
||||||
|
std::string& problem);
|
||||||
|
bool parseTagJson(const JsonValue& root, const std::string& defaultSpace, BlockTag& out,
|
||||||
|
std::string& problem);
|
||||||
|
|
||||||
|
} // namespace vf
|
||||||
Reference in new issue
Block a user