234 lines
6.8 KiB
Lua
234 lines
6.8 KiB
Lua
-- luacheck: globals Character MyModGlobal Timer
|
|
local quickstack = require("Cyka.quickstack")
|
|
local utils = require("Cyka.utils")
|
|
|
|
-- 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 InventorySlot[]
|
|
---@param depth number
|
|
---@return InventorySlot[], 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] = {
|
|
inventory = inventory,
|
|
slotIndex = i,
|
|
slot = slot
|
|
}
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
|
|
return slots, nil
|
|
end
|
|
|
|
---@class InventorySlot
|
|
---@field inventory Barotrauma.Inventory
|
|
---@field slotIndex number
|
|
---@field slot Barotrauma.Inventory.ItemSlot
|
|
|
|
---@return InventorySlot[], string?
|
|
local function getInventorySlotsUnderCursor()
|
|
-- Make sure we have a controlled character
|
|
local controlledCharacter = Character.Controlled
|
|
if not controlledCharacter then return nil, "No controlled character" end
|
|
|
|
local inventory = controlledCharacter.Inventory
|
|
if not inventory then return nil, "No inventory" end
|
|
|
|
local mouseoverSlots, err = getMouseoverSlots(inventory)
|
|
if err then return mouseoverSlots, err end
|
|
|
|
local openContainers = quickstack.getOpenContainers()
|
|
for _, container in ipairs(openContainers) do
|
|
local containerInventories = container.OwnInventories
|
|
for containerInventory in containerInventories do
|
|
for i, visualSlot in ipairs(containerInventory.visualSlots) do
|
|
if visualSlot:MouseOn() then
|
|
local slot = containerInventory.slots[i]
|
|
mouseoverSlots[#mouseoverSlots + 1] = {
|
|
inventory = containerInventory,
|
|
slotIndex = i,
|
|
slot = slot
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return mouseoverSlots, nil
|
|
end
|
|
|
|
local targetInventory = nil
|
|
local slotThrottle = {}
|
|
local function tryStackCursorItem()
|
|
local slots, err = getInventorySlotsUnderCursor()
|
|
if err then
|
|
-- MyModGlobal.debugPrint(string.format("Error getting inventory slot: %s", err))
|
|
return
|
|
end
|
|
|
|
if not slots or #slots == 0 then
|
|
-- MyModGlobal.debugPrint("No items in slot")
|
|
return
|
|
end
|
|
|
|
local inventory = targetInventory
|
|
-- MyModGlobal.debugPrint(string.format("Target inventory: %s", tostring(inventory)))
|
|
if not inventory then
|
|
local controlledCharacter = Character.Controlled
|
|
if not controlledCharacter then
|
|
-- MyModGlobal.debugPrint("No controlled character found")
|
|
return
|
|
end
|
|
local cinventory = controlledCharacter.Inventory
|
|
if not cinventory or not cinventory.slots then
|
|
-- MyModGlobal.debugPrint("No inventory found")
|
|
return
|
|
end
|
|
local bagSlot = cinventory.slots[MyModGlobal.BAG_SLOT]
|
|
if not bagSlot or not bagSlot.items or not bagSlot.items[1] then
|
|
-- MyModGlobal.debugPrint("No bag slot found")
|
|
return
|
|
end
|
|
local bagItem = bagSlot.items[1]
|
|
if not bagItem or not bagItem.OwnInventory then
|
|
-- MyModGlobal.debugPrint("Bag item has no own inventory")
|
|
return
|
|
end
|
|
local bagInventory = bagItem.OwnInventory
|
|
if not bagInventory or not bagInventory.slots then
|
|
-- MyModGlobal.debugPrint("Bag inventory has no slots")
|
|
return
|
|
end
|
|
inventory = bagInventory
|
|
end
|
|
if not inventory then
|
|
-- MyModGlobal.debugPrint("No inventory found")
|
|
return
|
|
end
|
|
|
|
local itemTree
|
|
itemTree, err = quickstack.buildItemTree(inventory)
|
|
if err then
|
|
-- MyModGlobal.debugPrint(string.format("Error building item tree: %s", err))
|
|
return
|
|
end
|
|
itemTree = quickstack.sortItemTree(itemTree)
|
|
|
|
local itemsToMove = {}
|
|
local now = Timer.GetTime()
|
|
for _, slot in ipairs(slots) do
|
|
local runAfter = slotThrottle[slot] or 0
|
|
if now < runAfter then
|
|
goto continue
|
|
end
|
|
-- MyModGlobal.debugPrint(string.format("Enqueuing slot: %s, before: %d", tostring(slot), #itemsToMove))
|
|
utils.enqueueSlot(slot.slot, itemsToMove)
|
|
-- MyModGlobal.debugPrint(string.format("Enqueuing slot: %s, after: %d", tostring(slot), #itemsToMove))
|
|
slotThrottle[slot] = now + 1
|
|
::continue::
|
|
end
|
|
-- 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)
|
|
|
|
quickstack.tryMoveItems(itemsToMove, itemTree, true)
|
|
-- local errors = quickstack.tryMoveItems(itemsToMove, itemTree, true)
|
|
-- for _, error in ipairs(errors) do
|
|
-- MyModGlobal.debugPrint(string.format("Error moving item: %s", error))
|
|
-- end
|
|
end
|
|
|
|
local function setTargetInventory()
|
|
---@type InventorySlot[]
|
|
local slots, err = getInventorySlotsUnderCursor()
|
|
if err then
|
|
MyModGlobal.debugPrint(string.format("Error getting inventory slot: %s", err))
|
|
return
|
|
end
|
|
if not slots or #slots == 0 then
|
|
MyModGlobal.debugPrint("No inventory slots found")
|
|
return
|
|
end
|
|
-- Yes we do this in a loop
|
|
-- The idea is if we get one slot we're golden, great!
|
|
-- If we get multiple we'll use the first valid one
|
|
-- Although everything is valid to us...
|
|
for _, slot in ipairs(slots) do
|
|
local item
|
|
local items = slot.slot.items
|
|
if not items or #items == 0 then
|
|
print(string.format("Slot is empty, setting target inventory to %s", tostring(slot.inventory)))
|
|
targetInventory = slot.inventory
|
|
goto continue
|
|
end
|
|
item = items[1]
|
|
if not item then
|
|
print(string.format("Item in slot is nil, setting target inventory to %s", tostring(slot.inventory)))
|
|
targetInventory = slot.inventory
|
|
goto continue
|
|
end
|
|
if not item.OwnInventory then
|
|
print(string.format("Item has no own inventory, setting target inventory to %s", tostring(slot.inventory)))
|
|
targetInventory = slot.inventory
|
|
goto continue
|
|
end
|
|
print(string.format("Item has own inventory, setting target inventory to %s", tostring(item.OwnInventory)))
|
|
targetInventory = item.OwnInventory
|
|
break
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
return {
|
|
tryStackCursorItem = tryStackCursorItem,
|
|
setTargetInventory = setTargetInventory,
|
|
getInventorySlotsUnderCursor = getInventorySlotsUnderCursor
|
|
}
|