Files
barotrauma-localmods/QuickStackToBag/Lua/Cyka/utils.lua
2025-03-30 22:02:00 +02:00

116 lines
4.2 KiB
Lua

-- We got to do this shit because enqueueInventory calls enqueueItem
-- And enqueueItem calls enqueueInventory
-- So unless we define them both before using them
-- We will get an error saying either is undefined
local enqueueItem
local enqueueSlot
local enqueueInventory
local _
---@alias FilterPredicate fun(item: Barotrauma.Item, inventoryRef?: Barotrauma.ItemInventory, slotRef: Barotrauma.ItemInventory.Slot): boolean
---@param item Barotrauma.Item
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@param slotRef? Barotrauma.ItemInventory.Slot
---@param inventoryRef? Barotrauma.ItemInventory
---@return Barotrauma.Item[], string?
enqueueItem = function(item, queue, predicate, loadRefs, slotRef, inventoryRef)
queue = queue or {}
predicate = predicate or function() return true end
-- debugPrint(string.format("Enqueuing item: %s", item.Prefab.Identifier.Value))
-- local err
-- This should make it breadth first, right...?
-- No, not yet...
if not item then return queue, "No item" end
local ok, stop = predicate(item, inventoryRef, slotRef)
if ok then
queue[#queue + 1] = item
end
if stop then return queue, "Stop" end
if item.OwnInventory then
-- As far as I know every item has only one inventory
-- Only machines have multiple
-- So inventrorY should be fine here
-- debugPrint("Item has its own inventory, enqueuing inventory...")
if loadRefs then
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, loadRefs)
else
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate)
end
-- if err then
-- debugPrint(string.format("Error enqueuing inventory: %s", err))
-- end
end
-- debugPrint(string.format("Item enqueued. Current queue size: %d", #queue))
return queue, nil
end
---@param slot Barotrauma.ItemInventory.Slot
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@param inventoryRef? Barotrauma.ItemInventory
---@return Barotrauma.Item[], string?
enqueueSlot = function(slot, queue, predicate, loadRefs, inventoryRef)
queue = queue or {}
predicate = predicate or function() return true end
-- debugPrint(string.format("Enqueuing slot with %d items.", #slot.items))
-- 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
if not slot then return queue, "No slot" end
if not slot.items then return queue, "No items" end
for _, item in ipairs(slot.items) do
-- Only the final leaf nodes decide upon the predicate
if loadRefs then
queue, err = enqueueItem(item, queue, predicate, loadRefs, inventoryRef, slot)
else
queue, err = enqueueItem(item, queue, predicate)
end
if err then
return queue, err
end
end
-- debugPrint(string.format("Finished enqueuing slot. Current queue size: %d", #queue))
return queue
end
---@param inventory Barotrauma.ItemInventory
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@return Barotrauma.Item[], string?
enqueueInventory = function(inventory, queue, predicate, loadRefs)
queue = queue or {}
predicate = predicate or function() return true end
-- debugPrint(string.format("Enqueuing inventory with %d slots.", #inventory.slots))
local err
if not inventory then return queue, "No inventory" end
if not inventory.slots then return queue, "No slots" end
for _, slot in ipairs(inventory.slots) do
-- Only the final leaf nodes decide upon the predicate
if loadRefs then
queue, err = enqueueSlot(slot, queue, predicate, loadRefs, inventory)
else
queue, err = enqueueSlot(slot, queue, predicate)
end
if err then
return queue, err
end
end
-- debugPrint(string.format("Finished enqueuing inventory. Current queue size: %d", #queue))
return queue
end
return {
enqueueItem = enqueueItem,
enqueueSlot = enqueueSlot,
enqueueInventory = enqueueInventory
}