|
|
|
@@ -1,3 +1,16 @@
|
|
|
|
|
-- luacheck: globals Character MyModGlobal
|
|
|
|
|
-- luacheck: max line length 420
|
|
|
|
|
|
|
|
|
|
---@class ItemRefs
|
|
|
|
|
---@field item Barotrauma.Item
|
|
|
|
|
---@field inventory Barotrauma.ItemInventory
|
|
|
|
|
---@field slot Barotrauma.ItemInventory.Slot
|
|
|
|
|
|
|
|
|
|
---@class InventorySlot
|
|
|
|
|
---@field slot Barotrauma.ItemSlot
|
|
|
|
|
---@field inventory Barotrauma.ItemInventory
|
|
|
|
|
---@field slotIndex number
|
|
|
|
|
|
|
|
|
|
-- We got to do this shit because enqueueInventory calls enqueueItem
|
|
|
|
|
-- And enqueueItem calls enqueueInventory
|
|
|
|
|
-- So unless we define them both before using them
|
|
|
|
@@ -5,6 +18,9 @@
|
|
|
|
|
local enqueueItem
|
|
|
|
|
local enqueueSlot
|
|
|
|
|
local enqueueInventory
|
|
|
|
|
local allPlayerItems
|
|
|
|
|
local allSubmarineItems
|
|
|
|
|
local allOwnedItems
|
|
|
|
|
local _
|
|
|
|
|
|
|
|
|
|
---@alias FilterPredicate fun(item: Barotrauma.Item, inventoryRef?: Barotrauma.ItemInventory, slotRef: Barotrauma.ItemInventory.Slot): boolean
|
|
|
|
@@ -15,19 +31,19 @@ local _
|
|
|
|
|
---@param queue Barotrauma.Item[]
|
|
|
|
|
---@param predicate? FilterPredicate
|
|
|
|
|
---@param loadRefs? boolean
|
|
|
|
|
---@param slotRef? Barotrauma.ItemInventory.Slot
|
|
|
|
|
---@param inventoryRef? Barotrauma.ItemInventory
|
|
|
|
|
---@param itemRef? ItemRefs
|
|
|
|
|
---@return Barotrauma.Item[], string?
|
|
|
|
|
enqueueItem = function(item, queue, predicate, loadRefs, inventoryRef, slotRef)
|
|
|
|
|
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, inventoryRef, slotRef)
|
|
|
|
|
local ok, stop = predicate(item, itemRef)
|
|
|
|
|
if ok then
|
|
|
|
|
queue[#queue + 1] = item
|
|
|
|
|
end
|
|
|
|
@@ -38,9 +54,10 @@ enqueueItem = function(item, queue, predicate, loadRefs, inventoryRef, slotRef)
|
|
|
|
|
-- So inventrorY should be fine here
|
|
|
|
|
-- debugPrint("Item has its own inventory, enqueuing inventory...")
|
|
|
|
|
if loadRefs then
|
|
|
|
|
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, loadRefs)
|
|
|
|
|
itemRef.item = item
|
|
|
|
|
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, loadRefs, itemRef)
|
|
|
|
|
else
|
|
|
|
|
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate)
|
|
|
|
|
queue, _ = enqueueInventory(item.OwnInventory, queue, predicate, itemRef)
|
|
|
|
|
end
|
|
|
|
|
-- if err then
|
|
|
|
|
-- debugPrint(string.format("Error enqueuing inventory: %s", err))
|
|
|
|
@@ -54,11 +71,12 @@ end
|
|
|
|
|
---@param queue Barotrauma.Item[]
|
|
|
|
|
---@param predicate? FilterPredicate
|
|
|
|
|
---@param loadRefs? boolean
|
|
|
|
|
---@param inventoryRef? Barotrauma.ItemInventory
|
|
|
|
|
---@param itemRef? ItemRefs
|
|
|
|
|
---@return Barotrauma.Item[], string?
|
|
|
|
|
enqueueSlot = function(slot, queue, predicate, loadRefs, inventoryRef)
|
|
|
|
|
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
|
|
|
|
@@ -70,7 +88,8 @@ enqueueSlot = function(slot, queue, predicate, loadRefs, inventoryRef)
|
|
|
|
|
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)
|
|
|
|
|
itemRef.slot = slot
|
|
|
|
|
queue, err = enqueueItem(item, queue, predicate, loadRefs, itemRef)
|
|
|
|
|
else
|
|
|
|
|
queue, err = enqueueItem(item, queue, predicate)
|
|
|
|
|
end
|
|
|
|
@@ -86,10 +105,12 @@ end
|
|
|
|
|
---@param queue Barotrauma.Item[]
|
|
|
|
|
---@param predicate? FilterPredicate
|
|
|
|
|
---@param loadRefs? boolean
|
|
|
|
|
---@param itemRef? ItemRefs
|
|
|
|
|
---@return Barotrauma.Item[], string?
|
|
|
|
|
enqueueInventory = function(inventory, queue, predicate, loadRefs)
|
|
|
|
|
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
|
|
|
|
@@ -98,7 +119,8 @@ enqueueInventory = function(inventory, queue, predicate, loadRefs)
|
|
|
|
|
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)
|
|
|
|
|
itemRef.inventory = inventory
|
|
|
|
|
queue, err = enqueueSlot(slot, queue, predicate, loadRefs, itemRef)
|
|
|
|
|
else
|
|
|
|
|
queue, err = enqueueSlot(slot, queue, predicate)
|
|
|
|
|
end
|
|
|
|
@@ -110,8 +132,219 @@ enqueueInventory = function(inventory, queue, predicate, loadRefs)
|
|
|
|
|
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
|
|
|
|
|
---@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
|
|
|
|
|
queue[#queue + 1] = item
|
|
|
|
|
end
|
|
|
|
|
if stop then return queue, "Stop" end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return queue
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@param queue Barotrauma.Item[]
|
|
|
|
|
---@param predicate? FilterPredicate
|
|
|
|
|
---@param loadRefs? boolean
|
|
|
|
|
---@return Barotrauma.Item[], string?
|
|
|
|
|
allOwnedItems = function(queue, predicate, loadRefs)
|
|
|
|
|
queue = queue or {}
|
|
|
|
|
predicate = predicate or function() return true end
|
|
|
|
|
|
|
|
|
|
local err
|
|
|
|
|
queue, err = allPlayerItems(queue, predicate, loadRefs)
|
|
|
|
|
if err then return queue, err end
|
|
|
|
|
|
|
|
|
|
queue, err = allSubmarineItems(queue, predicate)
|
|
|
|
|
if err then return queue, err end
|
|
|
|
|
|
|
|
|
|
return queue
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@return Barotrauma.Item[], string?
|
|
|
|
|
local function getOpenContainers()
|
|
|
|
|
local controlledCharacter = Character.Controlled
|
|
|
|
|
if not controlledCharacter then return {}, "No controlled character" end
|
|
|
|
|
local selectedItem = controlledCharacter.SelectedItem
|
|
|
|
|
if not selectedItem then return {}, "No selected item" end
|
|
|
|
|
return { selectedItem }, nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@return Barotrauma.Item, string?
|
|
|
|
|
local function getFirstOpenContainer()
|
|
|
|
|
local containers, err = getOpenContainers()
|
|
|
|
|
if err then return nil, err end
|
|
|
|
|
if #containers == 0 then return nil, "No open containers" end
|
|
|
|
|
return containers[1], nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- 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
|
|
|
|
|
|
|
|
|
|
---@return InventorySlot[], string?
|
|
|
|
|
local function getSlotsUnderCursor()
|
|
|
|
|
-- 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
|
|
|
|
|
|
|
|
|
|
-- Even if we don't get them we're still fine
|
|
|
|
|
local openContainers, _ = getOpenContainers()
|
|
|
|
|
-- if err then return mouseoverSlots, err end
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
---@return InventorySlot, string?
|
|
|
|
|
local function getFirstSlotUnderCursor()
|
|
|
|
|
local slots, err = getSlotsUnderCursor()
|
|
|
|
|
if err then return nil, err end
|
|
|
|
|
if #slots == 0 then return nil, "No slots found under cursor" end
|
|
|
|
|
return slots[1], nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
enqueueItem = enqueueItem,
|
|
|
|
|
enqueueSlot = enqueueSlot,
|
|
|
|
|
enqueueInventory = enqueueInventory
|
|
|
|
|
enqueueInventory = enqueueInventory,
|
|
|
|
|
enqueueAllPlayerItems = allPlayerItems,
|
|
|
|
|
enqueueAllSubmarineItems = allSubmarineItems,
|
|
|
|
|
enqueueAllOwnedItems = allOwnedItems,
|
|
|
|
|
getOpenContainers = getOpenContainers,
|
|
|
|
|
getFirstOpenContainer = getFirstOpenContainer,
|
|
|
|
|
getSlotsUnderCursor = getSlotsUnderCursor,
|
|
|
|
|
getFirstSlotUnderCursor = getFirstSlotUnderCursor,
|
|
|
|
|
}
|
|
|
|
|