Completely rework the stacking to be a little more better

This commit is contained in:
2025-03-29 23:19:33 +01:00
parent b440127e54
commit 959e666400

View File

@@ -115,6 +115,94 @@ local function moveItemsTo(slot, itemLocation)
end
end
---@param item Barotrauma.Item
---@param itemTree table<string, ItemLocation[]>
---@return string
local function tryMoveItem(item, itemTree)
local location = itemTree[item.Prefab.Identifier.Value]
if not location then return nil, "No locations for item, not stacking" end
local moved = false
-- First try to move to existing stacks
for _, itemLocation in ipairs(location) do
if itemLocation.maxFits > 0 then
moved = moved or itemLocation.inventory.TryPutItem(item, itemLocation.slotIndex, false, true, nil)
itemLocation.maxFits = itemLocation.inventory.HowManyCanBePut(item.Prefab, itemLocation.slotIndex)
end
end
-- If we can not find an existing stack
-- Then move to any of the empty slots
if not moved then
for _, itemLocation in ipairs(itemTree['empty']) do
moved = moved or itemLocation.inventory.TryPutItem(item, itemLocation.slotIndex, false, true, nil)
itemLocation.maxFits = itemLocation.inventory.HowManyCanBePut(item.Prefab, itemLocation.slotIndex)
end
end
-- If we still can not move the item give up
if not moved then return "Failed to find valid location for item" end
return nil
end
---@param items Barotrauma.Item[]
---@param itemTree table<string, ItemLocation[]>
---@return string[]
local function tryMoveItems(items, itemTree)
local errs = {}
for _, item in ipairs(items) do
local err = tryMoveItem(item, itemTree)
-- oops, this one failed, continue...
if err then
errs[#errs + 1] = string.format("Failed to move item: %s", item.Prefab.Identifier.Value)
end
end
return errs
end
---@param item Barotrauma.Item
---@param queue Barotrauma.Item[]
---@return Barotrauma.Item[], string
local function enqueueItem(item, queue)
queue = queue or {}
queue[#queue + 1] = item
return queue
end
---@param slot Barotrauma.ItemInventory.Slot
---@param queue Barotrauma.Item[]
---@return Barotrauma.Item[], string
local function enqueueSlot(slot, queue)
queue = queue or {}
-- We don't want to shadow queue
local err
-- If the slot is empty there's nothing to iterate
-- And we will naturally return queue as is
for _, item in ipairs(slot.items) do
queue, err = enqueueItem(item, queue)
if err then
print("Error enqueuing item: " .. err)
end
end
return queue
end
---@param inventory Barotrauma.ItemInventory
---@param queue Barotrauma.Item[]
---@return Barotrauma.Item[], string[]
local function enqueueInventory(inventory, queue)
queue = queue or {}
-- We don't want to shadow queue
local err
for _, slot in ipairs(inventory.slots) do
queue, err = enqueueSlot(slot, queue)
if err then
print("Error enqueuing slot: " .. err)
end
end
return queue
end
local function stackInventoryItems(inventory, itemTree)
debugPrint("Starting to stack inventory items...")
for slotIndex, slot in ipairs(inventory.slots) do
@@ -152,6 +240,43 @@ local function stackInventoryItems(inventory, itemTree)
debugPrint("Completed stacking inventory items.")
end
local function stackPlayerInventoryItems(inventory, itemTree)
debugPrint("Starting to stack player inventory items...")
for slotIndex, slot in ipairs(inventory.slots) do
debugPrint("Checking slot index: " .. slotIndex)
-- Cannot stack items if there are no items...
if #slot.items > 0 then
---@type Barotrauma.Item
local item = slot.items[1]
local identifier = item.Prefab.Identifier.Value
debugPrint("Item at slot " .. slotIndex .. " is " .. identifier)
---@type ItemLocation[]
local locations = itemTree[identifier]
-- If there are no locations for this item
-- Then there's nowhere to move it
if locations then
for _, location in ipairs(locations) do
moveItemsTo(slot, location)
if #slot.items == 0 then break end
end
-- If we have processed all the locations and we still have items to move
-- Then put them into the empty slots:
if #slot.items > 0 then
for _, location in ipairs(itemTree['empty']) do
moveItemsTo(slot, location)
if #slot.items == 0 then break end
end
end
end
else
debugPrint("Slot index " .. slotIndex .. " is empty.")
end
end
debugPrint("Completed stacking inventory items.")
end
-- This is a bit fucking sucky.....
-- But I really don't know better
-- Maybe it will be fine...
@@ -186,6 +311,32 @@ local function sortItemtreeBySlots(itemTree)
return itemTree
end
---@param inventory Barotrauma.ItemInventory
---@return table<string, ItemLocation[]>, string
local function tryBuildItemTree(inventory)
local itemTree = {}
debugPrint("Preparing to stack items into the bag...")
local bagSlot = inventory.slots[8]
if bagSlot then
debugPrint("Bag slot found at index 8 with " .. #bagSlot.items .. " items.")
if #bagSlot.items > 0 then
local item = bagSlot.items[1]
debugPrint("Found item in bag slot: " .. item.Name)
if item and item.OwnInventory then
debugPrint("Item has its own inventory, building item tree for it...")
itemTree = buildItemTree(item.OwnInventory, itemTree)
else
return itemTree, "Bag does not have its own inventory."
end
else
return itemTree, "Bag slot is empty."
end
else
return itemTree, "No bag slot found at index 8."
end
return itemTree, nil
end
-- Function to quickly stack items from inventory to containers
local function quickStackItems(character)
if not character then
@@ -201,35 +352,27 @@ local function quickStackItems(character)
return
end
local itemTree = {}
itemTree = buildItemTree(inventory, itemTree)
local itemTree, err = tryBuildItemTree(inventory)
if err then
debugPrint("Error building item tree: " .. err)
return
end
itemTree = sortItemtreeBySlots(itemTree)
debugPrint("Preparing to stack items into the bag...")
local bagSlot = inventory.slots[8]
if bagSlot then
debugPrint("Bag slot found at index 8 with " .. #bagSlot.items .. " items.")
if #bagSlot.items > 0 then
local item = bagSlot.items[1]
debugPrint("Found item in bag slot: " .. item.Name)
if item and item.OwnInventory then
debugPrint("Item has its own inventory, building item tree for it...")
itemTree = buildItemTree(item.OwnInventory, itemTree)
else
debugPrint("Item does not have its own inventory.")
end
else
debugPrint("Bag slot is empty.")
end
else
debugPrint("No bag slot found at index 8.")
local toMove = enqueueInventory(inventory)
for _, item in ipairs(toMove) do
print("Item: " .. item.Prefab.Identifier.Value)
end
local errors = tryMoveItems(toMove, itemTree)
for _, error in ipairs(errors) do
print("Error stacking item: " .. error)
end
stackInventoryItems(item.OwnInventory, itemTree)
local openContainerInventory = getOpenContainer()
if openContainerInventory then
stackInventoryItems(openContainerInventory, itemTree)
end
-- stackPlayerInventoryItems(inventory, itemTree)
-- local openContainerInventory = getOpenContainer()
-- if openContainerInventory then
-- stackInventoryItems(openContainerInventory, itemTree)
-- end
--local handItems = {}
--for _, slotIndex in ipairs(CONFIG.HAND_SLOTS) do