feat: add resolveItemId and resolveBlockId to DataPack
This commit is contained in:
1 parent
570172c86d
commit
4423e6c2b3
1 file changed
+159
@@ -157,3 +157,162 @@ bool readCountRange(const JsonValue& owner, const std::string& key, int& minOut,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
ResourceId::ResourceId(std::string space, std::string path)
|
||||||
|
: space(std::move(space)), path(std::move(path)) {}
|
||||||
|
|
||||||
|
bool ResourceId::validSpace(const std::string& text) {
|
||||||
|
if (text.empty()) return false;
|
||||||
|
for (char c : text) {
|
||||||
|
bool ok = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' ||
|
||||||
|
c == '.';
|
||||||
|
if (!ok) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceId::validPath(const std::string& text) {
|
||||||
|
if (text.empty()) return false;
|
||||||
|
if (text.front() == '/' || text.back() == '/') return false;
|
||||||
|
for (char c : text) {
|
||||||
|
bool ok = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' ||
|
||||||
|
c == '.' || c == '/';
|
||||||
|
if (!ok) return false;
|
||||||
|
}
|
||||||
|
return text.find("//") == std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceId::parse(const std::string& text, const std::string& defaultSpace, ResourceId& out) {
|
||||||
|
std::size_t colon = text.find(':');
|
||||||
|
if (colon == std::string::npos) {
|
||||||
|
out = ResourceId(defaultSpace, text);
|
||||||
|
} else {
|
||||||
|
if (text.find(':', colon + 1u) != std::string::npos) return false;
|
||||||
|
out = ResourceId(text.substr(0, colon), text.substr(colon + 1u));
|
||||||
|
}
|
||||||
|
return out.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool resolveItemId(const ResourceId& id, ItemId& out) {
|
||||||
|
if (!id.valid()) return false;
|
||||||
|
return parseItemName(loweredWithoutSeparators(id.path), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool resolveBlockId(const ResourceId& id, Block& out) {
|
||||||
|
if (!id.valid()) return false;
|
||||||
|
return parseBlockName(loweredWithoutSeparators(id.path), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataPackMeta::fromJson(const JsonValue& root, DataPackMeta& out, std::string& problem) {
|
||||||
|
if (!root.isObject()) {
|
||||||
|
problem = "pack metadata must be an object";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const JsonValue* name = root.find("name");
|
||||||
|
if (name == nullptr || !name->isString() || name->stringValue().empty()) {
|
||||||
|
problem = "\"name\" must be a non empty string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DataPackMeta parsed;
|
||||||
|
parsed.name = name->stringValue();
|
||||||
|
parsed.description = root.stringOr("description", "");
|
||||||
|
parsed.formatVersion = static_cast<int>(root.intOr("formatVersion", 1));
|
||||||
|
parsed.priority = static_cast<int>(root.intOr("priority", 0));
|
||||||
|
parsed.defaultSpace = root.stringOr("defaultSpace", "voxelforge");
|
||||||
|
if (parsed.formatVersion < 1) {
|
||||||
|
problem = "\"formatVersion\" must be at least 1";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ResourceId::validSpace(parsed.defaultSpace)) {
|
||||||
|
problem = "\"defaultSpace\" is not a valid namespace: " + parsed.defaultSpace;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out = parsed;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DataPackError::text() const {
|
||||||
|
std::string out = pack.empty() ? file : pack + "/" + file;
|
||||||
|
if (line > 0) out += ":" + std::to_string(line) + ":" + std::to_string(column);
|
||||||
|
return out + ": " + reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataPack::addFile(const std::string& path, std::string contents) {
|
||||||
|
files[path] = std::move(contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataPack::removeFile(const std::string& path) { return files.erase(path) > 0u; }
|
||||||
|
|
||||||
|
bool DataPack::hasFile(const std::string& path) const { return files.count(path) > 0u; }
|
||||||
|
|
||||||
|
const std::string* DataPack::fileContents(const std::string& path) const {
|
||||||
|
auto found = files.find(path);
|
||||||
|
return found == files.end() ? nullptr : &found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> DataPack::filesUnder(const std::string& prefix) const {
|
||||||
|
std::vector<std::string> out;
|
||||||
|
for (const auto& entry : files)
|
||||||
|
if (entry.first.compare(0, prefix.size(), prefix) == 0) out.push_back(entry.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> DataPack::allFiles() const {
|
||||||
|
std::vector<std::string> out;
|
||||||
|
out.reserve(files.size());
|
||||||
|
for (const auto& entry : files) out.push_back(entry.first);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapedRecipe RecipeData::toShaped() const {
|
||||||
|
ShapedRecipe out;
|
||||||
|
out.width = width;
|
||||||
|
out.height = height;
|
||||||
|
out.pattern = pattern;
|
||||||
|
out.allowMirror = allowMirror;
|
||||||
|
out.result.item = resultItem;
|
||||||
|
out.result.count = resultCount;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShapelessRecipe RecipeData::toShapeless() const {
|
||||||
|
ShapelessRecipe out;
|
||||||
|
out.ingredients = ingredients;
|
||||||
|
out.result.item = resultItem;
|
||||||
|
out.result.count = resultCount;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmeltingRecipe RecipeData::toSmelting() const {
|
||||||
|
SmeltingRecipe out;
|
||||||
|
out.input = smeltInput;
|
||||||
|
out.smeltSeconds = smeltSeconds;
|
||||||
|
out.result.item = resultItem;
|
||||||
|
out.result.count = resultCount;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlockTag::contains(const ResourceId& member) const {
|
||||||
|
for (const Entry& entry : entries)
|
||||||
|
if (!entry.reference && entry.id == member) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TagRegistry::define(const BlockTag& tag) {
|
||||||
|
auto found = tags.find(tag.id);
|
||||||
|
if (found == tags.end() || tag.replace) {
|
||||||
|
tags[tag.id] = tag;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BlockTag& existing = found->second;
|
||||||
|
for (const BlockTag::Entry& entry : tag.entries) {
|
||||||
|
bool already = false;
|
||||||
|
for (const BlockTag::Entry& present : existing.entries)
|
||||||
|
if (present == entry) already = true;
|
||||||
|
if (!already) existing.entries.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TagRegistry::clear() { tags.clear(); }
|
||||||
|
|
||||||
|
bool TagRegistry::has(const ResourceId& id) const { return tags.count(id) > 0u; }
|
||||||
|
|
||||||
Reference in new issue
Block a user