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() {