From 7115a9fe362f7643e3b45837899cefaf22a98e23 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sat, 29 Mar 2025 19:30:36 +0100 Subject: [PATCH] Fix goto disasters --- QuickStackToBag/Lua/Autorun/init.lua | 180 ++++++++++++++------------- 1 file changed, 93 insertions(+), 87 deletions(-) diff --git a/QuickStackToBag/Lua/Autorun/init.lua b/QuickStackToBag/Lua/Autorun/init.lua index f3b0348..995ca53 100644 --- a/QuickStackToBag/Lua/Autorun/init.lua +++ b/QuickStackToBag/Lua/Autorun/init.lua @@ -3,22 +3,22 @@ if SERVER then return end -- Register necessary types and make fields accessible LuaUserData.RegisterType("Barotrauma.Items.Components.ItemContainer+SlotRestrictions") LuaUserData.RegisterType( -'System.Collections.Immutable.ImmutableArray`1[[Barotrauma.Items.Components.ItemContainer+SlotRestrictions, Barotrauma]]') + 'System.Collections.Immutable.ImmutableArray`1[[Barotrauma.Items.Components.ItemContainer+SlotRestrictions, Barotrauma]]') LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.Items.Components.ItemContainer'], 'slotRestrictions') LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.ItemInventory'], 'slots') LuaUserData.MakeFieldAccessible(Descriptors["Barotrauma.CharacterInventory"], "slots") -- Configuration local CONFIG = { - TRIGGER_KEY = Keys.F, -- Key to press for quick stacking - BAG_TAGS = { "container", "cargocontainer" }, -- Tags that identify bags/containers - MAX_ITEMS_TO_PROCESS = 100, -- Safety limit to prevent infinite loops - PREFER_EXISTING_STACKS = true, -- Prefer stacking into existing item stacks - CHECK_ALL_CONTAINERS = true, -- Check all containers in inventory, not just bag slot - PRIMARY_BAG_SLOT = 8, -- Slot number for the primary bag (typically slot 8) - SKIP_HAND_SLOTS = true, -- Skip hand slots when processing items - HAND_SLOTS = { 6, 7 }, -- Slot numbers for hands (typically slots 6 and 7) - SKIP_DIVING_GEAR = true, -- Skip diving gear when processing items + TRIGGER_KEY = Keys.F, -- Key to press for quick stacking + BAG_TAGS = { "container", "cargocontainer" }, -- Tags that identify bags/containers + MAX_ITEMS_TO_PROCESS = 100, -- Safety limit to prevent infinite loops + PREFER_EXISTING_STACKS = true, -- Prefer stacking into existing item stacks + CHECK_ALL_CONTAINERS = true, -- Check all containers in inventory, not just bag slot + PRIMARY_BAG_SLOT = 8, -- Slot number for the primary bag (typically slot 8) + SKIP_HAND_SLOTS = true, -- Skip hand slots when processing items + HAND_SLOTS = { 6, 7 }, -- Slot numbers for hands (typically slots 6 and 7) + SKIP_DIVING_GEAR = true, -- Skip diving gear when processing items DIVING_GEAR_TAGS = { "divingsuit", "divingmask", "oxygensource" } -- Tags for diving gear } @@ -62,7 +62,7 @@ local function findContainersInInventory(character) if CONFIG.CHECK_ALL_CONTAINERS then for slotIndex, slot in ipairs(inventory.slots) do -- Skip the primary bag slot as we already processed it - if slotIndex == CONFIG.PRIMARY_BAG_SLOT then goto continue end + if slotIndex == CONFIG.PRIMARY_BAG_SLOT then goto continueSlot end -- Skip hand slots if configured to do so if CONFIG.SKIP_HAND_SLOTS then @@ -73,7 +73,7 @@ local function findContainersInInventory(character) break end end - if isHandSlot then goto continue end + if isHandSlot then goto continueSlot end end for _, item in ipairs(slot.items) do @@ -82,7 +82,7 @@ local function findContainersInInventory(character) end end - ::continue:: + ::continueSlot:: end end @@ -124,88 +124,94 @@ local function tryStackItemInSlot(container, sourceItem, slotIndex) return false end +-- Function to process a single inventory slot +local function processInventorySlot(playerInv, slotIndex, containers, processedCount, stackedCount) + -- Check if this slot should be skipped (hand slots) + if CONFIG.SKIP_HAND_SLOTS then + for _, handSlot in ipairs(CONFIG.HAND_SLOTS) do + if slotIndex == handSlot then + return processedCount, stackedCount + end + end + end + + local slot = playerInv.slots[slotIndex] + if not slot then return processedCount, stackedCount end + + -- Process items in the slot + for i = #slot.items, 1, -1 do -- Iterate backwards to safely remove + local item = slot.items[i] + local success = false + + -- Skip containers themselves + if isContainer(item) then goto nextItem end + + -- Skip diving gear if configured to do so + if isDivingGear(item) then goto nextItem end + + processedCount = processedCount + 1 + if processedCount > CONFIG.MAX_ITEMS_TO_PROCESS then + print("QuickStack: Safety limit reached") + return processedCount, stackedCount + end + + -- Try each container in order + for _, container in ipairs(containers) do + local containerInv = container.OwnInventory + if not containerInv then goto nextContainer end + + -- First try to stack with existing stacks if configured to do so + if CONFIG.PREFER_EXISTING_STACKS then + for bagSlotIndex = 0, #containerInv.slots - 1 do + for _, containerItem in ipairs(containerInv.slots[bagSlotIndex + 1].items) do + if canStackWith(containerItem, item) then + success = tryStackItemInSlot(containerInv, item, bagSlotIndex) + if success then break end + end + end + if success then break end + end + end + + -- If not stacked yet, try any valid slot + if not success then + for bagSlotIndex = 0, #containerInv.slots - 1 do + success = tryStackItemInSlot(containerInv, item, bagSlotIndex) + if success then break end + end + end + + if success then + stackedCount = stackedCount + 1 + break -- Stop trying containers if we succeeded + end + + ::nextContainer:: + end + + ::nextItem:: + end + + return processedCount, stackedCount +end + -- Function to quick stack items into containers local function quickStackToContainers(character, containers) - if not character or #containers == 0 then return end + if not character or #containers == 0 then return 0 end local playerInv = character.Inventory local processedCount = 0 local stackedCount = 0 - -- Process inventory slots + -- Process each inventory slot for slotIndex = 1, #playerInv.slots do - -- Skip hand slots if configured to do so - if CONFIG.SKIP_HAND_SLOTS then - local isHandSlot = false - for _, handSlot in ipairs(CONFIG.HAND_SLOTS) do - if slotIndex == handSlot then - isHandSlot = true - break - end - end - if isHandSlot then goto continue end - end - - local slot = playerInv.slots[slotIndex] - if not slot then goto continue end - - -- Process items in the slot - for i = #slot.items, 1, -1 do -- Iterate backwards to safely remove - local item = slot.items[i] - -- Declare success variable outside any potential goto jumps - local success = false - - -- Skip containers themselves - if isContainer(item) then goto nextItem end - - -- Skip diving gear if configured to do so - if isDivingGear(item) then goto nextItem end - - processedCount = processedCount + 1 - if processedCount > CONFIG.MAX_ITEMS_TO_PROCESS then - print("QuickStack: Safety limit reached") - return stackedCount - end - - -- Try to stack the item into the containers - -- Try each container in order - for _, container in ipairs(containers) do - local containerInv = container.OwnInventory - if not containerInv then goto nextContainer end - - -- First try to stack with existing stacks if configured to do so - if CONFIG.PREFER_EXISTING_STACKS then - for bagSlotIndex = 0, #containerInv.slots - 1 do - for _, containerItem in ipairs(containerInv.slots[bagSlotIndex + 1].items) do - if canStackWith(containerItem, item) then - success = tryStackItemInSlot(containerInv, item, bagSlotIndex) - if success then break end - end - end - if success then break end - end - end - - -- If not stacked yet, try any valid slot - if not success then - for bagSlotIndex = 0, #containerInv.slots - 1 do - success = tryStackItemInSlot(containerInv, item, bagSlotIndex) - if success then break end - end - end - - if success then - stackedCount = stackedCount + 1 - break -- Stop trying containers if we succeeded - end - - ::nextContainer:: - end - - ::nextItem:: - end - - ::continue:: + processedCount, stackedCount = processInventorySlot( + playerInv, + slotIndex, + containers, + processedCount, + stackedCount + ) end return stackedCount