Completely and totally rework utils

This commit is contained in:
2025-04-01 18:49:22 +02:00
parent 07b42dfa05
commit 91b8576385

View File

@@ -1,15 +1,172 @@
-- luacheck: globals Character MyModGlobal -- luacheck: globals Character MyModGlobal Timer _
-- luacheck: max line length 420 -- luacheck: max line length 420
---@class ItemRefs ---@class Barotrauma.Inventory.ItemSlot
---@field item Barotrauma.Item ---@field items Barotrauma.Item[]
---@field inventory Barotrauma.ItemInventory
---@field slot Barotrauma.ItemInventory.Slot
-- local globalInventorySlotCache = {}
---@class InventorySlot ---@class InventorySlot
---@field slot Barotrauma.ItemSlot ---@field slot Barotrauma.Inventory.ItemSlot
---@field inventory Barotrauma.ItemInventory ---@field inventory Barotrauma.Inventory
---@field slotIndex number ---@field slotIndex1 number Lua based item slots
---@field slotIndex0 number Barotrauma API based item slots
---@field item Barotrauma.Item
---@field stackSize number
---@field maxStackSize number
-- ---@field lastUpdated number
MyModGlobal.InventorySlot = {
---@param inventory Barotrauma.Inventory
---@param slotIndex1 number
---@return InventorySlot
new = function(inventory, slotIndex1)
local self = setmetatable({}, {
__index = MyModGlobal.InventorySlot
})
self.inventory = inventory
self.slotIndex1 = slotIndex1
self.slotIndex0 = slotIndex1 - 1
-- self:update()
if inventory and inventory.slots and #inventory.slots > 0 then
self.slot = inventory.slots[slotIndex1]
end
if self.slot and self.slot.items and #self.slot.items > 0 then
self.item = self.slot.items[1]
self.stackSize = #self.slot.items
-- At this point inventory has to exist
-- If it didn't slot wouldn't either and then this wouldn't either
self.maxStackSize = self.item.Prefab.GetMaxStackSize(inventory)
end
return self
end,
update = function(self)
-- self.lastUpdated = Timer.GetTime()
if not self.inventory then
MyModGlobal.debugPrint("Error updating inventory slot, inventory not found")
return
end
if not self.inventory.slots then
MyModGlobal.debugPrint("Error updating inventory slot, inventory has no slots")
return
end
local slot = self.inventory.slots[self.slotIndex1]
if not slot then
MyModGlobal.debugPrint("Error updating inventory slot, slot not found")
return
end
self.slot = slot
if not slot.items or #slot.items == 0 then
-- MyModGlobal.debugPrint("Error updating inventory slot, slot is empty")
return
end
self.item = slot.items[1]
self.stackSize = #slot.items
self.maxStackSize = self.item.Prefab.GetMaxStackSize(self.inventory)
end,
__tostring = function(self)
return string.format(
"InventorySlot(inventory=%s, slotIndex1=%d, slotIndex0=%d, item=%s, stackSize=%d, maxStackSize=%d)",
tostring(self.inventory), self.slotIndex1, self.slotIndex0, tostring(self.item), self.stackSize,
self.maxStackSize)
end,
---@param predicate? fun(slot: InventorySlot): boolean
getNearbySlots = function(self, predicate)
predicate = predicate or function() return true end
local slotsPerRow = 900
local ok, err = pcall(function()
slotsPerRow = self.inventory.slotsPerRow
end)
if not ok then
MyModGlobal.debugPrint(string.format("Error getting slots per row: %s", err))
end
local getGridPos = function(slotIndex)
local x = slotIndex % slotsPerRow
local y = math.floor(slotIndex / slotsPerRow)
return x, y
end
local slots = {}
for slotIndex, _ in ipairs(self.inventory.slots) do
local inventorySlot = MyModGlobal.InventorySlot.new(self.inventory, slotIndex)
if predicate(inventorySlot) then
slots[#slots + 1] = inventorySlot
end
end
local slotx, sloty = getGridPos(self.slotIndex0)
table.sort(slots, function(a, b)
local ax, ay = getGridPos(a.slotIndex0)
local bx, by = getGridPos(b.slotIndex0)
-- Chebyshev distance
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.slotIndex0 < b.slotIndex0
end
return distA < distB
end)
return slots
end,
-- hash = function(self)
-- return string.format("%s:%d:%d", tostring(self.inventory), self.slotIndex1, self.slotIndex0)
-- end
}
---@class ItemMoveRequest
---@field A InventorySlot
---@field B InventorySlot
---@field allowSwap boolean
---@field allowCombine boolean
local enqueueMove
do
-- A bit of cheeky scoping
local enabled = true
---@type ItemMoveRequest[]
local itemMoveQueue = {}
local rate = 10
local function processQueue()
MyModGlobal.debugPrint("Processing queue")
Timer.Wait(processQueue, rate)
if not enabled then return end
if #itemMoveQueue == 0 then return end
---@type ItemMoveRequest
local moveRequest = table.remove(itemMoveQueue, 1)
-- TODO: Maybe try and figure out if we CAN put A into B
moveRequest.allowCombine = moveRequest.allowCombine or false
moveRequest.allowSwap = moveRequest.allowSwap or false
local success = moveRequest.B.inventory.TryPutItem(moveRequest.A.item, moveRequest.B.slotIndex0,
moveRequest.allowSwap, moveRequest.allowCombine, Character.Controlled, true)
if not success then
MyModGlobal.debugPrint(string.format("Failed moving item from %s to %s", tostring(moveRequest.A),
tostring(moveRequest.B)))
end
end
processQueue()
---@param A InventorySlot
---@param B InventorySlot
---@param allowSwap boolean
---@param allowCombine boolean
enqueueMove = function(A, B, allowSwap, allowCombine)
MyModGlobal.debugPrint(string.format("Enqueuing move from %s to %s", tostring(A), tostring(B)))
table.insert(itemMoveQueue, {
A = A,
B = B,
allowSwap = allowSwap,
allowCombine = allowCombine,
})
end
end
---@return Barotrauma.Item[], string? ---@return Barotrauma.Item[], string?
local function getOpenContainers() local function getOpenContainers()
@@ -23,7 +180,9 @@ end
---@return Barotrauma.Item, string? ---@return Barotrauma.Item, string?
local function getFirstOpenContainer() local function getFirstOpenContainer()
local containers, err = getOpenContainers() local containers, err = getOpenContainers()
---@diagnostic disable-next-line: return-type-mismatch
if err then return nil, err end if err then return nil, err end
---@diagnostic disable-next-line: return-type-mismatch
if #containers == 0 then return nil, "No open containers" end if #containers == 0 then return nil, "No open containers" end
return containers[1], nil return containers[1], nil
end end
@@ -32,227 +191,261 @@ end
-- And enqueueItem calls enqueueInventory -- And enqueueItem calls enqueueInventory
-- So unless we define them both before using them -- So unless we define them both before using them
-- We will get an error saying either is undefined -- We will get an error saying either is undefined
-- TODO: Rework these enqueue functions to accept a params object
-- That will house all optional parameters
-- And in that include recurse boolean
---@class ItemRefs
---@field item Barotrauma.Item
---@field inventory Barotrauma.Inventory
---@field slot Barotrauma.Inventory.ItemSlot
---@field slotIndex1 number
---@class EnqueueOptions
---@field itemQueue Barotrauma.Item[]
---@field slotQueue Barotrauma.Inventory.ItemSlot[]
---@field inventoryQueue Barotrauma.Inventory[]
---@field itemPredicate fun(item: Barotrauma.Item, itemRef: ItemRefs): boolean
---@field slotPredicate fun(slot: Barotrauma.Inventory.ItemSlot, itemRef: ItemRefs): boolean
---@field inventoryPredicate fun(inventory: Barotrauma.Inventory, itemRef: ItemRefs): boolean
---@field loadRefs boolean
---@field itemRef ItemRefs
---@field recurse boolean
---@param options EnqueueOptions
---@return EnqueueOptions
local function ensureOptionsDefaults(options)
options = options or {}
options.itemQueue = options.itemQueue or {}
options.slotQueue = options.slotQueue or {}
options.inventoryQueue = options.inventoryQueue or {}
options.itemPredicate = options.itemPredicate or function() return true end
options.slotPredicate = options.slotPredicate or function() return true end
options.inventoryPredicate = options.inventoryPredicate or function() return true end
options.loadRefs = options.loadRefs or false
options.itemRef = options.itemRef or nil
options.recurse = options.recurse or true
return options
end
local enqueueItem local enqueueItem
local enqueueSlot local enqueueSlot
local enqueueInventory local enqueueInventory
local enqueuePlayerItems
local enqueueOpenContainers local enqueueOpenContainers
local allPlayerItems local enqueueSubmarineItems
local allSubmarineItems local enqueueAllOwnedItems
local allOwnedItems
local _
---@alias FilterPredicate fun(item: Barotrauma.Item, inventoryRef?: Barotrauma.ItemInventory, slotRef: Barotrauma.ItemInventory.Slot): boolean do
---@param item Barotrauma.Item
---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueItem = function(item, options)
options = ensureOptionsDefaults(options)
if not item then return options.itemQueue, "No item" end
-- Loading refs is optional because it MAY have a performance impact local ok, stop = options.itemPredicate(item, options.itemRef)
---@param item Barotrauma.Item
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@param itemRef? ItemRefs
---@return Barotrauma.Item[], string?
enqueueItem = function(item, queue, predicate, loadRefs, itemRef)
queue = queue or {}
predicate = predicate or function() return true end
itemRef = itemRef or {}
-- 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, itemRef)
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
itemRef.item = item
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, loadRefs, itemRef)
else
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, itemRef)
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 itemRef? ItemRefs
---@return Barotrauma.Item[], string?
enqueueSlot = function(slot, queue, predicate, loadRefs, itemRef)
queue = queue or {}
predicate = predicate or function() return true end
itemRef = itemRef or {}
-- 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
itemRef.slot = slot
queue, err = enqueueItem(item, queue, predicate, loadRefs, itemRef)
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
---@param itemRef? ItemRefs
---@return Barotrauma.Item[], string?
enqueueInventory = function(inventory, queue, predicate, loadRefs, itemRef)
queue = queue or {}
predicate = predicate or function() return true end
itemRef = itemRef or {}
-- 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
itemRef.inventory = inventory
queue, err = enqueueSlot(slot, queue, predicate, loadRefs, itemRef)
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
local relevantPlayerInventorySlots = { 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, MyModGlobal.BAG_SLOT }
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@return Barotrauma.Item[], string?
allPlayerItems = function(queue, predicate, loadRefs)
queue = queue or {}
predicate = predicate or function() return true end
local character = Character.Controlled
if not character then return queue, "No character" end
local inventory = character.Inventory
if not inventory then return queue, "No inventory" end
for _, slotid in ipairs(relevantPlayerInventorySlots) do
local slot = inventory.slots[slotid]
local err
if not slot then goto continue end
if #slot.items == 0 then goto continue end
queue, err = enqueueSlot(slot, queue, predicate, loadRefs)
if err then return queue, err end
::continue::
end
return queue
end
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@param loadRefs? boolean
---@return Barotrauma.Item[], string?
enqueueOpenContainers = function(queue, predicate, loadRefs)
queue = queue or {}
predicate = predicate or function() return true end
local containers, err = getOpenContainers()
if err then return queue, err end
for _, container in ipairs(containers) do
local inventories = container.OwnInventories
if not inventories then goto continue end
for containerInventory in inventories do
queue, err = enqueueInventory(containerInventory, queue, predicate, loadRefs)
if err then return queue, err end
end
::continue::
end
return queue
end
---@param queue Barotrauma.Item[]
---@param predicate? FilterPredicate
---@return Barotrauma.Item[], string?
allSubmarineItems = function(queue, predicate)
queue = queue or {}
predicate = predicate or function() return true end
-- This only exists so predicate does not explode
-- Even if its empty
local itemRef = {}
local character = Character.Controlled
if not character then return queue, "No character" end
local submarine = character.Submarine
if not submarine then return queue, "No submarine" end
for item in submarine.GetItems(false) do
-- We do NOT want to call enqueueItem here because enqueueItem
-- Is recursive
-- And this call (GetItems) already gets all items
-- So we would be doing double the work (at best case)
-- It also means we won't have refs here which sucks
local ok, stop = predicate(item, itemRef)
if ok then if ok then
queue[#queue + 1] = item options.itemQueue[#options.itemQueue + 1] = item
end end
if stop then return queue, "Stop" end if stop then return options.itemQueue, "Stop" end
local err
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
if options.recurse then
if options.loadRefs then
options.itemRef.item = item
options.inventoryQueue, err = enqueueInventory(item.OwnInventory, options)
else
options.inventoryQueue, err = enqueueInventory(item.OwnInventory, options)
end
end
end
return options, err
end end
return queue ---@param slot Barotrauma.Inventory.ItemSlot
end ---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueSlot = function(slot, options)
options = ensureOptionsDefaults(options)
if not slot then return options, "No slot" end
if not slot.items then return options, "No items" end
---@param queue Barotrauma.Item[] local ok, stop = options.slotPredicate(slot, options.itemRef)
---@param predicate? FilterPredicate if ok then
---@param loadRefs? boolean options.slotQueue[#options.slotQueue + 1] = slot
---@return Barotrauma.Item[], string? end
allOwnedItems = function(queue, predicate, loadRefs) if stop then return options, "Stop" end
queue = queue or {}
predicate = predicate or function() return true end
local err for _, item in ipairs(slot.items) do
queue, err = allPlayerItems(queue, predicate, loadRefs) -- We redeclare err every iteration so it doesn't spill over
if err then return queue, err end local err
if options.loadRefs then
options.itemRef.slot = slot
options, err = enqueueItem(item, options)
else
options, err = enqueueItem(item, options)
end
if err then
return options, err
end
end
return options
end
queue, err = allSubmarineItems(queue, predicate) ---@param inventory Barotrauma.Inventory
if err then return queue, err end ---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueInventory = function(inventory, options)
options = ensureOptionsDefaults(options)
if not inventory then return options, "No inventory" end
if not inventory.slots then return options, "No slots" end
return queue local ok, stop = options.inventoryPredicate(inventory, options.itemRef)
if ok then
options.inventoryQueue[#options.inventoryQueue + 1] = inventory
end
if stop then return options, "Stop" end
for i, slot in ipairs(inventory.slots) do
local err
if options.loadRefs then
options.itemRef.inventory = inventory
options.itemRef.slot = slot
options.itemRef.slotIndex1 = i
options, err = enqueueSlot(slot, options)
else
options, err = enqueueSlot(slot, options)
end
if err then
return options, err
end
end
return options
end
local relevantPlayerInventorySlots = {
false,
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
}
---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueuePlayerItems = function(options)
options = ensureOptionsDefaults(options)
local character = Character.Controlled
if not character then return options, "No character" end
local inventory = character.Inventory
if not inventory then return options, "No inventory" end
options.loadRefs = true
options.itemPredicate = function(item)
if not item then return false end
local parentInventory = item.ParentInventory
if not parentInventory then return false end
if not parentInventory.Equals(inventory) then return false end
return true
end
options.slotPredicate = function(slot, itemRef)
if not slot then return false end
if itemRef.slotIndex1 and relevantPlayerInventorySlots[itemRef.slotIndex1] then
return true
end
return false
end
local err
options, err = enqueueInventory(inventory, options)
if err then return options, err end
return options
end
---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueOpenContainers = function(options)
options = ensureOptionsDefaults(options)
local containers, err = getOpenContainers()
if err then return options, err end
for _, container in ipairs(containers) do
local inventories = container.OwnInventories
if not inventories then goto continue end
for containerInventory in inventories do
options, err = enqueueInventory(containerInventory, options)
if err then return options, err end
end
::continue::
end
return options
end
---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueSubmarineItems = function(options)
options = ensureOptionsDefaults(options)
-- This only exists so predicate does not explode
-- Even if its empty
local itemRef = {}
local character = Character.Controlled
if not character then return options, "No character" end
local submarine = character.Submarine
if not submarine then return options, "No submarine" end
for item in submarine.GetItems(false) do
-- We do NOT want to call enqueueItem here because enqueueItem
-- Is recursive
-- And this call (GetItems) already gets all items
-- So we would be doing double the work (at best case)
-- It also means we won't have refs here which sucks
local ok, stop = options.itemPredicate(item, itemRef)
if ok then
options.itemQueue[#options.itemQueue + 1] = item
end
if stop then return options, "Stop" end
end
return options
end
---@param options EnqueueOptions
---@return EnqueueOptions, string?
enqueueAllOwnedItems = function(options)
options = ensureOptionsDefaults(options)
local err
options, err = enqueuePlayerItems(options)
if err then return options, err end
options, err = enqueueSubmarineItems(options)
if err then return options, err end
return options
end
end end
-- There is actually no need to recurse deep -- There is actually no need to recurse deep
@@ -260,8 +453,8 @@ end
-- And not an item in an item in the inventory -- And not an item in an item in the inventory
-- So in theory we only need to recurse 1 deep -- So in theory we only need to recurse 1 deep
---@param inventory Barotrauma.Inventory ---@param inventory Barotrauma.Inventory
---@param slots InventorySlot[] ---@param slots? InventorySlot[]
---@param depth number ---@param depth? number
---@return InventorySlot[], string? ---@return InventorySlot[], string?
local function getMouseoverSlots(inventory, slots, depth) local function getMouseoverSlots(inventory, slots, depth)
slots = slots or {} slots = slots or {}
@@ -269,7 +462,7 @@ local function getMouseoverSlots(inventory, slots, depth)
if depth > 1 then return slots, nil end if depth > 1 then return slots, nil end
local visualSlots = inventory.visualSlots local visualSlots = inventory.visualSlots
if not visualSlots then return nil, "Inventory has no visual slots" end if not visualSlots then return slots, "Inventory has no visual slots" end
for i, visualSlot in ipairs(visualSlots) do for i, visualSlot in ipairs(visualSlots) do
local item local item
@@ -305,11 +498,8 @@ local function getMouseoverSlots(inventory, slots, depth)
::mouseover:: ::mouseover::
if visualSlot:MouseOn() then if visualSlot:MouseOn() then
slots[#slots + 1] = { local inventorySlot = MyModGlobal.InventorySlot.new(inventory, i)
inventory = inventory, slots[#slots + 1] = inventorySlot
slotIndex = i,
slot = slot
}
end end
::continue:: ::continue::
@@ -320,15 +510,17 @@ end
---@return InventorySlot[], string? ---@return InventorySlot[], string?
local function getSlotsUnderCursor() local function getSlotsUnderCursor()
local slots = {}
-- 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, "No controlled character" end if not controlledCharacter then return slots, "No controlled character" end
local inventory = controlledCharacter.Inventory local inventory = controlledCharacter.Inventory
if not inventory then return nil, "No inventory" end if not inventory then return slots, "No inventory" end
local mouseoverSlots, err = getMouseoverSlots(inventory) local err
if err then return mouseoverSlots, err end slots, err = getMouseoverSlots(inventory, slots)
if err then return slots, err end
-- Even if we don't get them we're still fine -- Even if we don't get them we're still fine
local openContainers, _ = getOpenContainers() local openContainers, _ = getOpenContainers()
@@ -337,33 +529,28 @@ local function getSlotsUnderCursor()
for _, container in ipairs(openContainers) do for _, container in ipairs(openContainers) do
local containerInventories = container.OwnInventories local containerInventories = container.OwnInventories
for containerInventory in containerInventories do for containerInventory in containerInventories do
local slot
if not containerInventory or not containerInventory.visualSlots then if not containerInventory or not containerInventory.visualSlots then
MyModGlobal.debugPrint("Container inventory has no visual slots") MyModGlobal.debugPrint("Container inventory has no visual slots")
goto continue goto continue
end end
for i, visualSlot in ipairs(containerInventory.visualSlots) do for i, visualSlot in ipairs(containerInventory.visualSlots) do
if visualSlot:MouseOn() then if visualSlot:MouseOn() then
slot = containerInventory.slots[i] local inventorySlot = MyModGlobal.InventorySlot.new(containerInventory, i)
mouseoverSlots[#mouseoverSlots + 1] = { slots[#slots + 1] = inventorySlot
inventory = containerInventory,
slotIndex = i,
slot = slot
}
end end
end end
::continue:: ::continue::
end end
end end
return mouseoverSlots, nil return slots, nil
end end
---@return InventorySlot, string? ---@return InventorySlot, string?
local function getFirstSlotUnderCursor() local function getFirstSlotUnderCursor()
local slots, err = getSlotsUnderCursor() local slots, err = getSlotsUnderCursor()
if err then return nil, err end if err then return slots, err end
if #slots == 0 then return nil, "No slots found under cursor" end if #slots == 0 then return slots, "No slots found under cursor" end
for _, slot in ipairs(slots) do for _, slot in ipairs(slots) do
if slot.slot.items and #slot.slot.items > 0 then if slot.slot.items and #slot.slot.items > 0 then
return slot return slot
@@ -376,12 +563,13 @@ return {
enqueueItem = enqueueItem, enqueueItem = enqueueItem,
enqueueSlot = enqueueSlot, enqueueSlot = enqueueSlot,
enqueueInventory = enqueueInventory, enqueueInventory = enqueueInventory,
enqueueAllPlayerItems = allPlayerItems, enqueuePlayerItems = enqueuePlayerItems,
enqueueAllSubmarineItems = allSubmarineItems, enqueueSubmarineItems = enqueueSubmarineItems,
enqueueAllOwnedItems = allOwnedItems, enqueueAllOwnedItems = enqueueAllOwnedItems,
enqueueOpenContainers = enqueueOpenContainers, enqueueOpenContainers = enqueueOpenContainers,
getOpenContainers = getOpenContainers, getOpenContainers = getOpenContainers,
getFirstOpenContainer = getFirstOpenContainer, getFirstOpenContainer = getFirstOpenContainer,
getSlotsUnderCursor = getSlotsUnderCursor, getSlotsUnderCursor = getSlotsUnderCursor,
getFirstSlotUnderCursor = getFirstSlotUnderCursor, getFirstSlotUnderCursor = getFirstSlotUnderCursor,
enqueueMove = enqueueMove,
} }