diff --git a/doc/en/scripting/builtins/libhud.md b/doc/en/scripting/builtins/libhud.md index 1d6264b2d..550659ccc 100644 --- a/doc/en/scripting/builtins/libhud.md +++ b/doc/en/scripting/builtins/libhud.md @@ -57,6 +57,10 @@ hud.get_block_inventory() -> int -- Gives the ID of the second open inventory (block, virtual inventory...) or 0. hud.get_second_inventory() -> int +-- Get the inventory ID of exchange item (grabbed item in inventory) or 0. +-- It has only one slot - 0 +hud.get_exchange_inventory() -> int + -- Gives the ID of the player that the UI is bound to. hud.get_player() -> int diff --git a/doc/ru/scripting/builtins/libhud.md b/doc/ru/scripting/builtins/libhud.md index bad0e93c6..7a93c93e4 100644 --- a/doc/ru/scripting/builtins/libhud.md +++ b/doc/ru/scripting/builtins/libhud.md @@ -58,6 +58,11 @@ hud.get_block_inventory() -> int -- Дает ID второго открытого инвентаря (блок, виртуальный инвентарь...) или 0. hud.get_second_inventory() -> int +-- Получить ID инвентаря, в котором находится предмет во время +-- его перемещения в инвентаре, или 0 если его не существует. +-- Имеет единственный слот - 0 +hud.get_exchange_inventory() -> int + -- Дает ID игрока, к которому привязан пользовательский интерфейс. hud.get_player() -> int @@ -81,4 +86,4 @@ hud.set_allow_pause(flag: boolean) -- Функция, управляющая именованным скелетом 'hand' (см. gfx.skeletons) hud.hand_controller: function() -``` \ No newline at end of file +``` diff --git a/res/content/base/modules/util.lua b/res/content/base/modules/util.lua index 874e6d3d6..4d25ccb91 100644 --- a/res/content/base/modules/util.lua +++ b/res/content/base/modules/util.lua @@ -1,5 +1,44 @@ local util = {} +local DROP_FORCE = 8 +local DROP_INIT_VEL = {0, 3, 0} + +---@param mode integer 0 - whole stack, 1 - single item, 2 - dupe whole stack +function util.drop_from_slot(invid, slot, mode) + if invid == 0 then + return + end + local pid = hud.get_player() + if mode == 2 and not player.is_infinite_items(pid) then + return + end + local itemid, itemcount = inventory.get(invid, slot) + if itemid == 0 then + return + end + + local drop_itemcount = 1 + if mode == 0 then + drop_itemcount = itemcount + end + if mode == 2 then + drop_itemcount = item.stack_size(itemid) + else + inventory.set(invid, slot, itemid, itemcount - drop_itemcount) + end + + local data = inventory.get_all_data(invid, slot) + local pvel = { player.get_vel(pid) } + local ppos = vec3.add({ player.get_pos(pid) }, { 0, 0.7, 0 }) + local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE) + local drop = util.drop(ppos, itemid, drop_itemcount, data, 1.5) + if not drop then + return + end + local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) + drop.rigidbody:set_vel(velocity) +end + function util.drop(ppos, itemid, count, data, pickup_delay) if itemid == 0 or not itemid then return nil diff --git a/res/content/base/scripts/hud.lua b/res/content/base/scripts/hud.lua index 0ec427c11..d0e3d1532 100644 --- a/res/content/base/scripts/hud.lua +++ b/res/content/base/scripts/hud.lua @@ -1,31 +1,21 @@ local base_util = require "util" -local DROP_FORCE = 8 -local DROP_INIT_VEL = {0, 3, 0} - function on_hud_open() - input.add_callback("player.drop", function () + events.on("core:drop_outside_inventory", function(mode) + local invid = hud.get_exchange_inventory() + base_util.drop_from_slot(invid, 0, mode) + end) + input.add_callback("player.drop", function() if hud.is_paused() or hud.is_inventory_open() then return end local pid = hud.get_player() local invid, slot = player.get_inventory(pid) - local itemid, itemcount = inventory.get(invid, slot) - if itemid == 0 then - return + local mode = 1 + if input.is_pressed("key:left-ctrl") or input.is_pressed("key:right-ctrl") then + mode = 0 end - local data = inventory.get_all_data(invid, slot) - inventory.set(invid, slot, itemid, itemcount-1) - - local pvel = {player.get_vel(pid)} - local ppos = vec3.add({player.get_pos(pid)}, {0, 0.7, 0}) - local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE) - local drop = base_util.drop(ppos, itemid, 1, data, 1.5) - if not drop then - return - end - local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) - drop.rigidbody:set_vel(velocity) + base_util.drop_from_slot(invid, slot, mode) end) rules.create("do-loot-non-player", true) end diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 1aa03436b..08a4b8455 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -174,6 +174,15 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) gui, "" ); + + inventoryDropArea = guiutil::create( + gui, + R"()" + ); uicamera = std::make_unique(glm::vec3(), 1); uicamera->perspective = false; @@ -188,6 +197,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) gui.add(debugPanel); gui.add(darkOverlay); + gui.add(inventoryDropArea); gui.add(hotbarView); gui.add(contentAccessPanel); @@ -213,6 +223,7 @@ Hud::~Hud() { } gui.remove(hotbarView); gui.remove(darkOverlay); + gui.remove(inventoryDropArea); gui.remove(contentAccessPanel); gui.remove(debugPanel); } @@ -358,6 +369,7 @@ void Hud::update(bool visible) { contentAccess->setMinSize(glm::vec2(1, windowSize.y)); hotbarView->setVisible(visible && !(secondUI && !inventoryView)); darkOverlay->setVisible(isMenuOpen); + inventoryDropArea->setVisible(inventoryOpen); menu.setVisible(isMenuOpen); if (visible) { @@ -739,6 +751,10 @@ std::shared_ptr Hud::getSecondInventory() { return nullptr; } +std::shared_ptr Hud::getExchangeInventory() { + return exchangeSlotInv; +} + bool Hud::isContentAccess() const { return showContentPanel; } diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index f80c36369..f40a53581 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -93,6 +93,8 @@ class Hud : public util::ObjectsKeeper { std::shared_ptr debugPanel; /// @brief Overlay used in pause mode std::shared_ptr darkOverlay; + /// @brief Overlay used in inventory + std::shared_ptr inventoryDropArea; /// @brief Inventories interaction agent (grabbed item) std::shared_ptr exchangeSlot; /// @brief Exchange slot inventory (1 slot only) @@ -207,6 +209,8 @@ public: std::shared_ptr getSecondInventory(); + std::shared_ptr getExchangeInventory(); + bool isContentAccess() const; void setContentAccess(bool flag); diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 8bfe3a341..944c32fb5 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -14,7 +14,6 @@ #include "frontend/UiDocument.hpp" #include "frontend/locale.hpp" #include "graphics/core/Batch2D.hpp" -#include "graphics/core/LineBatch.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Font.hpp" #include "graphics/core/DrawContext.hpp" diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index 144d80397..395c8d34e 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -12,11 +12,8 @@ #include "graphics/core/Batch2D.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/Font.hpp" -#include "graphics/core/Shader.hpp" -#include "graphics/core/Texture.hpp" #include "graphics/render/BlocksPreview.hpp" #include "graphics/ui/GUI.hpp" -#include "items/Inventories.hpp" #include "items/Inventory.hpp" #include "items/ItemDef.hpp" #include "logic/scripting/scripting.hpp" diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index 7f5c893c5..a457ca6ee 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -149,6 +149,15 @@ static int l_get_second_inventory(lua::State* L) { } } +static int l_get_exchange_inventory(lua::State* L) { + auto inventory = hud->getExchangeInventory(); + 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()); @@ -216,6 +225,7 @@ const luaL_Reg hudlib[] = { {"show_overlay", wrap_hud}, {"get_block_inventory", wrap_hud}, {"get_second_inventory", wrap_hud}, + {"get_exchange_inventory", wrap_hud}, {"close", wrap_hud}, {"pause", wrap_hud}, {"resume", wrap_hud},