Merge pull request #602 from MihailRis/item-properties-methods

Item properties methods
This commit is contained in:
MihailRis 2025-08-31 13:30:30 +03:00 committed by GitHub
commit cda5bfaf40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 162 additions and 32 deletions

View File

@ -68,6 +68,9 @@ block.get_variant(x: int, y: int, z: int) -> int
-- Sets the block variant by index
block.set_variant(x: int, y: int, z: int, index: int) -> int
-- Checks if an block has specified tag
block.has_tag(id: int, tag: str) -> bool
```
## Rotation

View File

@ -33,4 +33,7 @@ item.emission(itemid: int) -> str
-- Returns the value of the `uses` property
item.uses(itemid: int) -> int
-- Checks if an item has specified tag
item.has_tag(itemid: int, tag: str) -> bool
```

View File

@ -67,6 +67,9 @@ block.get_variant(x: int, y: int, z: int) -> int
-- Устанавливает вариант блока по индексу
block.set_variant(x: int, y: int, z: int, index: int) -> int
-- Проверяет наличие тега у блока
block.has_tag(id: int, tag: str) -> bool
```
### Raycast

View File

@ -33,6 +33,9 @@ item.emission(itemid: int) -> str
-- Возвращает значение свойства `uses`
item.uses(itemid: int) -> int
-- Проверяет наличие тега у предмета
item.has_tag(itemid: int, tag: str) -> bool
```

View File

@ -1,4 +1,5 @@
{
"texture": "coal_ore",
"tags": ["base:ore"],
"base:durability": 16.0
}

View File

@ -7,5 +7,6 @@
"obstacle": false,
"selectable": false,
"replaceable": true,
"translucent": true
"translucent": true,
"tags": ["base:liquid"]
}

View File

