From 2cec6c3f9a046157e66378437a2096b4486e07e6 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Sat, 28 Feb 2026 20:41:40 +0300 Subject: [PATCH 01/10] added on_inventory_interact --- src/content/ContentPack.hpp | 1 + src/graphics/ui/elements/InventoryView.cpp | 9 +++++++++ src/logic/scripting/scripting.cpp | 18 ++++++++++++++++++ src/logic/scripting/scripting.hpp | 1 + 4 files changed, 29 insertions(+) diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index a4548d038..676bdffa3 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -127,6 +127,7 @@ struct WorldFuncsSet { bool onchunkremove; bool oninventoryopen; bool oninventoryclosed; + bool oninventoryinteract; }; class ContentPackRuntime { diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index 49c8bd3b9..f366a64a8 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -431,14 +431,23 @@ void SlotView::clicked(Mousecode button) { ItemStack& grabbed = exchangeSlot->getStack(); ItemStack& stack = *bound; + int action = -1; + if (button == Mousecode::BUTTON_1) { performLeftClick(stack, grabbed); + action = 0; } else if (button == Mousecode::BUTTON_2) { performRightClick(stack, grabbed); + action = 1; } + if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } + + const auto& input = gui.getInput(); + action = action | (input.pressed(Keycode::LEFT_SHIFT) ? 2 : 0); + scripting::on_inventory_interact(inventoryId, layout.index, action); } void SlotView::onFocus() { diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index e3c23ee1e..713018503 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -540,6 +540,22 @@ void scripting::on_inventory_closed(const Player* player, const Inventory& inven } } +void scripting::on_inventory_interact(int invid, int slot, int action) { + auto args = [invid, slot, action](lua::State* L) { + lua::pushinteger(L, invid); + lua::pushinteger(L, slot); + lua::pushinteger(L, action); + return 3; + }; + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.oninventoryinteract) { + lua::emit_event( + lua::get_main_state(), packid + ":.inventoryinteract", args + ); + } + } +} + void scripting::on_player_tick(Player* player, int tps) { auto args = [=](lua::State* L) { lua::pushinteger(L, player ? player->getId() : -1); @@ -761,6 +777,8 @@ void scripting::load_world_script( register_event(env, "on_inventory_open", prefix + ":.inventoryopen"); funcsset.oninventoryclosed = register_event(env, "on_inventory_closed", prefix + ":.inventoryclosed"); + funcsset.oninventoryinteract = + register_event(env, "on_inventory_interact", prefix + ":.inventoryinteract"); } void scripting::load_layout_script( diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index e1553216d..c54a5fcf1 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -108,6 +108,7 @@ namespace scripting { void on_inventory_open(const Player* player, const Inventory& inventory); void on_inventory_closed(const Player* player, const Inventory& inventory); + void on_inventory_interact(int invid, int slot, int action); void on_player_tick(Player* player, int tps); From cb1b113181b0a31114a8e069d104b4cdace8611f Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:23:47 +0300 Subject: [PATCH 02/10] added hud.get_second_inventory --- doc/ru/scripting/builtins/libhud.md | 3 +++ src/frontend/hud.cpp | 10 ++++++++++ src/frontend/hud.hpp | 2 ++ src/logic/scripting/lua/libs/libhud.cpp | 10 ++++++++++ 4 files changed, 25 insertions(+) diff --git a/doc/ru/scripting/builtins/libhud.md b/doc/ru/scripting/builtins/libhud.md index 1e904cc56..5c1696ef7 100644 --- a/doc/ru/scripting/builtins/libhud.md +++ b/doc/ru/scripting/builtins/libhud.md @@ -55,6 +55,9 @@ hud.close(layoutid: string) -- Дает ID инвентаря открытого блока или 0. hud.get_block_inventory() -> int +-- Дает ID второго открытого инвентаря (блок, виртуальный инвентарь...) или 0. +hud.get_second_inventory() -> int + -- Дает ID игрока, к которому привязан пользовательский интерфейс. hud.get_player() -> int diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 6f3593610..c5c1352cb 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -725,6 +725,16 @@ std::shared_ptr Hud::getBlockInventory() { return blockUI->getInventory(); } +std::shared_ptr Hud::getSecondInventory() { + if (blockUI) { + return blockUI->getInventory(); + } + if (secondInvView) { + return secondInvView->getInventory(); + } + return nullptr; +} + bool Hud::isContentAccess() const { return showContentPanel; } diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index 4e3e4f3dc..dc0a35666 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -203,6 +203,8 @@ public: std::shared_ptr getBlockInventory(); + std::shared_ptr getSecondInventory(); + bool isContentAccess() const; void setContentAccess(bool flag); diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index 7ab5d33c0..a65acb170 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -140,6 +140,15 @@ static int l_get_block_inventory(lua::State* L) { } } +static int l_get_second_inventory(lua::State* L) { + auto inventory = hud->getSecondInventory(); + if (inventory == nullptr) { + return lua::pushinteger(L, 0); + } else { + return lua::pushinteger(L, inventory->getId()); + } +} + static int l_get_player(lua::State* L) { auto player = hud->getPlayer(); return lua::pushinteger(L, player->getId()); @@ -202,6 +211,7 @@ const luaL_Reg hudlib[] = { {"open_permanent", wrap_hud}, {"show_overlay", wrap_hud}, {"get_block_inventory", wrap_hud}, + {"get_second_inventory", wrap_hud}, {"close", wrap_hud}, {"pause", wrap_hud}, {"resume", wrap_hud}, From 9ad21460a2dfa1a169dc83fc44ff574de812f3f0 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:34:52 +0300 Subject: [PATCH 03/10] added hud.is_player_inventory_open --- doc/ru/scripting/builtins/libhud.md | 3 +++ src/frontend/hud.cpp | 4 ++++ src/frontend/hud.hpp | 2 ++ src/logic/scripting/lua/libs/libhud.cpp | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/doc/ru/scripting/builtins/libhud.md b/doc/ru/scripting/builtins/libhud.md index 5c1696ef7..bad0e93c6 100644 --- a/doc/ru/scripting/builtins/libhud.md +++ b/doc/ru/scripting/builtins/libhud.md @@ -73,6 +73,9 @@ hud.is_paused() -> boolean -- Возвращает true если открыт инвентарь или оверлей. hud.is_inventory_open() -> boolean +-- Возвращает true если открыт инвентарь игрока. +hud.is_player_inventory_open() -> boolean + -- Устанавливает разрешение на паузу. При значении false меню паузы не приостанавливает игру. hud.set_allow_pause(flag: boolean) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index c5c1352cb..fee9ff192 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -688,6 +688,10 @@ bool Hud::isInventoryOpen() const { return inventoryOpen; } +bool Hud::isPlayerInventoryOpen() const { + return inventoryView != nullptr; +} + bool Hud::isPause() const { return pause; } diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index dc0a35666..f80c36369 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -147,6 +147,8 @@ public: /// @brief Check if inventory mode on bool isInventoryOpen() const; + bool isPlayerInventoryOpen() const; + /// @brief Check if pause mode on bool isPause() const; diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index a65acb170..7f5c893c5 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -162,6 +162,10 @@ static int l_is_inventory_open(lua::State* L) { return lua::pushboolean(L, hud->isInventoryOpen()); } +static int l_is_player_inventory_open(lua::State* L) { + return lua::pushboolean(L, hud->isPlayerInventoryOpen()); +} + static int l_is_content_access(lua::State* L) { return lua::pushboolean(L, hud->isContentAccess()); } @@ -217,6 +221,7 @@ const luaL_Reg hudlib[] = { {"resume", wrap_hud}, {"is_paused", wrap_hud}, {"is_inventory_open", wrap_hud}, + {"is_player_inventory_open", wrap_hud}, {"get_player", wrap_hud}, {"_is_content_access", wrap_hud}, {"_set_content_access", wrap_hud}, From 09a1985cfb0cc07a1d3501da8169c1d739660b6d Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:48:23 +0300 Subject: [PATCH 04/10] Update events.md --- doc/ru/scripting/events.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 72ff37244..08609939f 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -189,6 +189,13 @@ function on_inventory_closed(invid: int, playerid: int) Вызывается при закрытии инвентаря. +```lua +function on_inventory_interact(invid: int, slot: int, action: int) +``` + +Вызывается при взаимодействии со слотом игрока. +action отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) + ## События макета From ec29c2a68d609af0a6661a00446dc5ea880f5539 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:52:31 +0300 Subject: [PATCH 05/10] Update events.md --- doc/ru/scripting/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 08609939f..598a10d44 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -194,7 +194,7 @@ function on_inventory_interact(invid: int, slot: int, action: int) ``` Вызывается при взаимодействии со слотом игрока. -action отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) +**action** отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) ## События макета From 3d301f13d7bbb1413af33ba43b2fd096853f0321 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Fri, 6 Mar 2026 23:58:51 +0300 Subject: [PATCH 06/10] moved interact from world to hud --- src/content/ContentPack.hpp | 1 - src/logic/scripting/scripting.cpp | 18 ------------------ src/logic/scripting/scripting_hud.cpp | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index 676bdffa3..a4548d038 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -127,7 +127,6 @@ struct WorldFuncsSet { bool onchunkremove; bool oninventoryopen; bool oninventoryclosed; - bool oninventoryinteract; }; class ContentPackRuntime { diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 713018503..e3c23ee1e 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -540,22 +540,6 @@ void scripting::on_inventory_closed(const Player* player, const Inventory& inven } } -void scripting::on_inventory_interact(int invid, int slot, int action) { - auto args = [invid, slot, action](lua::State* L) { - lua::pushinteger(L, invid); - lua::pushinteger(L, slot); - lua::pushinteger(L, action); - return 3; - }; - for (auto& [packid, pack] : content->getPacks()) { - if (pack->worldfuncsset.oninventoryinteract) { - lua::emit_event( - lua::get_main_state(), packid + ":.inventoryinteract", args - ); - } - } -} - void scripting::on_player_tick(Player* player, int tps) { auto args = [=](lua::State* L) { lua::pushinteger(L, player ? player->getId() : -1); @@ -777,8 +761,6 @@ void scripting::load_world_script( register_event(env, "on_inventory_open", prefix + ":.inventoryopen"); funcsset.oninventoryclosed = register_event(env, "on_inventory_closed", prefix + ":.inventoryclosed"); - funcsset.oninventoryinteract = - register_event(env, "on_inventory_interact", prefix + ":.inventoryinteract"); } void scripting::load_layout_script( diff --git a/src/logic/scripting/scripting_hud.cpp b/src/logic/scripting/scripting_hud.cpp index da72b031b..62dd0781a 100644 --- a/src/logic/scripting/scripting_hud.cpp +++ b/src/logic/scripting/scripting_hud.cpp @@ -93,6 +93,22 @@ void scripting::on_frontend_close() { scripting::post_processing = nullptr; } +void scripting::on_inventory_interact(int invid, int slot, int action) { + auto L = lua::get_main_state(); + for (auto& pack : content_control->getAllContentPacks()) { + lua::emit_event( + L, + pack.id + ":.hudinventoryinteract", + [&](lua::State* L) { + lua::pushinteger(L, invid); + lua::pushinteger(L, slot); + lua::pushinteger(L, action); + return 3; + } + ); + } +} + void scripting::load_hud_script( const scriptenv& senv, const std::string& packid, @@ -109,6 +125,7 @@ void scripting::load_hud_script( register_event(env, "on_hud_open", packid + ":.hudopen"); register_event(env, "on_hud_render", packid + ":.hudrender"); register_event(env, "on_hud_close", packid + ":.hudclose"); + register_event(env, "on_hud_inventory_interact", packid + ":.hudinventoryinteract"); } gui::PageLoaderFunc scripting::create_page_loader() { From f2684edf1fc5cd3aa365742b7103dddda41c2bf3 Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Sat, 7 Mar 2026 00:09:37 +0300 Subject: [PATCH 07/10] update InventoryView --- doc/ru/scripting/events.md | 14 +++++------ src/graphics/ui/elements/InventoryView.cpp | 28 +++++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 598a10d44..f2ccd4787 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -189,13 +189,6 @@ function on_inventory_closed(invid: int, playerid: int) Вызывается при закрытии инвентаря. -```lua -function on_inventory_interact(invid: int, slot: int, action: int) -``` - -Вызывается при взаимодействии со слотом игрока. -**action** отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) - ## События макета @@ -237,6 +230,13 @@ function on_hud_close(playerid: int) Вызывается при выходе из мира, перед его сохранением. +```lua +function on_hud_inventory_interact"(invid: int, slot: int, action: int) +``` + +Вызывается при взаимодействии со слотом игрока. +**action** отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) + ## События ECS События **ECS** описаны [тут](ecs.md#события-компонента) diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index f366a64a8..1ed3518f6 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -350,6 +350,8 @@ bool SlotView::isHighlighted() const { void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) { const auto& input = gui.getInput(); + const int action = 0; + if (layout.taking && input.pressed(Keycode::LEFT_SHIFT)) { if (layout.shareFunc) { layout.shareFunc(layout.index, stack); @@ -357,6 +359,7 @@ void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) { if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } + scripting::on_inventory_interact(inventoryId, layout.index, action | 2); return; } if (!layout.itemSource && stack.accepts(grabbed) && layout.placing) { @@ -376,17 +379,26 @@ void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) { std::swap(grabbed, stack); } } + + scripting::on_inventory_interact(inventoryId, layout.index, action); } void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { + const auto& input = gui.getInput(); + const int action = 1; + if (layout.rightClick) { layout.rightClick(inventoryId, stack); if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } + scripting::on_inventory_interact(inventoryId, layout.index, action); + return; + } + if (layout.itemSource) { + scripting::on_inventory_interact(inventoryId, layout.index, action); return; } - if (layout.itemSource) return; if (grabbed.isEmpty()) { if (!stack.isEmpty() && layout.taking) { grabbed.set(std::move(stack)); @@ -399,10 +411,14 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { stack = ItemStack(0, 0); } } + scripting::on_inventory_interact(inventoryId, layout.index, action); return; } + auto& stackDef = content->getIndices()->items.require(stack.getItemId()); + if (!layout.placing) { + scripting::on_inventory_interact(inventoryId, layout.index, action); return; } if (stack.isEmpty()) { @@ -419,6 +435,8 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { stack.setCount(stack.getCount() + 1); grabbed.setCount(grabbed.getCount() - 1); } + + scripting::on_inventory_interact(inventoryId, layout.index, action); } void SlotView::clicked(Mousecode button) { @@ -431,23 +449,15 @@ void SlotView::clicked(Mousecode button) { ItemStack& grabbed = exchangeSlot->getStack(); ItemStack& stack = *bound; - int action = -1; - if (button == Mousecode::BUTTON_1) { performLeftClick(stack, grabbed); - action = 0; } else if (button == Mousecode::BUTTON_2) { performRightClick(stack, grabbed); - action = 1; } if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } - - const auto& input = gui.getInput(); - action = action | (input.pressed(Keycode::LEFT_SHIFT) ? 2 : 0); - scripting::on_inventory_interact(inventoryId, layout.index, action); } void SlotView::onFocus() { From 8ae35c0a5e1263cbc27b0457281f9d5d5d47338c Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:53:57 +0300 Subject: [PATCH 08/10] rewriting on_inventory_interact --- doc/en/scripting/events.md | 12 +++++++ doc/ru/scripting/events.md | 10 ++++-- src/graphics/ui/elements/InventoryView.cpp | 39 ++++++++++++++-------- src/graphics/ui/elements/InventoryView.hpp | 11 ++++++ src/logic/scripting/scripting.hpp | 2 +- src/logic/scripting/scripting_hud.cpp | 9 ++--- 6 files changed, 62 insertions(+), 21 deletions(-) diff --git a/doc/en/scripting/events.md b/doc/en/scripting/events.md index 6ecc5db27..b78c791a5 100644 --- a/doc/en/scripting/events.md +++ b/doc/en/scripting/events.md @@ -221,6 +221,18 @@ function on_hud_close(playerid: int) Called on world close (before saving) +```lua +function on_inventory_interact(invid: int, slot: int, mode: int, action: int) +``` + +Triggered when a player interacts with inventory slots. + +| ACTION / MODE | (0) PRIMARY | (1) SECONDARY | +| ------------- | -------------------------------------------------- | ------------------------------------------------------ | +| (0) PUT | Places all items; if occupied, swaps them. | Places a single item from the cursor into the slot. | +| (1) TAKE | Picks up all items from the slot. | Picks up half of the items from the slot (rounded up). | +| (2) SHARE | Triggers the share event for the inventory layout. | Undefined | + ## *events* library ```lua diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index f2ccd4787..58a588f28 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -231,11 +231,15 @@ function on_hud_close(playerid: int) Вызывается при выходе из мира, перед его сохранением. ```lua -function on_hud_inventory_interact"(invid: int, slot: int, action: int) +function on_inventory_interact(invid: int, slot: int, mode: int, action: int) ``` -Вызывается при взаимодействии со слотом игрока. -**action** отвечает за тип взаимодействия (0 - левый клик, 1 - правый клик, 2 - левый клик + шифт) +Вызывается при взаимодействии со слотами игроком +| ACTION / MODE | (0) PRIMARY | (1) SECONDARY | +| --------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------- | +| `(0) PUT` | Кладёт все предметы в слот, если другой предмет в слоте - обмен | Кладёт в слот один предмет из слота курсора | +| `(1) TAKE` | Забирает все предметы из слота | Берёт половину предметов из слота (округление вверх) | +| `(2) SHARE` | Вызывает share ивент у макета инвентаря | Не определён | ## События ECS События **ECS** описаны [тут](ecs.md#события-компонента) diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index 1ed3518f6..6429f710f 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -350,57 +350,68 @@ bool SlotView::isHighlighted() const { void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) { const auto& input = gui.getInput(); - const int action = 0; + const int mode = PRIMARY; + int action; if (layout.taking && input.pressed(Keycode::LEFT_SHIFT)) { + action = SHARE; if (layout.shareFunc) { layout.shareFunc(layout.index, stack); } if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } - scripting::on_inventory_interact(inventoryId, layout.index, action | 2); + scripting::on_inventory_interact(inventoryId, layout.index, mode, action); return; } + if (!layout.itemSource && stack.accepts(grabbed) && layout.placing) { + action = PUT; stack.move(grabbed, *content->getIndices()); } else { if (layout.itemSource) { if (grabbed.isEmpty()) { + action = TAKE; grabbed.set(stack); } else { + action = PUT; grabbed.clear(); } } else if (grabbed.isEmpty()) { if (layout.taking) { + action = TAKE; std::swap(grabbed, stack); } } else if (layout.taking && layout.placing) { + action = PUT; std::swap(grabbed, stack); } } - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, action); } void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { const auto& input = gui.getInput(); - const int action = 1; + const int mode = SECONDARY; + int action = PUT; if (layout.rightClick) { layout.rightClick(inventoryId, stack); if (layout.updateFunc) { layout.updateFunc(layout.index, stack); } - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, PUT); return; } if (layout.itemSource) { - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, TAKE); return; } + if (grabbed.isEmpty()) { if (!stack.isEmpty() && layout.taking) { + action = TAKE; grabbed.set(std::move(stack)); int halfremain = stack.getCount() / 2; grabbed.setCount(stack.getCount() - halfremain); @@ -411,17 +422,19 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { stack = ItemStack(0, 0); } } - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, action); return; } - auto& stackDef = content->getIndices()->items.require(stack.getItemId()); - if (!layout.placing) { - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, PUT); return; } + + auto& stackDef = content->getIndices()->items.require(stack.getItemId()); + if (stack.isEmpty()) { + action = PUT; itemcount_t count = grabbed.getCount(); stack.set(std::move(grabbed)); stack.setCount(1); @@ -430,13 +443,13 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) { } else { grabbed = ItemStack(stack.getItemId(), count - 1); } - } else if (stack.accepts(grabbed) && - stack.getCount() < stackDef.stackSize) { + } else if (stack.accepts(grabbed) && stack.getCount() < stackDef.stackSize) { + action = PUT; stack.setCount(stack.getCount() + 1); grabbed.setCount(grabbed.getCount() - 1); } - scripting::on_inventory_interact(inventoryId, layout.index, action); + scripting::on_inventory_interact(inventoryId, layout.index, mode, action); } void SlotView::clicked(Mousecode button) { diff --git a/src/graphics/ui/elements/InventoryView.hpp b/src/graphics/ui/elements/InventoryView.hpp index b77e7d684..03e328815 100644 --- a/src/graphics/ui/elements/InventoryView.hpp +++ b/src/graphics/ui/elements/InventoryView.hpp @@ -56,6 +56,17 @@ namespace gui { ItemStack stack {}; std::wstring countStr; } cache; + + enum InteractionMode { + PRIMARY = 0, + SECONDARY = 1 + }; + + enum InteractionAction { + PUT = 0, + TAKE = 1, + SHARE = 2, + }; const Content* content = nullptr; SlotLayout layout; diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index c54a5fcf1..26bd43ac5 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -108,7 +108,7 @@ namespace scripting { void on_inventory_open(const Player* player, const Inventory& inventory); void on_inventory_closed(const Player* player, const Inventory& inventory); - void on_inventory_interact(int invid, int slot, int action); + void on_inventory_interact(int invid, int slot, int mode, int action); void on_player_tick(Player* player, int tps); diff --git a/src/logic/scripting/scripting_hud.cpp b/src/logic/scripting/scripting_hud.cpp index 62dd0781a..995c2e7a5 100644 --- a/src/logic/scripting/scripting_hud.cpp +++ b/src/logic/scripting/scripting_hud.cpp @@ -93,17 +93,18 @@ void scripting::on_frontend_close() { scripting::post_processing = nullptr; } -void scripting::on_inventory_interact(int invid, int slot, int action) { +void scripting::on_inventory_interact(int invid, int slot, int mode, int action) { auto L = lua::get_main_state(); for (auto& pack : content_control->getAllContentPacks()) { lua::emit_event( L, - pack.id + ":.hudinventoryinteract", + pack.id + ":.inventoryinteract", [&](lua::State* L) { lua::pushinteger(L, invid); lua::pushinteger(L, slot); + lua::pushinteger(L, mode); lua::pushinteger(L, action); - return 3; + return 4; } ); } @@ -125,7 +126,7 @@ void scripting::load_hud_script( register_event(env, "on_hud_open", packid + ":.hudopen"); register_event(env, "on_hud_render", packid + ":.hudrender"); register_event(env, "on_hud_close", packid + ":.hudclose"); - register_event(env, "on_hud_inventory_interact", packid + ":.hudinventoryinteract"); + register_event(env, "on_inventory_interact", packid + ":.inventoryinteract"); } gui::PageLoaderFunc scripting::create_page_loader() { From 4ee97434a247dd25c1cf819dcc5363d3b28a8b1c Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:56:06 +0300 Subject: [PATCH 09/10] update en docs --- doc/en/scripting/builtins/libhud.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/en/scripting/builtins/libhud.md b/doc/en/scripting/builtins/libhud.md index a7e3fa853..1d6264b2d 100644 --- a/doc/en/scripting/builtins/libhud.md +++ b/doc/en/scripting/builtins/libhud.md @@ -54,6 +54,9 @@ hud.close(layoutid: str) -- Get open block inventory ID or 0. hud.get_block_inventory() -> int +-- Gives the ID of the second open inventory (block, virtual inventory...) or 0. +hud.get_second_inventory() -> int + -- Gives the ID of the player that the UI is bound to. hud.get_player() -> int @@ -69,6 +72,9 @@ hud.is_paused() -> bool -- Returns true if inventory is open or overlay is shown. hud.is_inventory_open() -> bool +-- Returns true if the player's inventory is open. +hud.is_player_inventory_open() -> boolean + -- Sets whether to allow pausing. If false, the pause menu will not pause the game. hud.set_allow_pause(flag: bool) From 988c82bc88d6805cc0313457b9d30eb65f6a45bc Mon Sep 17 00:00:00 2001 From: Xertis <118364459+Xertis@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:58:03 +0300 Subject: [PATCH 10/10] Update events.md --- doc/ru/scripting/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 58a588f28..d0cf88a24 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -234,7 +234,7 @@ function on_hud_close(playerid: int) function on_inventory_interact(invid: int, slot: int, mode: int, action: int) ``` -Вызывается при взаимодействии со слотами игроком +Вызывается при взаимодействии игрока с любым слотом | ACTION / MODE | (0) PRIMARY | (1) SECONDARY | | --------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------- | | `(0) PUT` | Кладёт все предметы в слот, если другой предмет в слоте - обмен | Кладёт в слот один предмет из слота курсора |