Implement stacking from open containers
This commit is contained in:
@@ -469,146 +469,25 @@ local function stackInventoryItems(inventory, itemTree)
|
|||||||
debugPrint("Completed stacking inventory items.")
|
debugPrint("Completed stacking inventory items.")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Find the currently open container - improved version
|
-- This is a bit fucking sucky.....
|
||||||
|
-- But I really don't know better
|
||||||
|
-- Maybe it will be fine...
|
||||||
|
---@return Barotrauma.ItemInventory
|
||||||
local function getOpenContainer()
|
local function getOpenContainer()
|
||||||
debugPrint("Attempting to find open container...")
|
debugPrint("Attempting to find open container...")
|
||||||
|
for item in Item.ItemList do
|
||||||
local openContainer = nil
|
---@cast item Barotrauma.Item
|
||||||
local hasVisibleInventory = false
|
if item and item.OwnInventory then
|
||||||
|
if item.OwnInventory.visualSlots and #item.OwnInventory.visualSlots > 0 then
|
||||||
-- Method 1: Try to use Inventory.CurrentInventory or similar properties
|
return item.OwnInventory
|
||||||
pcall(function()
|
|
||||||
if Inventory and Inventory.CurrentContainer and Inventory.CurrentContainer.Owner then
|
|
||||||
openContainer = Inventory.CurrentContainer.Owner
|
|
||||||
hasVisibleInventory = true
|
|
||||||
debugPrint("Found open container via CurrentContainer: " .. openContainer.Name)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
if hasVisibleInventory and openContainer then return openContainer end
|
|
||||||
|
|
||||||
-- Method 2: Check if Inventory.OpenInventories exists and has entries
|
|
||||||
pcall(function()
|
|
||||||
if Inventory and Inventory.OpenInventories and #Inventory.OpenInventories > 0 then
|
|
||||||
-- Get the last opened inventory
|
|
||||||
for _, inv in ipairs(Inventory.OpenInventories) do
|
|
||||||
if inv and inv.Owner and inv.Owner ~= Character.Controlled then
|
|
||||||
openContainer = inv.Owner
|
|
||||||
hasVisibleInventory = true
|
|
||||||
debugPrint("Found open container via OpenInventories: " .. openContainer.Name)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
|
||||||
|
|
||||||
if hasVisibleInventory and openContainer then return openContainer end
|
|
||||||
|
|
||||||
-- Method 3: Check if currently selected item is interacting with a container
|
|
||||||
pcall(function()
|
|
||||||
if Character.Controlled and Character.Controlled.SelectedItem then
|
|
||||||
local selectedItem = Character.Controlled.SelectedItem
|
|
||||||
-- Check if selected item is interacting with something
|
|
||||||
if selectedItem.InteractingWith and selectedItem.InteractingWith.OwnInventory and
|
|
||||||
selectedItem.InteractingWith ~= Character.Controlled then
|
|
||||||
openContainer = selectedItem.InteractingWith
|
|
||||||
hasVisibleInventory = true
|
|
||||||
debugPrint("Found open container via current interaction: " .. openContainer.Name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
if hasVisibleInventory and openContainer then return openContainer end
|
|
||||||
|
|
||||||
-- For safety, add a visual check - only return a container if it has a visible UI element
|
|
||||||
if openContainer then
|
|
||||||
-- Verify this container actually has a visible UI
|
|
||||||
local isVisible = false
|
|
||||||
|
|
||||||
pcall(function()
|
|
||||||
-- Common method to check if inventory is visible - look for visual components
|
|
||||||
if openContainer.OwnInventory and openContainer.OwnInventory.visualSlots and
|
|
||||||
#openContainer.OwnInventory.visualSlots > 0 then
|
|
||||||
isVisible = true
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
if not isVisible then
|
|
||||||
debugPrint("Container found but not visibly open in UI: " .. openContainer.Name)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
debugPrint("No open container found")
|
debugPrint("No open container found")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function to stack from open container to player containers
|
|
||||||
local function stackFromOpenContainer(character, playerContainers, openContainer)
|
|
||||||
if not character or not openContainer or not openContainer.OwnInventory then return 0 end
|
|
||||||
|
|
||||||
debugPrint("Stacking from open container: " .. openContainer.Name)
|
|
||||||
|
|
||||||
local itemsMoved = 0
|
|
||||||
local openContainerInv = openContainer.OwnInventory
|
|
||||||
|
|
||||||
-- Create a cache of processable items to avoid redundant checks
|
|
||||||
local itemsToProcess = {}
|
|
||||||
local processedIdentifiers = {}
|
|
||||||
|
|
||||||
-- Process each slot in the open container
|
|
||||||
for slotIndex = 0, #openContainerInv.slots - 1 do
|
|
||||||
local slot = openContainerInv.slots[slotIndex + 1]
|
|
||||||
|
|
||||||
-- Process items in the slot
|
|
||||||
for i = #slot.items, 1, -1 do
|
|
||||||
local item = slot.items[i]
|
|
||||||
local identifierValue = item.Prefab.Identifier.Value
|
|
||||||
|
|
||||||
-- Skip container items
|
|
||||||
if item.OwnInventory then
|
|
||||||
debugPrint("Skipping container item: " .. item.Name)
|
|
||||||
goto nextItem
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Skip if we've already processed an item of this type
|
|
||||||
if processedIdentifiers[identifierValue] then
|
|
||||||
debugPrint("Already processed items of type: " .. identifierValue .. " from open container")
|
|
||||||
goto nextItem
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(itemsToProcess, {
|
|
||||||
item = item,
|
|
||||||
slotIndex = slotIndex
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Mark identifier as scheduled for processing
|
|
||||||
processedIdentifiers[identifierValue] = true
|
|
||||||
|
|
||||||
::nextItem::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Now process the collected items - this greatly reduces redundant container checks
|
|
||||||
for _, itemData in ipairs(itemsToProcess) do
|
|
||||||
local item = itemData.item
|
|
||||||
|
|
||||||
debugPrint("Processing item from container: " .. item.Name)
|
|
||||||
|
|
||||||
-- Try to move the item to each player container
|
|
||||||
for _, container in ipairs(playerContainers) do
|
|
||||||
debugPrint("Trying to stack " .. item.Name .. " into " .. container.Name)
|
|
||||||
if moveItemToContainer(item, container.OwnInventory) then
|
|
||||||
debugPrint("Stacked " .. item.Name .. " from open container into " .. container.Name)
|
|
||||||
itemsMoved = itemsMoved + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return itemsMoved
|
|
||||||
end
|
|
||||||
|
|
||||||
-- We would like to fill larger stacks first
|
-- We would like to fill larger stacks first
|
||||||
---@param itemTree table<string, ItemLocation[]>
|
---@param itemTree table<string, ItemLocation[]>
|
||||||
---@return table<string, ItemLocation[]>
|
---@return table<string, ItemLocation[]>
|
||||||
@@ -642,6 +521,10 @@ local function quickStackItems(character)
|
|||||||
local itemTree = buildItemTree(inventory, {})
|
local itemTree = buildItemTree(inventory, {})
|
||||||
itemTree = sortItemtreeBySlots(itemTree)
|
itemTree = sortItemtreeBySlots(itemTree)
|
||||||
stackInventoryItems(inventory, itemTree)
|
stackInventoryItems(inventory, itemTree)
|
||||||
|
local openContainerInventory = getOpenContainer()
|
||||||
|
if openContainerInventory then
|
||||||
|
stackInventoryItems(openContainerInventory, itemTree)
|
||||||
|
end
|
||||||
|
|
||||||
-- Find all containers in player inventory, including nested ones
|
-- Find all containers in player inventory, including nested ones
|
||||||
-- local containers = findAllContainers(inventory, {})
|
-- local containers = findAllContainers(inventory, {})
|
||||||
|
|||||||
Reference in New Issue
Block a user