diff --git a/QuickStackToBag/Lua/Autorun/init.lua b/QuickStackToBag/Lua/Autorun/init.lua index 33ae36c..3d3ab96 100644 --- a/QuickStackToBag/Lua/Autorun/init.lua +++ b/QuickStackToBag/Lua/Autorun/init.lua @@ -1,4 +1,5 @@ if SERVER then return end +-- Docs: https://evilfactory.github.io/LuaCsForBarotrauma/lua-docs/manual/common-questions/ -- Register necessary types and make fields accessible LuaUserData.RegisterType("Barotrauma.Items.Components.ItemContainer+SlotRestrictions") @@ -184,7 +185,7 @@ local _ ---@param item Barotrauma.Item ---@param queue Barotrauma.Item[] ---@param predicate? fun(item: Barotrauma.Item): boolean ----@return Barotrauma.Item[], string +---@return Barotrauma.Item[], string? enqueueItem = function(item, queue, predicate) queue = queue or {} predicate = predicate or function() return true end @@ -202,10 +203,9 @@ enqueueItem = function(item, queue, predicate) end local ok, stop = predicate(item) if ok then - -- debugPrint(string.format("Enqueuing item: %s", item.Prefab.Identifier.Value)) queue[#queue + 1] = item end - if stop then return queue, nil end + if stop then return queue, "Stop" end -- debugPrint(string.format("Item enqueued. Current queue size: %d", #queue)) return queue, nil end @@ -213,21 +213,21 @@ end ---@param slot Barotrauma.ItemInventory.Slot ---@param queue Barotrauma.Item[] ---@param predicate? fun(item: Barotrauma.Item): boolean ----@return Barotrauma.Item[], string +---@return Barotrauma.Item[], string? enqueueSlot = function(slot, queue, predicate) queue = queue or {} predicate = predicate or function() return true end -- debugPrint(string.format("Enqueuing slot with %d items.", #slot.items)) -- We don't want to shadow queue - -- local err + local err -- If the slot is empty there's nothing to iterate -- And we will naturally return queue as is for _, item in ipairs(slot.items) do -- Only the final leaf nodes decide upon the predicate - queue, _ = enqueueItem(item, queue, predicate) - -- if err then - -- debugPrint(string.format("Error enqueuing item: %s", err)) - -- end + queue, err = enqueueItem(item, queue, predicate) + if err then + return queue, err + end end -- debugPrint(string.format("Finished enqueuing slot. Current queue size: %d", #queue)) return queue @@ -236,18 +236,18 @@ end ---@param inventory Barotrauma.ItemInventory ---@param queue Barotrauma.Item[] ---@param predicate? fun(item: Barotrauma.Item): boolean ----@return Barotrauma.Item[] +---@return Barotrauma.Item[], string? enqueueInventory = function(inventory, queue, predicate) queue = queue or {} predicate = predicate or function() return true end -- debugPrint(string.format("Enqueuing inventory with %d slots.", #inventory.slots)) - -- local err + local err for _, slot in ipairs(inventory.slots) do -- Only the final leaf nodes decide upon the predicate - queue, _ = enqueueSlot(slot, queue, predicate) - -- if err then - -- debugPrint(string.format("Error enqueuing slot: %s", err)) - -- end + queue, err = enqueueSlot(slot, queue, predicate) + if err then + return queue, err + end end -- debugPrint(string.format("Finished enqueuing inventory. Current queue size: %d", #queue)) return queue @@ -539,8 +539,9 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab recipe, err = getSelectedRecipeRequirements(fabricator.fabricator) if err then print(string.format("Error getting selected recipe requirements: %s", err)) + return end - DumpTable(recipe) + -- DumpTable(recipe) -- TODO: Maybe make it so every press cycles the input -- For recipes that have multiple prefabs @@ -549,7 +550,7 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab local toFind = recipe.requiredItems ---@type Barotrauma.Item[] local toGet = {} - ---@type fun(item: Barotrauma.Item): boolean + ---@type fun(item: Barotrauma.Item): boolean, boolean local filter = function(item) local found = false -- toFind are all items we need to find @@ -561,19 +562,20 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab -- debugPrint(string.format("That'll do %s %s", item.Prefab.Identifier.Value, prefab)) toGet[#toGet + 1] = item itemInfo.amount = itemInfo.amount - 1 - found = false + found = true break end end if itemInfo.amount <= 0 then toFind[i] = nil end if found then break end end - -- debugPrint(string.format("Found %s %s", item.Prefab.Identifier.Value, tostring(found))) + -- debugPrint(string.format("Found %s %s", item.Prefab.Identifier.Value, tostring(#toFind))) return found, #toFind == 0 end -- DumpTable(toGet) local items = enqueueInventory(bagItem.OwnInventory, {}, filter) + -- DumpTable(items) -- TODO: This might explode... Oh well? local inputInventory = fabricator.item.OwnInventories[1] for iinventory in fabricator.item.OwnInventories do @@ -587,7 +589,7 @@ Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptab local previous = nil for _, item in ipairs(items) do if previous ~= item.Prefab.Identifier then slot = slot + 1 end - -- inputInventory.TryPutItem(item, slot, false, true, nil) + inputInventory.TryPutItem(item, slot, false, true, nil) previous = item.Prefab.Identifier end DumpTable(items) @@ -644,45 +646,45 @@ end -- Example: Add a key binding to buy all items in the current store -- when the 'B' key is pressed Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable) - if PlayerInput.KeyHit(CONFIG.MAX_BUY) then - local cargoManager = Game.GameSession.Campaign.CargoManager - if not cargoManager then - print("No cargo manager available") - return + if not PlayerInput.KeyHit(CONFIG.MAX_BUY) then return end + + local cargoManager = Game.GameSession.Campaign.CargoManager + if not cargoManager then + print("No cargo manager available") + return + end + + local stores, err = getCurrentStore() + if err then + print(string.format("Error getting current store: %s", err)) + return + end + + for _, store in ipairs(stores) do + local toAdd = {} + -- Get items available at the store + local items = cargoManager:GetBuyCrateItems(store) + for item in items do + -- We have already added this many of item + toAdd[item.ItemPrefab.Identifier.Value] = { + quantity = -item.Quantity, + prefab = item.ItemPrefab -- Store the ItemPrefab object + } + end + for item in store.Stock do + -- So if we add the total amount available + -- We get the amount we have to add to buy entire stock + local idValue = item.ItemPrefab.Identifier.Value + if toAdd[idValue] then + toAdd[idValue].quantity = toAdd[idValue].quantity + item.Quantity + end end - local stores, err = getCurrentStore() - if err then - print(string.format("Error getting current store: %s", err)) - return - end - - for _, store in ipairs(stores) do - local toAdd = {} - -- Get items available at the store - local items = cargoManager:GetBuyCrateItems(store) - for item in items do - -- We have already added this many of item - toAdd[item.ItemPrefab.Identifier.Value] = { - quantity = -item.Quantity, - prefab = item.ItemPrefab -- Store the ItemPrefab object - } - end - for item in store.Stock do - -- So if we add the total amount available - -- We get the amount we have to add to buy entire stock - local idValue = item.ItemPrefab.Identifier.Value - if toAdd[idValue] then - toAdd[idValue].quantity = toAdd[idValue].quantity + item.Quantity - end - end - - for idValue, info in pairs(toAdd) do - if info.quantity > 0 then - print(string.format("Adding %d of %s to the buy crate", info.quantity, idValue)) - -- Use the stored ItemPrefab object, not the string identifier - cargoManager:ModifyItemQuantityInBuyCrate(store.Identifier, info.prefab, info.quantity) - end + for idValue, info in pairs(toAdd) do + if info.quantity > 0 then + print(string.format("Adding %d of %s to the buy crate", info.quantity, idValue)) + -- Use the stored ItemPrefab object, not the string identifier + cargoManager:ModifyItemQuantityInBuyCrate(store.Identifier, info.prefab, info.quantity) end end end