diff --git a/res/scripts/post_content.lua b/res/scripts/post_content.lua index 1b69f42f..b512882d 100644 --- a/res/scripts/post_content.lua +++ b/res/scripts/post_content.lua @@ -14,28 +14,20 @@ for name, _ in pairs(user_props) do end -- remove undefined properties and build tags set -local function process_properties(properties) - for id, props in pairs(properties) do - local tags_set = nil - for propname, value in pairs(props) do - if propname == "tags" then - if #value > 0 then - tags_set = tags_set or {} - end - for _, tag in ipairs(value) do - tags_set[tag] = true - end - end +local function process_properties(lib) + for id, props in pairs(lib.properties) do + for propname, _ in pairs(props) do if not table.has(names, propname) then props[propname] = nil end end - props.tags_set = tags_set + + props.tags_set = lib.__get_tags(id) end end -process_properties(block.properties) -process_properties(item.properties) +process_properties(block) +process_properties(item) local function make_read_only(t) setmetatable(t, { @@ -68,7 +60,11 @@ local function cache_names(library) end function library.has_tag(id, tag) - local tags_set = library.properties[id].tags_set + if id == nil then + error("id is nil") + end + local props = library.properties[id] + local tags_set = props.tags_set if tags_set then return tags_set[tag] else diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 1527d98b..ea29e27c 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -413,6 +413,25 @@ void ContentLoader::load() { if (io::exists(contentFile)) { loadContent(io::read_json(contentFile)); } + + // Load attached tags + io::path tagsFile = folder / "tags.toml"; + if (io::exists(tagsFile)) { + auto tagsMap = io::read_object(tagsFile); + for (const auto& [key, list] : tagsMap.asObject()) { + for (const auto& id : list) { + const auto& stringId = id.asString(); + if (auto block = builder.blocks.get(stringId)) { + block->tags.push_back(key); + if (auto item = builder.items.get(stringId + BLOCK_ITEM_SUFFIX)) { + item->tags.push_back(key); + } + } else if (auto item = builder.items.get(stringId)) { + item->tags.push_back(key); + } + } + } + } } template diff --git a/src/logic/scripting/lua/libs/libblock.cpp b/src/logic/scripting/lua/libs/libblock.cpp index 29f7747c..e72bf96f 100644 --- a/src/logic/scripting/lua/libs/libblock.cpp +++ b/src/logic/scripting/lua/libs/libblock.cpp @@ -20,21 +20,21 @@ using namespace scripting; -static inline const Block* require_block(lua::State* L) { +static inline const Block* get_block_def(lua::State* L) { auto indices = content->getIndices(); auto id = lua::tointeger(L, 1); return indices->blocks.get(id); } static inline int l_get_def(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushstring(L, def->name); } return 0; } static int l_material(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushstring(L, def->material); } return 0; @@ -59,14 +59,14 @@ static int l_index(lua::State* L) { } static int l_is_extended(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushboolean(L, def->rt.extended); } return 0; } static int l_get_size(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushivec_stack(L, glm::ivec3(def->size)); } return 0; @@ -343,14 +343,14 @@ static int l_is_replaceable_at(lua::State* L) { } static int l_caption(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushstring(L, def->caption); } return 0; } static int l_get_textures(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { lua::createtable(L, 6, 0); for (size_t i = 0; i < 6; i++) { lua::pushstring(L, def->defaults.textureFaces[i]); // TODO: variant argument @@ -363,7 +363,7 @@ static int l_get_textures(lua::State* L) { static int l_model_name(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { // TODO: variant argument const auto& modelName = def->defaults.model.name; if (modelName.empty()) { @@ -375,7 +375,7 @@ static int l_model_name(lua::State* L) { } static int l_get_model(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { // TODO: variant argument return lua::pushlstring(L, BlockModelTypeMeta.getName(def->defaults.model.type)); } @@ -383,7 +383,7 @@ static int l_get_model(lua::State* L) { } static int l_get_hitbox(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { size_t rotation = lua::tointeger(L, 2); if (def->rotatable) { rotation %= def->rotations.MAX_COUNT; @@ -404,14 +404,14 @@ static int l_get_hitbox(lua::State* L) { } static int l_get_rotation_profile(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushstring(L, def->rotations.name); } return 0; } static int l_get_picking_item(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { return lua::pushinteger(L, def->rt.pickingItem); } return 0; @@ -699,7 +699,7 @@ static int l_reload_script(lua::State* L) { } static int l_has_tag(lua::State* L) { - if (auto def = require_block(L)) { + if (auto def = get_block_def(L)) { auto tag = lua::require_string(L, 2); const auto& tags = def->rt.tags; return lua::pushboolean(L, tags.find(content->getTagIndex(tag)) != tags.end()); @@ -707,6 +707,21 @@ static int l_has_tag(lua::State* L) { return 0; } +static int l_get_tags(lua::State* L) { + if (auto def = get_block_def(L)) { + if (def->tags.empty()) { + return 0; + } + lua::createtable(L, 0, def->tags.size()); + for (const auto& tag : def->tags) { + lua::pushboolean(L, true); + lua::setfield(L, tag); + } + return 1; + } + return 0; +} + static int l_pull_register_events(lua::State* L) { auto events = blocks_agent::pull_register_events(); if (events.empty()) @@ -766,6 +781,7 @@ const luaL_Reg blocklib[] = { {"set_field", lua::wrap}, {"reload_script", lua::wrap}, {"has_tag", lua::wrap}, + {"__get_tags", lua::wrap}, {"__pull_register_events", lua::wrap}, {NULL, NULL} }; diff --git a/src/logic/scripting/lua/libs/libitem.cpp b/src/logic/scripting/lua/libs/libitem.cpp index b26e524c..79c03c2a 100644 --- a/src/logic/scripting/lua/libs/libitem.cpp +++ b/src/logic/scripting/lua/libs/libitem.cpp @@ -117,6 +117,21 @@ static int l_has_tag(lua::State* L) { return 0; } +static int l_get_tags(lua::State* L) { + if (auto def = get_item_def(L, 1)) { + if (def->tags.empty()) { + return 0; + } + lua::createtable(L, 0, def->tags.size()); + for (const auto& tag : def->tags) { + lua::pushboolean(L, true); + lua::setfield(L, tag); + } + return 1; + } + return 0; +} + const luaL_Reg itemlib[] = { {"index", lua::wrap}, {"name", lua::wrap}, @@ -131,5 +146,6 @@ const luaL_Reg itemlib[] = { {"uses", lua::wrap}, {"reload_script", lua::wrap}, {"has_tag", lua::wrap}, + {"__get_tags", lua::wrap}, {NULL, NULL} };