From 8a19c903e44b7569a38e470ec7b260a03cd4d673 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Mar 2026 20:15:39 +0300 Subject: [PATCH 1/7] fix audio.input.request_open --- res/modules/internal/audio_input.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/res/modules/internal/audio_input.lua b/res/modules/internal/audio_input.lua index 99c80dae6..5a6da06a7 100644 --- a/res/modules/internal/audio_input.lua +++ b/res/modules/internal/audio_input.lua @@ -54,7 +54,10 @@ function audio.input.request_open(callback) _gui_confirm(gui.str(GRANT_PERMISSION_MSG):gsub("%%{0}", caller), function() audio_input_tokens_store[token] = caller callback(token) - menu:reset() + if not menu:back() then + menu:reset() + gui.set_active_frame("") + end end) end From 91a1fc12108c2f845b7294739728942081ce4b31 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 28 Mar 2026 22:47:07 +0300 Subject: [PATCH 2/7] update doc/ru/entity-properties.md --- doc/ru/entity-properties.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/entity-properties.md b/doc/ru/entity-properties.md index c66f0141f..de10cfd32 100644 --- a/doc/ru/entity-properties.md +++ b/doc/ru/entity-properties.md @@ -104,7 +104,7 @@ Определяет массу сущности. За стандарт приняты килограммы. В случае `kinematic` тела вместо указанной используется бесконечная масса. -### Эластичность - *elasticity* +### Упругость - *elasticity* Определяет упругость сущности. From a9d185256ae14789c17b005b27f7be94895f7dca Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 3 Apr 2026 19:29:07 +0300 Subject: [PATCH 3/7] fix: block/item.properties not inheriting parent content unit properties --- res/scripts/post_content.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/res/scripts/post_content.lua b/res/scripts/post_content.lua index b6ca05598..92eff79ce 100644 --- a/res/scripts/post_content.lua +++ b/res/scripts/post_content.lua @@ -16,6 +16,13 @@ end -- remove undefined properties and build tags set local function process_properties(lib) for id, props in pairs(lib.properties) do + if props.parent then + for propname, value in pairs(lib.properties[block.index(props.parent)]) do + if not props[propname] then + props[propname] = value + end + end + end for propname, _ in pairs(props) do if not table.has(names, propname) then props[propname] = nil From 33db2633a282a9ba532143e223e3ae8b4d12fc22 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 3 Apr 2026 19:49:19 +0300 Subject: [PATCH 4/7] fix: player name 3d text not updating by Decorator --- src/graphics/render/Decorator.cpp | 11 +++++------ src/logic/scripting/lua/libs/libplayer.cpp | 6 +++--- src/objects/Player.cpp | 14 +++++++++----- src/objects/Player.hpp | 8 ++++---- src/objects/Players.cpp | 4 ++-- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index 80291194e..59840770a 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -66,9 +66,7 @@ Decorator::Decorator( continue; } playerTexts[id] = renderer.texts->add(std::make_unique( - util::str2wstr_utf8(player->getName()), - playerNamePreset, - player->getPosition() + player->getName(), playerNamePreset, player->getPosition() )); } } @@ -296,9 +294,7 @@ void Decorator::updateTextNotes() { continue; } playerTexts[id] = renderer.texts->add(std::make_unique( - util::str2wstr_utf8(player->getName()), - playerNamePreset, - player->getPosition() + player->getName(), playerNamePreset, player->getPosition() )); } @@ -315,6 +311,9 @@ void Decorator::updateTextNotes() { position = entity->getInterpolatedPosition(); } note->setPosition(position + glm::vec3(0, 1, 0)); + if (note->getText() != player->getName()) { + note->setText(player->getName()); + } ++textsIter; } } diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index a978e5c22..e143d368a 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -294,14 +294,14 @@ static int l_set_camera(lua::State* L) { static int l_get_name(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushstring(L, player->getName()); + return lua::pushwstring(L, player->getName()); } return 0; } static int l_set_name(lua::State* L) { if (auto player = get_player(L, 1)) { - player->setName(lua::require_string(L, 2)); + player->setName(lua::require_wstring(L, 2)); } return 0; } @@ -313,7 +313,7 @@ static int l_create(lua::State* L) { } auto& level = require_level(); auto player = level.players->create(playerId); - player->setName(lua::require_string(L, 1)); + player->setName(lua::require_wstring(L, 1)); return lua::pushinteger(L, player->getId()); } diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index d51ae0d4c..fec65d7de 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -20,6 +20,7 @@ #include "world/generator/GeneratorDef.hpp" #include "data/dv_util.hpp" #include "debug/Logger.hpp" +#include "util/stringutil.hpp" static debug::Logger logger("player"); @@ -28,7 +29,7 @@ constexpr int SPAWN_ATTEMPTS_PER_UPDATE = 64; Player::Player( Level& level, int64_t id, - const std::string& name, + const std::wstring& name, glm::vec3 position, float speed, std::shared_ptr inv, @@ -230,11 +231,11 @@ entityid_t Player::getSelectedEntity() const { return selectedEid; } -void Player::setName(const std::string& name) { +void Player::setName(const std::wstring& name) { this->name = name; } -const std::string& Player::getName() const { +const std::wstring& Player::getName() const { return name; } @@ -266,7 +267,7 @@ dv::value Player::serialize() const { auto root = dv::object(); root["id"] = id; - root["name"] = name; + root["name"] = util::wstr2str_utf8(name); root["position"] = dv::to_value(position); root["rotation"] = dv::to_value(rotation); @@ -293,7 +294,10 @@ dv::value Player::serialize() const { void Player::deserialize(const dv::value& src) { src.at("id").get(id); - src.at("name").get(name); + + std::string utf8name; + src.at("name").get(utf8name); + name = util::str2wstr_utf8(utf8name); const auto& posarr = src["position"]; diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 6fbd4a899..a095ccfb7 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -45,7 +45,7 @@ struct CursorSelection { class Player : public Serializable { Level& level; int64_t id; - std::string name; + std::wstring name; float speed; int chosenSlot; @@ -79,7 +79,7 @@ public: Player( Level& level, int64_t id, - const std::string& name, + const std::wstring& name, glm::vec3 position, float speed, std::shared_ptr inv, @@ -124,8 +124,8 @@ public: entityid_t getSelectedEntity() const; - void setName(const std::string& name); - const std::string& getName() const; + void setName(const std::wstring& name); + const std::wstring& getName() const; const std::shared_ptr& getInventory() const; diff --git a/src/objects/Players.cpp b/src/objects/Players.cpp index c925c9390..c100e3d67 100644 --- a/src/objects/Players.cpp +++ b/src/objects/Players.cpp @@ -79,7 +79,7 @@ Player* Players::create(int64_t id) { auto playerPtr = std::make_unique( level, id, - "", + L"", glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), @@ -134,7 +134,7 @@ void Players::deserialize(const dv::value& src) { auto playerPtr = std::make_unique( level, 0, - "", + L"", glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), From 9893c09fd5459eda2f013b7603fd32db18e02b98 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 5 Apr 2026 10:31:44 +0300 Subject: [PATCH 5/7] fix: destroyed skeleton config access on skeleton reload --- src/graphics/render/NamedSkeletons.cpp | 4 ++-- src/graphics/render/NamedSkeletons.hpp | 3 ++- src/graphics/render/WorldRenderer.cpp | 4 +++- src/logic/scripting/lua/libs/libentity.cpp | 4 ++-- src/objects/Entities.cpp | 4 ++-- src/objects/Entity.cpp | 10 ++-------- src/objects/Entity.hpp | 2 +- src/objects/rigging.cpp | 16 +++++++++++++++- src/objects/rigging.hpp | 10 ++++++---- 9 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/graphics/render/NamedSkeletons.cpp b/src/graphics/render/NamedSkeletons.cpp index 35dd57ec7..c30278a9c 100644 --- a/src/graphics/render/NamedSkeletons.cpp +++ b/src/graphics/render/NamedSkeletons.cpp @@ -7,9 +7,9 @@ using namespace rigging; NamedSkeletons::NamedSkeletons() = default; std::shared_ptr NamedSkeletons::createSkeleton( - const std::string& name, const SkeletonConfig* config + const std::string& name, std::shared_ptr config ) { - auto skeleton = std::make_shared(config); + auto skeleton = std::make_shared(std::move(config)); skeletons[name] = skeleton; return skeleton; } diff --git a/src/graphics/render/NamedSkeletons.hpp b/src/graphics/render/NamedSkeletons.hpp index 4e4fb77a1..4982443b6 100644 --- a/src/graphics/render/NamedSkeletons.hpp +++ b/src/graphics/render/NamedSkeletons.hpp @@ -14,7 +14,8 @@ public: NamedSkeletons(); std::shared_ptr createSkeleton( - const std::string& name, const rigging::SkeletonConfig* config + const std::string& name, + std::shared_ptr config ); rigging::Skeleton* getSkeleton(const std::string& name); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e1f683b96..9f173eb38 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -113,7 +113,9 @@ WorldRenderer::WorldRenderer( content.getDefaults()["hand-skeleton"].asString() ); hands = std::make_unique( - assets, *modelBatch, skeletons->createSkeleton("hand", &skeletonConfig) + assets, + *modelBatch, + skeletons->createSkeleton("hand", skeletonConfig.shared_from_this()) ); shadowMapping = std::make_unique(level); debugLines = std::make_unique(level); diff --git a/src/logic/scripting/lua/libs/libentity.cpp b/src/logic/scripting/lua/libs/libentity.cpp index 0ae21f3c7..d2c0c4bc5 100644 --- a/src/logic/scripting/lua/libs/libentity.cpp +++ b/src/logic/scripting/lua/libs/libentity.cpp @@ -108,13 +108,13 @@ static int l_set_skeleton(lua::State* L) { } if (auto entity = get_entity(L, 1)) { std::string skeletonName = lua::require_string(L, 2); - auto rigConfig = assets->get(skeletonName); + auto rigConfig = assets->getShared(skeletonName); if (rigConfig == nullptr) { throw std::runtime_error( "skeleton not found '" + skeletonName + "'" ); } - entity->setRig(rigConfig); + entity->setRig(std::move(rigConfig)); } return 0; } diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index dbdaa1881..c98349f3c 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -155,7 +155,7 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { std::string skeletonName = skeleton->config->getName(); map.at("skeleton-name").get(skeletonName); if (skeletonName != skeleton->config->getName()) { - skeleton->config = assets->get(skeletonName); + skeleton->config = assets->getShared(skeletonName); } if (auto foundSkeleton = map.at(COMP_SKELETON)) { skeleton->deserialize(*foundSkeleton); @@ -470,7 +470,7 @@ void Entities::render( continue; } - const auto* rigConfig = skeleton.config; + const auto& rigConfig = skeleton.config; if (rigConfig) { rigConfig->render( assets, batch, skeleton, transform.rot, pos, size diff --git a/src/objects/Entity.cpp b/src/objects/Entity.cpp index e8c276dd2..0bf898351 100644 --- a/src/objects/Entity.cpp +++ b/src/objects/Entity.cpp @@ -37,15 +37,9 @@ rigging::Skeleton* Entity::getSkeleton() const { return registry.try_get(entity); } -void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { +void Entity::setRig(std::shared_ptr rigConfig) { auto& skeleton = registry.get(entity); - skeleton.config = rigConfig; - skeleton.pose.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); - skeleton.calculated.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); + skeleton.setConfig(std::move(rigConfig)); } dv::value Entity::serialize() const { diff --git a/src/objects/Entity.hpp b/src/objects/Entity.hpp index ef00a1bf2..960bdfc9a 100644 --- a/src/objects/Entity.hpp +++ b/src/objects/Entity.hpp @@ -60,7 +60,7 @@ public: rigging::Skeleton* getSkeleton() const; - void setRig(const rigging::SkeletonConfig* rigConfig); + void setRig(std::shared_ptr rigConfig); entityid_t getUID() const; diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index d1a41bef7..f686bfbcf 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -39,7 +39,7 @@ void Bone::setModel(const std::string& name) { model = {name, nullptr, true}; } -Skeleton::Skeleton(const SkeletonConfig* config) +Skeleton::Skeleton(std::shared_ptr config) : config(config), pose(config->getBones().size()), calculated(config->getBones().size()), @@ -86,6 +86,16 @@ void Skeleton::deserialize(const dv::value& root) { } } +void Skeleton::setConfig(std::shared_ptr rigConfig) { + config = std::move(rigConfig); + pose.matrices.resize( + config->getBones().size(), glm::mat4(1.0f) + ); + calculated.matrices.resize( + config->getBones().size(), glm::mat4(1.0f) + ); +} + static void get_all_nodes(std::vector& nodes, Bone* node) { nodes[node->getIndex()] = node; for (auto& subnode : node->getBones()) { @@ -97,6 +107,7 @@ SkeletonConfig::SkeletonConfig( const std::string& name, std::unique_ptr root, size_t nodesCount ) : name(name), root(std::move(root)), nodes(nodesCount) { + assert(this->root.get() != nullptr); get_all_nodes(nodes, this->root.get()); } @@ -159,6 +170,9 @@ void SkeletonConfig::render( const glm::vec3& position, const glm::vec3& scale ) const { + if (skeleton.config->root == nullptr) { + return; + } update(skeleton, rotation, position, scale); if (!skeleton.visible) { diff --git a/src/objects/rigging.hpp b/src/objects/rigging.hpp index 7726d0b95..9e7fc75f6 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -78,7 +78,7 @@ namespace rigging { }; struct Skeleton { - const SkeletonConfig* config; + std::shared_ptr config; Pose pose; Pose calculated; std::vector flags; @@ -89,13 +89,15 @@ namespace rigging { util::VecInterpolation<3, float> interpolation {false}; - Skeleton(const SkeletonConfig* config); + Skeleton(std::shared_ptr config); dv::value serialize(bool saveTextures, bool savePose) const; void deserialize(const dv::value& root); + + void setConfig(std::shared_ptr config); }; - class SkeletonConfig { + class SkeletonConfig : public std::enable_shared_from_this { std::string name; std::unique_ptr root; std::unordered_map indices; @@ -135,7 +137,7 @@ namespace rigging { ) const; Skeleton instance() const { - return Skeleton(this); + return Skeleton(shared_from_this()); } const Bone* find(std::string_view str) const; From bb44b4186bd617281614c5f04329bd4221b08c0d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 5 Apr 2026 10:55:30 +0300 Subject: [PATCH 6/7] fix entity bounding box check on block place --- src/objects/Entities.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index c98349f3c..7d2db5b84 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -482,7 +482,9 @@ void Entities::render( bool Entities::hasBlockingInside(AABB aabb) { auto view = registry->view(); for (auto [entity, eid, body] : view.each()) { - if (eid.def.blocking && aabb.intersects(body.hitbox.getAABB(), -0.05f)) { + AABB bodyAABB(body.hitbox.getAABB()); + bodyAABB.scale({1, 0.95f, 1}); + if (eid.def.blocking && aabb.intersects(bodyAABB)) { return true; } } From 6896fa433ca2a5f6bfd5205072edfaded7107a42 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 5 Apr 2026 11:05:20 +0300 Subject: [PATCH 7/7] fix: cursor is not hidden in wayland if previously changed by glfwSetCursor --- src/window/detail/GLFWWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/window/detail/GLFWWindow.cpp b/src/window/detail/GLFWWindow.cpp index 2433cc27f..db3d67241 100644 --- a/src/window/detail/GLFWWindow.cpp +++ b/src/window/detail/GLFWWindow.cpp @@ -294,6 +294,7 @@ public: glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } else { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetCursor(window, nullptr); } cursorLocked = !cursorLocked; }