From 63573465443dfa6a052f08342908ffa28126813c Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sat, 29 Mar 2025 22:47:13 +0100 Subject: [PATCH] Implement stacking from open containers --- QuickStackToBag/Lua/Autorun/init.lua | 143 +++------------------------ 1 file changed, 13 insertions(+), 130 deletions(-) diff --git a/QuickStackToBag/Lua/Autorun/init.lua b/QuickStackToBag/Lua/Autorun/init.lua index fbc3fde..0e9cf36 100644 --- a/QuickStackToBag/Lua/Autorun/init.lua +++ b/QuickStackToBag/Lua/Autorun/init.lua @@ -469,146 +469,25 @@ local function stackInventoryItems(inventory, itemTree) debugPrint("Completed stacking inventory items.") 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() debugPrint("Attempting to find open container...") - - local openContainer = nil - local hasVisibleInventory = false - - -- Method 1: Try to use Inventory.CurrentInventory or similar properties - 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 + for item in Item.ItemList do + ---@cast item Barotrauma.Item + if item and item.OwnInventory then + if item.OwnInventory.visualSlots and #item.OwnInventory.visualSlots > 0 then + return item.OwnInventory 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 debugPrint("No open container found") return nil 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 ---@param itemTree table ---@return table @@ -642,6 +521,10 @@ local function quickStackItems(character) local itemTree = buildItemTree(inventory, {}) itemTree = sortItemtreeBySlots(itemTree) stackInventoryItems(inventory, itemTree) + local openContainerInventory = getOpenContainer() + if openContainerInventory then + stackInventoryItems(openContainerInventory, itemTree) + end -- Find all containers in player inventory, including nested ones -- local containers = findAllContainers(inventory, {})