Rework finding mouseover slots to not go over inventories that can not be open at this time

This commit is contained in:
2025-03-30 18:22:17 +02:00
parent 254f384648
commit e463b84bf6
2 changed files with 99 additions and 57 deletions

View File

@@ -1,121 +1,162 @@
local quickstack = require("Cyka.quickstack") local quickstack = require("Cyka.quickstack")
local utils = require("Cyka.utils") local utils = require("Cyka.utils")
---@return Barotrauma.VisualSlot|nil, Barotrauma.Inventory|nil, Barotrauma.Inventory.ItemSlot|nil -- There is actually no need to recurse deep
-- Because we can only have an item in the inventory open
-- And not an item in an item in the inventory
-- So in theory we only need to recurse 1 deep
---@param inventory Barotrauma.Inventory
---@param slots Barotrauma.Inventory.SlotReference[]
---@return Barotrauma.Inventory.SlotReference[], string?
local function getMouseoverSlots(inventory, slots, depth)
slots = slots or {}
depth = depth or 0
if depth > 1 then return slots, nil end
local visualSlots = inventory.visualSlots
if not visualSlots then return nil, "Inventory has no visual slots" end
for i, visualSlot in ipairs(visualSlots) do
local item
local itemInventory
-- local err
local slot = inventory.slots[i]
if not slot then
-- MyModGlobal.debugPrint("Slot is not a valid slot")
goto continue
end
if #slot.items == 0 then
goto mouseover
end
item = slot.items[1]
if not item then
goto mouseover
end
itemInventory = item.OwnInventory
if not itemInventory then
goto mouseover
end
-- print("Before: " .. #slots)--
getMouseoverSlots(itemInventory, slots, depth + 1)
-- if err then
-- MyModGlobal.debugPrint(string.format("Error getting mouseover slots: %s", err))
-- end
-- print("After: " .. #slots)
::mouseover::
if visualSlot:MouseOn() then
slots[#slots + 1] = slot
end
::continue::
end
return slots, nil
end
---@return Barotrauma.Inventory.ItemSlot[]?, string?
local function getInventorySlotUnderCursor() local function getInventorySlotUnderCursor()
-- Make sure we have a controlled character -- Make sure we have a controlled character
local controlledCharacter = Character.Controlled local controlledCharacter = Character.Controlled
if not controlledCharacter then return nil, nil, nil end if not controlledCharacter then return nil, "No controlled character" end
-- Check player inventory first local inventory = controlledCharacter.Inventory
local charInventory = controlledCharacter.Inventory if not inventory then return nil, "No inventory" end
if charInventory and charInventory.visualSlots then
for i, visualSlot in ipairs(charInventory.visualSlots) do
-- Check if mouse is over this slot
if visualSlot:MouseOn() then
local slot = charInventory.slots[i]
return visualSlot, charInventory, slot
end
end
end
-- Check if selected item has inventory (containers, etc.) local mouseoverSlots, err = getMouseoverSlots(inventory)
local selectedItem = controlledCharacter.SelectedItem if err then return mouseoverSlots, err end
if selectedItem and selectedItem.OwnInventory and selectedItem.OwnInventory.visualSlots then
local itemInv = selectedItem.OwnInventory
for i, visualSlot in ipairs(itemInv.visualSlots) do
if visualSlot:MouseOn() then
local slot = itemInv.slots[i]
return visualSlot, itemInv, slot
end
end
end
-- Check open containers or other items with visible inventories local openContainers = quickstack.getOpenContainers()
for item in Item.ItemList do for _, container in ipairs(openContainers) do
if item and item.OwnInventory and item.OwnInventory.visualSlots then local containerInventories = container.OwnInventories
local itemInv = item.OwnInventory for containerInventory in containerInventories do
for i, visualSlot in ipairs(itemInv.visualSlots) do for i, visualSlot in ipairs(containerInventory.visualSlots) do
if visualSlot:MouseOn() then if visualSlot:MouseOn() then
local slot = itemInv.slots[i] local slot = containerInventory.slots[i]
return visualSlot, itemInv, slot mouseoverSlots[#mouseoverSlots + 1] = slot
end end
end end
end end
end end
return nil, nil, nil return mouseoverSlots, nil
end end
local targetInventory = nil local targetInventory = nil
local function tryStackCursorItem() local function tryStackCursorItem()
local visualSlot, itemInv, slot = getInventorySlotUnderCursor() local slots, err = getInventorySlotUnderCursor()
if not visualSlot or not itemInv or not slot then if err then
MyModGlobal.debugPrint(string.format("No inventory slot or item found")) -- MyModGlobal.debugPrint(string.format("Error getting inventory slot: %s", err))
return return
end end
-- MyModGlobal.debugPrint(string.format("Visual slot: %s", tostring(visualSlot)))
-- MyModGlobal.debugPrint(string.format("Item inventory: %s", tostring(itemInv)))
-- MyModGlobal.debugPrint(string.format("Inventory slot: %s", tostring(slot)))
if not slot or not slot.items or not slot.items[1] then if not slots or #slots == 0 then
MyModGlobal.debugPrint("No items in slot") -- MyModGlobal.debugPrint("No items in slot")
return return
end end
local inventory = targetInventory local inventory = targetInventory
MyModGlobal.debugPrint(string.format("Target inventory: %s", tostring(inventory))) -- MyModGlobal.debugPrint(string.format("Target inventory: %s", tostring(inventory)))
if not inventory then if not inventory then
local controlledCharacter = Character.Controlled local controlledCharacter = Character.Controlled
if not controlledCharacter then if not controlledCharacter then
MyModGlobal.debugPrint("No controlled character found") -- MyModGlobal.debugPrint("No controlled character found")
return return
end end
local cinventory = controlledCharacter.Inventory local cinventory = controlledCharacter.Inventory
if not cinventory or not cinventory.slots then if not cinventory or not cinventory.slots then
MyModGlobal.debugPrint("No inventory found") -- MyModGlobal.debugPrint("No inventory found")
return return
end end
local bagSlot = cinventory.slots[MyModGlobal.BAG_SLOT] local bagSlot = cinventory.slots[MyModGlobal.BAG_SLOT]
if not bagSlot or not bagSlot.items or not bagSlot.items[1] then if not bagSlot or not bagSlot.items or not bagSlot.items[1] then
MyModGlobal.debugPrint("No bag slot found") -- MyModGlobal.debugPrint("No bag slot found")
return return
end end
local bagItem = bagSlot.items[1] local bagItem = bagSlot.items[1]
if not bagItem or not bagItem.OwnInventory then if not bagItem or not bagItem.OwnInventory then
MyModGlobal.debugPrint("Bag item has no own inventory") -- MyModGlobal.debugPrint("Bag item has no own inventory")
return return
end end
local bagInventory = bagItem.OwnInventory local bagInventory = bagItem.OwnInventory
if not bagInventory or not bagInventory.slots then if not bagInventory or not bagInventory.slots then
MyModGlobal.debugPrint("Bag inventory has no slots") -- MyModGlobal.debugPrint("Bag inventory has no slots")
return return
end end
inventory = bagInventory inventory = bagInventory
end end
if not inventory then if not inventory then
MyModGlobal.debugPrint("No inventory found") -- MyModGlobal.debugPrint("No inventory found")
return return
end end
local itemTree, err = quickstack.buildItemTree(inventory) local itemTree
itemTree, err = quickstack.buildItemTree(inventory)
if err then if err then
MyModGlobal.debugPrint(string.format("Error building item tree: %s", err)) -- MyModGlobal.debugPrint(string.format("Error building item tree: %s", err))
return return
end end
itemTree = quickstack.sortItemTree(itemTree) itemTree = quickstack.sortItemTree(itemTree)
local itemsToMove = utils.enqueueSlot(slot) local itemsToMove = {}
for _, item in ipairs(itemsToMove) do for _, slot in ipairs(slots) do
MyModGlobal.debugPrint(string.format("Enqueued item: %s", tostring(item))) utils.enqueueSlot(slot, itemsToMove)
end end
-- MyModGlobal.debugPrint(string.format("Enqueued %d items from the inventory slot", #itemsToMove)) -- for _, item in ipairs(itemsToMove) do
-- MyModGlobal.debugPrint(string.format("Enqueued item: %s", tostring(item)))
-- end
-- -- MyModGlobal.debugPrint(string.format("Enqueued %d items from the inventory slot", #itemsToMove))
-- MyModGlobal.DumpTable(itemTree) -- MyModGlobal.DumpTable(itemTree)
local errors = quickstack.tryMoveItems(itemsToMove, itemTree, true) local errors = quickstack.tryMoveItems(itemsToMove, itemTree, true)
for _, error in ipairs(errors) do -- for _, error in ipairs(errors) do
MyModGlobal.debugPrint(string.format("Error moving item: %s", error)) -- MyModGlobal.debugPrint(string.format("Error moving item: %s", error))
end -- end
end end
local function setTargetInventory() local function setTargetInventory()

View File

@@ -338,5 +338,6 @@ return {
sortItemTree = sortItemTree, sortItemTree = sortItemTree,
tryMoveItem = tryMoveItem, tryMoveItem = tryMoveItem,
tryMoveItems = tryMoveItems, tryMoveItems = tryMoveItems,
quickStackItems = quickStackItems quickStackItems = quickStackItems,
getOpenContainers = getOpenContainers
} }