diff --git a/doc/en/block-properties.md b/doc/en/block-properties.md index 87df173b..8011e9cc 100644 --- a/doc/en/block-properties.md +++ b/doc/en/block-properties.md @@ -213,3 +213,11 @@ User properties must be declared in `pack:config/user-props.toml` file: ``` Example: [user properties of pack **base**](../../res/content/base/config/user-props.toml). + +## Methods + +Methods are used to manage the overwriting of properties when extending a block with other packs. + +### `property_name@append` + +Adds elements to the end of the list instead of completely overwriting it. diff --git a/doc/ru/block-properties.md b/doc/ru/block-properties.md index 2f958e88..71d7cea3 100644 --- a/doc/ru/block-properties.md +++ b/doc/ru/block-properties.md @@ -224,3 +224,11 @@ ``` Пример: [пользовательские свойства пака **base**](../../res/content/base/config/user-props.toml). + +## Методы + +Методы используются для управлением перезаписью свойств при расширении блока другими паками. + +### `имя_свойства@append` + +Добавляет элементы в конец списка, вместо его полной перезаписи. diff --git a/src/content/ContentBuilder.cpp b/src/content/ContentBuilder.cpp index 63308578..49433dfd 100644 --- a/src/content/ContentBuilder.cpp +++ b/src/content/ContentBuilder.cpp @@ -93,8 +93,8 @@ std::unique_ptr ContentBuilder::build() { def->rt.surfaceReplacement = content->blocks.require(def->surfaceReplacement).rt.id; if (def->properties == nullptr) { def->properties = dv::object(); + def->properties["name"] = def->name; } - def->properties["name"] = def->name; } for (ItemDef* def : itemDefsIndices) { diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 1dc676ea..1b650f1d 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -187,11 +187,49 @@ static void perform_user_block_fields( layout = StructLayout::create(fields); } +static void process_method( + dv::value& properties, + const std::string& method, + const std::string& name, + const dv::value& value +) { + if (method == "append") { + if (!properties.has(name)) { + properties[name] = dv::list(); + } + auto& list = properties[name]; + if (value.isList()) { + for (const auto& item : value) { + list.add(item); + } + } else { + list.add(value); + } + } else { + throw std::runtime_error( + "unknown method " + method + " for " + name + ); + } +} + void ContentLoader::loadBlock( Block& def, const std::string& name, const fs::path& file ) { auto root = files::read_json(file); - def.properties = root; + if (def.properties == nullptr) { + def.properties = dv::object(); + def.properties["name"] = name; + } + for (auto& [key, value] : root.asObject()) { + auto pos = key.rfind('@'); + if (pos == std::string::npos) { + def.properties[key] = value; + continue; + } + auto field = key.substr(0, pos); + auto suffix = key.substr(pos + 1); + process_method(def.properties, suffix, field, value); + } if (root.has("parent")) { const auto& parentName = root["parent"].asString();