@ -12,22 +12,31 @@ local names = {
for name, _ in pairs(user_props) do
table.insert(names, name)
end
-- remove undefined properties
for id, blockprops in pairs(block.properties) do
for propname, value in pairs(blockprops) do
if not table.has(names, propname) then
blockprops[propname] = nil
end
end
end
for id, itemprops in pairs(item.properties) do
for propname, value in pairs(itemprops) do
if not table.has(names, propname) then
itemprops[propname] = nil
-- 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
if not table.has(names, propname) then
props[propname] = nil
end
end
props.tags_set = tags_set
end
end
process_properties(block.properties)
process_properties(item.properties)
local function make_read_only(t)
setmetatable(t, {
__newindex = function()
@ -57,6 +66,15 @@ local function cache_names(library)
function library.index(name)
return indices[name]
end
function library.has_tag(id, tag)
local tags_set = library.properties[id].tags_set
if tags_set then
return tags_set[tag]
else
return false
end
end
end
cache_names(block)

View File

@ -35,13 +35,15 @@ Content::Content(
UptrsMap<std::string, BlockMaterial> blockMaterials,
UptrsMap<std::string, rigging::SkeletonConfig> skeletons,
ResourceIndicesSet resourceIndices,
dv::value defaults
dv::value defaults,
std::unordered_map<std::string, int> tags
)
: indices(std::move(indices)),
packs(std::move(packs)),
blockMaterials(std::move(blockMaterials)),
skeletons(std::move(skeletons)),
defaults(std::move(defaults)),
tags(std::move(tags)),
blocks(std::move(blocks)),
items(std::move(items)),
entities(std::move(entities)),

View File

@ -176,6 +176,7 @@ class Content {
UptrsMap<std::string, BlockMaterial> blockMaterials;
UptrsMap<std::string, rigging::SkeletonConfig> skeletons;
dv::value defaults = nullptr;
std::unordered_map<std::string, int> tags;
public:
ContentUnitDefs<Block> blocks;
ContentUnitDefs<ItemDef> items;
@ -195,7 +196,8 @@ public:
UptrsMap<std::string, BlockMaterial> blockMaterials,
UptrsMap<std::string, rigging::SkeletonConfig> skeletons,
ResourceIndicesSet resourceIndices,
dv::value defaults
dv::value defaults,
std::unordered_map<std::string, int> tags
);
~Content();
@ -211,6 +213,14 @@ public:
return defaults;
}
int getTagIndex(const std::string& tag) const {
const auto& found = tags.find(tag);
if (found == tags.end()) {
return -1;
}
return found->second;
}
const rigging::SkeletonConfig* getSkeleton(const std::string& id) const;
const rigging::SkeletonConfig& requireSkeleton(const std::string& id) const;
const BlockMaterial* findBlockMaterial(const std::string& id) const;

View File

@ -28,6 +28,9 @@ std::unique_ptr<Content> ContentBuilder::build() {
// Generating runtime info
def.rt.id = blockDefsIndices.size();
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
for (const auto& tag : def.tags) {
def.rt.tags.insert(tags.add(tag));
}
if (def.variants) {
for (auto& variant : def.variants->variants) {
@ -58,7 +61,7 @@ std::unique_ptr<Content> ContentBuilder::build() {
}
blockDefsIndices.push_back(&def);
groups->insert(def.defaults.drawGroup); // FIXME
groups->insert(def.defaults.drawGroup); // FIXME: variants
}
std::vector<ItemDef*> itemDefsIndices;
@ -93,7 +96,8 @@ std::unique_ptr<Content> ContentBuilder::build() {
std::move(blockMaterials),
std::move(skeletons),
std::move(resourceIndices),
std::move(defaults)
std::move(defaults),
std::move(tags.map)
);
// Now, it's time to resolve foreign keys

View File

@ -62,6 +62,27 @@ public:
}
};
struct TagsIndices {
int nextIndex = 1;
std::unordered_map<std::string, int> map;
int add(const std::string& tag) {
const auto& found = map.find(tag);
if (found != map.end()) {
return found->second;
}
return map[tag] = nextIndex++;
}
int indexOf(const std::string& tag) {
const auto& found = map.find(tag);
if (found == map.end()) {
return -1;
}
return found->second;
}
};
class ContentBuilder {
UptrsMap<std::string, BlockMaterial> blockMaterials;
UptrsMap<std::string, rigging::SkeletonConfig> skeletons;
@ -74,6 +95,7 @@ public:
ContentUnitBuilder<GeneratorDef> generators {allNames, ContentType::GENERATOR};
ResourceIndicesSet resourceIndices {};
dv::value defaults = nullptr;
TagsIndices tags {};
~ContentBuilder();

View File

@ -1,5 +1,6 @@
#define VC_ENABLE_REFLECTION
#include "ContentUnitLoader.hpp"
#include "ContentLoadingCommons.hpp"
#include "../ContentBuilder.hpp"
#include "coders/json.hpp"
@ -87,20 +88,8 @@ template<> void ContentUnitLoader<Block>::loadUnit(
Block& def, const std::string& name, const io::path& file
) {
auto root = io::read_json(file);
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);
}
process_properties(def, name, root);
process_tags(def, root);
if (root.has("parent")) {
const auto& parentName = root["parent"].asString();

View File

@ -0,0 +1,37 @@
#pragma once
#include "data/dv.hpp"
#include <string>
template <typename T>
inline void process_properties(T& def, const std::string& name, const dv::value& 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);
}
}
template <typename T>
inline void process_tags(T& def, const dv::value& root) {
if (!root.has("tags")) {
return;
}
const auto& tags = root["tags"];
for (const auto& tagValue : tags) {
if (!tagValue.isString()) {
continue;
}
def.tags.push_back(tagValue.asString());
}
}

View File

@ -1,5 +1,6 @@
#define VC_ENABLE_REFLECTION
#include "ContentUnitLoader.hpp"
#include "ContentLoadingCommons.hpp"
#include "../ContentBuilder.hpp"
#include "coders/json.hpp"
@ -12,11 +13,13 @@
static debug::Logger logger("item-content-loader");
template<> void ContentUnitLoader<ItemDef>::loadUnit(
ItemDef& def, const std::string& name, const io::path& file
) {
auto root = io::read_json(file);
def.properties = root;
process_properties(def, name, root);
process_tags(def, root);
if (root.has("parent")) {
const auto& parentName = root["parent"].asString();

View File

@ -2,6 +2,8 @@
#include <glm/glm.hpp>
#include <string>
#include <vector>
#include <set>
#include "data/dv.hpp"
#include "typedefs.hpp"
@ -64,11 +66,15 @@ struct ItemDef {
std::string scriptFile;
std::vector<std::string> tags;
struct {
itemid_t id;
blockid_t placingBlock;
ItemFuncsSet funcsset {};
bool emissive = false;
std::set<int> tags;
} rt {};
ItemDef(const std::string& name);

View File

@ -698,6 +698,15 @@ static int l_reload_script(lua::State* L) {
return 0;
}
static int l_has_tag(lua::State* L) {
if (auto def = require_block(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());
}
return 0;
}
const luaL_Reg blocklib[] = {
{"index", lua::wrap<l_index>},
{"name", lua::wrap<l_get_def>},
@ -737,5 +746,6 @@ const luaL_Reg blocklib[] = {
{"get_field", lua::wrap<l_get_field>},
{"set_field", lua::wrap<l_set_field>},
{"reload_script", lua::wrap<l_reload_script>},
{"has_tag", lua::wrap<l_has_tag>},
{NULL, NULL}
};

View File

@ -108,6 +108,15 @@ static int l_reload_script(lua::State* L) {
return 0;
}
static int l_has_tag(lua::State* L) {
if (auto def = get_item_def(L, 1)) {
auto tag = lua::require_string(L, 2);
const auto& tags = def->rt.tags;
return lua::pushboolean(L, tags.find(content->getTagIndex(tag)) != tags.end());
}
return 0;
}
const luaL_Reg itemlib[] = {
{"index", lua::wrap<l_index>},
{"name", lua::wrap<l_name>},
@ -121,5 +130,6 @@ const luaL_Reg itemlib[] = {
{"emission", lua::wrap<l_emission>},
{"uses", lua::wrap<l_uses>},
{"reload_script", lua::wrap<l_reload_script>},
{"has_tag", lua::wrap<l_has_tag>},
{NULL, NULL}
};

View File

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <array>
#include <set>
#include "data/dv.hpp"
#include "maths/UVRegion.hpp"
@ -261,6 +262,8 @@ public:
std::unique_ptr<Variants> variants;
std::vector<std::string> tags;
/// @brief Runtime indices (content indexing results)
struct {
/// @brief block runtime integer id
@ -285,6 +288,8 @@ public:
itemid_t pickingItem = 0;
blockid_t surfaceReplacement = 0;
std::set<int> tags;
} rt {};
Block(const std::string& name);