201 lines
6.3 KiB
Lua
201 lines
6.3 KiB
Lua
-- luacheck: globals Character MyModGlobal Timer
|
|
local cursormacroer = require("Cyka.cursormacroer")
|
|
local dump = require("Cyka.dump")
|
|
|
|
---@class InventorySlot
|
|
---@field slot Barotrauma.ItemSlot
|
|
---@field inventory Barotrauma.ItemInventory
|
|
---@field slotIndex number
|
|
|
|
---@param inventory Barotrauma.ItemInventory
|
|
---@param predicate fun(slot: InventorySlot): boolean
|
|
---@return InventorySlot[], string?
|
|
local function findSlotsThat(inventory, predicate)
|
|
local slots = {}
|
|
for i, slot in ipairs(inventory.slots) do
|
|
local inventorySlot = {
|
|
slot = slot,
|
|
inventory = inventory,
|
|
slotIndex = i - 1
|
|
}
|
|
if predicate(inventorySlot) then
|
|
slots[#slots + 1] = inventorySlot
|
|
end
|
|
end
|
|
return slots
|
|
end
|
|
|
|
---@param slot InventorySlot
|
|
local function tryUnloadSlot(slot)
|
|
---@type Barotrauma.Item
|
|
local item = slot.slot.items[1]
|
|
if not item then
|
|
MyModGlobal.debugPrint("No item in slot")
|
|
return
|
|
end
|
|
local inventory = item.OwnInventory
|
|
if not inventory then
|
|
MyModGlobal.debugPrint("Item has no own inventory")
|
|
return
|
|
end
|
|
|
|
local toUnload = {}
|
|
local toUnloadByPrefab = {}
|
|
local inventorySlots = inventory.slots
|
|
for _, inventorySlot in ipairs(inventorySlots) do
|
|
for _, inventoryItem in ipairs(inventorySlot.items) do
|
|
toUnload[#toUnload + 1] = inventoryItem
|
|
-- This will only serve as O(1) lookup
|
|
toUnloadByPrefab[inventoryItem.Prefab] = true
|
|
end
|
|
end
|
|
|
|
-- Where can we put our toUnload items?
|
|
local nearbySlots = findSlotsThat(slot.inventory, function(islot)
|
|
local isEmpty = #islot.slot.items == 0
|
|
if isEmpty then return true end
|
|
|
|
for _, prefab in ipairs(toUnloadByPrefab) do
|
|
local canAccept = islot.inventory.CanBePutInSlot(prefab, islot.slotIndex)
|
|
if canAccept then return true end
|
|
end
|
|
return false
|
|
end)
|
|
-- print("Before sorting:")
|
|
-- dump(nearbySlots)
|
|
|
|
local slotsPerRow = slot.inventory.slotsPerRow or 1
|
|
local getGridPos = function(slotIndex)
|
|
local x = slotIndex % slotsPerRow
|
|
local y = math.floor(slotIndex / slotsPerRow)
|
|
return x, y
|
|
end
|
|
|
|
-- We are offsetting here by 1 because the backend uses 0-indexed slots
|
|
-- And the lua uses 1-indexed slots
|
|
-- We are trying to match the backend behavior for sorting
|
|
local slotx, sloty = getGridPos(slot.slotIndex - 1)
|
|
-- print(string.format("Slot position %d: %d, %d", slot.slotIndex, slotx, sloty))
|
|
table.sort(nearbySlots, function(a, b)
|
|
local ax, ay = getGridPos(a.slotIndex)
|
|
local bx, by = getGridPos(b.slotIndex)
|
|
|
|
local distA = math.max(math.abs(ax - slotx), math.abs(ay - sloty))
|
|
local distB = math.max(math.abs(bx - slotx), math.abs(by - sloty))
|
|
|
|
if distA == distB then
|
|
return a.slotIndex < b.slotIndex
|
|
end
|
|
return distA < distB
|
|
end)
|
|
-- print(string.format("Current slot: %d at (%d, %d)", slot.slotIndex, slotx, sloty))
|
|
|
|
for _, iitem in ipairs(toUnload) do
|
|
for _, nearbySlot in ipairs(nearbySlots) do
|
|
local canAccept = nearbySlot.inventory.CanBePutInSlot(iitem.Prefab, nearbySlot.slotIndex)
|
|
if canAccept then
|
|
local moved = nearbySlot.inventory.TryPutItem(iitem, nearbySlot.slotIndex, true, false, nil)
|
|
-- print(string.format("Moved item %s to slot %d", iitem.Name, nearbySlot.slotIndex))
|
|
if moved then break end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function tryUnloadCursorItem()
|
|
local slots, err = cursormacroer.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
|
|
|
|
for _, slot in ipairs(slots) do
|
|
tryUnloadSlot(slot)
|
|
end
|
|
|
|
-- local canAccept = inventorySlot.CanBePutInSlot(item, inventorySlot.slotIndex, item.Condition)
|
|
-- if canAccept then
|
|
-- toUnload[#toUnload + 1] = inventoryItem
|
|
-- end
|
|
-- local slots = findSlotsThat(inventory, function(slot)
|
|
-- local canAccept
|
|
-- 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
|
|
|
|
return {
|
|
tryUnloadCursorItem = tryUnloadCursorItem,
|
|
}
|