Also stack from open container
This commit is contained in:
@@ -2,20 +2,55 @@ 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]]')
|
||||
LuaUserData.RegisterType(
|
||||
'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")
|
||||
|
||||
-- Simple configuration
|
||||
local HAND_SLOTS = { 6, 7 }
|
||||
local PRIORITY_CONTAINERS = { "toolbelt", "backpack", "pouch" } -- Identifiers for priority containers
|
||||
local CONFIG = {
|
||||
TRIGGER_KEY = Keys.F, -- Key to press for quick stacking
|
||||
NESTED_CONTAINERS = true, -- Whether to include nested containers
|
||||
DEBUG_MODE = true, -- Print debug messages
|
||||
HAND_SLOTS = { 6, 7 }, -- Slot numbers for hands (typically slots 6 and 7)
|
||||
PRIORITY_CONTAINERS = { "toolbelt", "backpack", "pouch" } -- Priority order for containers
|
||||
}
|
||||
|
||||
-- MOD INFO
|
||||
local MOD_NAME = "Quick Stack To Containers"
|
||||
local MOD_VERSION = "1.1.0"
|
||||
|
||||
print(MOD_NAME .. " v" .. MOD_VERSION .. " loaded!")
|
||||
|
||||
-- Debugging helper function
|
||||
local function debugPrint(message)
|
||||
if CONFIG.DEBUG_MODE then
|
||||
print("[" .. MOD_NAME .. "] " .. message)
|
||||
end
|
||||
end
|
||||
|
||||
-- Show notification to player
|
||||
local function showNotification(message)
|
||||
-- Try different methods to show a message to the player
|
||||
debugPrint(message)
|
||||
|
||||
-- Method 1: Print to console (always works)
|
||||
print("[" .. MOD_NAME .. "] " .. message)
|
||||
|
||||
-- Method 2: Try to use GUIMessageBox if available
|
||||
pcall(function()
|
||||
if GUI and GUI.AddMessage then
|
||||
GUI.AddMessage(message, GUI.Font.Default)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Helper function to move an item to a container, but only if matching items exist
|
||||
local function moveItemToContainer(item, containerInv)
|
||||
if not item or not containerInv then return false end
|
||||
|
||||
print("[QuickStack] Attempting to stack with existing items in container (" .. #containerInv.slots .. " slots)")
|
||||
debugPrint("Attempting to stack with existing items in container (" .. #containerInv.slots .. " slots)")
|
||||
|
||||
-- Only try to find matching items to stack with
|
||||
local foundMatchingItem = false
|
||||
@@ -25,7 +60,7 @@ local function moveItemToContainer(item, containerInv)
|
||||
for _, containerItem in ipairs(containerInv.slots[slotIndex + 1].items) do
|
||||
if containerItem.Prefab.Identifier.Equals(item.Prefab.Identifier) then
|
||||
foundMatchingItem = true
|
||||
print("[QuickStack] Found matching item in container")
|
||||
debugPrint("Found matching item in container: " .. containerItem.Name)
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -34,7 +69,7 @@ local function moveItemToContainer(item, containerInv)
|
||||
|
||||
-- If no matching items exist in the container, don't move the item
|
||||
if not foundMatchingItem then
|
||||
print("[QuickStack] No matching items in container, skipping")
|
||||
debugPrint("No matching items in container, skipping " .. item.Name)
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -43,16 +78,19 @@ local function moveItemToContainer(item, containerInv)
|
||||
for _, containerItem in ipairs(containerInv.slots[slotIndex + 1].items) do
|
||||
if containerItem.Prefab.Identifier.Equals(item.Prefab.Identifier) then
|
||||
-- Try to stack with existing item
|
||||
print("[QuickStack] Stacking with existing item")
|
||||
debugPrint("Trying to stack " .. item.Name .. " with existing item")
|
||||
if containerInv.TryPutItem(item, slotIndex, true, false, nil) then
|
||||
debugPrint("Successfully stacked " .. item.Name)
|
||||
return true
|
||||
else
|
||||
debugPrint("Failed to stack " .. item.Name .. " - TryPutItem failed")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- We don't try to place in empty slots anymore, only stack with existing items
|
||||
print("[QuickStack] Failed to stack with existing items")
|
||||
debugPrint("Failed to stack with existing items")
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -63,7 +101,7 @@ local function sortContainersByPriority(containers)
|
||||
local bPriority = -1
|
||||
|
||||
-- Check priority for first container
|
||||
for i, identifier in ipairs(PRIORITY_CONTAINERS) do
|
||||
for i, identifier in ipairs(CONFIG.PRIORITY_CONTAINERS) do
|
||||
if a.Prefab.Identifier.Value:find(identifier) then
|
||||
aPriority = i
|
||||
break
|
||||
@@ -71,7 +109,7 @@ local function sortContainersByPriority(containers)
|
||||
end
|
||||
|
||||
-- Check priority for second container
|
||||
for i, identifier in ipairs(PRIORITY_CONTAINERS) do
|
||||
for i, identifier in ipairs(CONFIG.PRIORITY_CONTAINERS) do
|
||||
if b.Prefab.Identifier.Value:find(identifier) then
|
||||
bPriority = i
|
||||
break
|
||||
@@ -87,48 +125,119 @@ end
|
||||
-- Recursively find all containers in the player's inventory, including nested ones
|
||||
local function findAllContainers(inventory, containers)
|
||||
if not inventory or not inventory.slots then return containers end
|
||||
|
||||
|
||||
containers = containers or {}
|
||||
|
||||
|
||||
for _, slot in ipairs(inventory.slots) do
|
||||
for _, item in ipairs(slot.items) do
|
||||
if item.OwnInventory then
|
||||
-- Add this container
|
||||
print("[QuickStack] Found container: " .. item.Name .. " (" .. item.Prefab.Identifier.Value .. ")")
|
||||
debugPrint("Found container: " .. item.Name .. " (" .. item.Prefab.Identifier.Value .. ")")
|
||||
table.insert(containers, item)
|
||||
|
||||
-- Recursively search inside this container
|
||||
findAllContainers(item.OwnInventory, containers)
|
||||
|
||||
-- Recursively search inside this container if enabled
|
||||
if CONFIG.NESTED_CONTAINERS then
|
||||
debugPrint("Searching inside " .. item.Name .. " for nested containers")
|
||||
findAllContainers(item.OwnInventory, containers)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return containers
|
||||
end
|
||||
|
||||
-- Find the currently open container using the better approach with opened GUIs
|
||||
-- Find the currently open container
|
||||
local function getOpenContainer()
|
||||
-- Check if any ItemContainer GUIs are open
|
||||
for _, gui in pairs(GUI.OpenGuis) do
|
||||
if gui.UserData ~= nil and gui.UserData.Inventory ~= nil then
|
||||
-- Make sure it's not the player's inventory
|
||||
if gui.UserData.Item ~= nil and gui.UserData.Item.Inventory ~= Character.Controlled.Inventory then
|
||||
print("[QuickStack] Found open container: " .. gui.UserData.Item.Name)
|
||||
return gui.UserData.Item
|
||||
debugPrint("Attempting to find open container...")
|
||||
|
||||
-- Method 1: Check if Inventory.OpenState is accessible and has an open container
|
||||
pcall(function()
|
||||
if Character.Controlled and Character.Controlled.SelectedCharacter then
|
||||
local selectedChar = Character.Controlled.SelectedCharacter
|
||||
if selectedChar.Inventory then
|
||||
debugPrint("Checking selected character's inventory")
|
||||
-- This is likely the container the player is interacting with
|
||||
return selectedChar
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Method 2: Inspect GUI components to find inventory GUI components
|
||||
pcall(function()
|
||||
if GUI and GUI.Components then
|
||||
for _, component in pairs(GUI.Components) do
|
||||
-- Look for UI components related to inventory
|
||||
if component.RectTransform and component.RectTransform.GUIComponent and
|
||||
component.RectTransform.GUIComponent.UserData and
|
||||
component.RectTransform.GUIComponent.UserData.Item then
|
||||
local item = component.RectTransform.GUIComponent.UserData.Item
|
||||
if item.OwnInventory then
|
||||
debugPrint("Found open container via GUI component: " .. item.Name)
|
||||
return item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
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 then
|
||||
debugPrint("Found open container via current interaction: " .. selectedItem.InteractingWith.Name)
|
||||
return selectedItem.InteractingWith
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Method 4: Try to use Inventory.DraggingInventory (if it exists)
|
||||
pcall(function()
|
||||
if Inventory and Inventory.DraggingInventory and
|
||||
Inventory.DraggingInventory.Owner and
|
||||
Inventory.DraggingInventory.Owner ~= Character.Controlled then
|
||||
debugPrint("Found open container via DraggingInventory: " .. Inventory.DraggingInventory.Owner.Name)
|
||||
return Inventory.DraggingInventory.Owner
|
||||
end
|
||||
end)
|
||||
|
||||
-- Method 5: Check all items in the game with open inventories
|
||||
for item in Item.ItemList do
|
||||
if item and item.OwnInventory then
|
||||
local isOpened = false
|
||||
-- Try different ways to detect if an inventory is opened
|
||||
|
||||
-- Method 5.1: Check IsOpenedByPlayer if available
|
||||
pcall(function()
|
||||
if item.OwnInventory.IsOpenedByPlayer then
|
||||
isOpened = item.OwnInventory.IsOpenedByPlayer
|
||||
end
|
||||
end)
|
||||
|
||||
-- Method 5.2: Check if inventory has visualSlots created
|
||||
pcall(function()
|
||||
if item.OwnInventory.visualSlots and #item.OwnInventory.visualSlots > 0 then
|
||||
isOpened = true
|
||||
end
|
||||
end)
|
||||
|
||||
-- Method 5.3: Check if OpenState > 0
|
||||
pcall(function()
|
||||
if item.OwnInventory.OpenState and item.OwnInventory.OpenState > 0 then
|
||||
isOpened = true
|
||||
end
|
||||
end)
|
||||
|
||||
if isOpened then
|
||||
debugPrint("Found open container: " .. item.Name)
|
||||
return item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Try an alternative approach using opened inventories
|
||||
for _, inventory in pairs(ItemInventory.OpenInventories) do
|
||||
if inventory.Owner ~= nil and inventory.Owner.Inventory ~= Character.Controlled.Inventory then
|
||||
-- Found a non-player inventory
|
||||
print("[QuickStack] Found open inventory: " .. inventory.Owner.Name)
|
||||
return inventory.Owner
|
||||
end
|
||||
end
|
||||
|
||||
print("[QuickStack] No open container found")
|
||||
|
||||
debugPrint("No open container found")
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -136,7 +245,7 @@ end
|
||||
local function stackFromOpenContainer(character, playerContainers, openContainer)
|
||||
if not character or not openContainer or not openContainer.OwnInventory then return 0 end
|
||||
|
||||
print("[QuickStack] Stacking from open container: " .. openContainer.Name)
|
||||
debugPrint("Stacking from open container: " .. openContainer.Name)
|
||||
|
||||
local itemsMoved = 0
|
||||
local openContainerInv = openContainer.OwnInventory
|
||||
@@ -150,12 +259,18 @@ local function stackFromOpenContainer(character, playerContainers, openContainer
|
||||
local item = slot.items[i]
|
||||
|
||||
-- Skip container items
|
||||
if item.OwnInventory then goto nextItem end
|
||||
if item.OwnInventory then
|
||||
debugPrint("Skipping container item: " .. item.Name)
|
||||
goto nextItem
|
||||
end
|
||||
|
||||
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
|
||||
print("[QuickStack] Stacked " .. item.Name .. " from open container into " .. container.Name)
|
||||
debugPrint("Stacked " .. item.Name .. " from open container into " .. container.Name)
|
||||
itemsMoved = itemsMoved + 1
|
||||
break
|
||||
end
|
||||
@@ -170,23 +285,34 @@ end
|
||||
|
||||
-- Function to quickly stack items from inventory to containers
|
||||
local function quickStackItems(character)
|
||||
if not character then return end
|
||||
print("[QuickStack] Function called")
|
||||
if not character then
|
||||
debugPrint("No character found")
|
||||
return
|
||||
end
|
||||
|
||||
debugPrint("Quick stack function called")
|
||||
|
||||
local inventory = character.Inventory
|
||||
if not inventory or not inventory.slots then return end
|
||||
if not inventory or not inventory.slots then
|
||||
debugPrint("Character has no inventory")
|
||||
return
|
||||
end
|
||||
|
||||
-- Find all containers in player inventory, including nested ones
|
||||
local containers = findAllContainers(inventory, {})
|
||||
|
||||
print("[QuickStack] Found " .. #containers .. " containers (including nested)")
|
||||
debugPrint("Found " .. #containers .. " containers" .. (CONFIG.NESTED_CONTAINERS and " (including nested)" or ""))
|
||||
if #containers == 0 then
|
||||
print("[QuickStack] No containers with inventory found!")
|
||||
debugPrint("No containers with inventory found!")
|
||||
return
|
||||
end
|
||||
|
||||
-- Sort containers by priority
|
||||
containers = sortContainersByPriority(containers)
|
||||
for i, container in ipairs(containers) do
|
||||
debugPrint(i .. ": " .. container.Name .. " - priority container: " ..
|
||||
tostring(container.Prefab.Identifier.Value:find(CONFIG.PRIORITY_CONTAINERS[1]) ~= nil))
|
||||
end
|
||||
|
||||
local itemsMoved = 0
|
||||
|
||||
@@ -194,25 +320,34 @@ local function quickStackItems(character)
|
||||
for slotIndex, slot in ipairs(inventory.slots) do
|
||||
-- Skip hand slots
|
||||
local isHandSlot = false
|
||||
for _, handSlot in ipairs(HAND_SLOTS) do
|
||||
for _, handSlot in ipairs(CONFIG.HAND_SLOTS) do
|
||||
if slotIndex == handSlot then
|
||||
isHandSlot = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if isHandSlot then goto continueSlot end
|
||||
if isHandSlot then
|
||||
debugPrint("Skipping hand slot: " .. slotIndex)
|
||||
goto continueSlot
|
||||
end
|
||||
|
||||
-- Process items in the slot
|
||||
for i = #slot.items, 1, -1 do
|
||||
local item = slot.items[i]
|
||||
|
||||
-- Skip container items
|
||||
if item.OwnInventory then goto nextItem end
|
||||
if item.OwnInventory then
|
||||
debugPrint("Skipping container item: " .. item.Name)
|
||||
goto nextItem
|
||||
end
|
||||
|
||||
debugPrint("Processing inventory item: " .. item.Name .. " (" .. item.Prefab.Identifier.Value .. ")")
|
||||
|
||||
-- Try to move the item to each container
|
||||
for _, container in ipairs(containers) do
|
||||
debugPrint("Trying container: " .. container.Name)
|
||||
if moveItemToContainer(item, container.OwnInventory) then
|
||||
print("[QuickStack] Stacked " .. item.Name .. " into " .. container.Name)
|
||||
debugPrint("Stacked " .. item.Name .. " into " .. container.Name)
|
||||
itemsMoved = itemsMoved + 1
|
||||
break
|
||||
end
|
||||
@@ -227,20 +362,35 @@ local function quickStackItems(character)
|
||||
-- Check if there's an open container to stack from
|
||||
local openContainer = getOpenContainer()
|
||||
if openContainer then
|
||||
debugPrint("Found open container to stack from: " .. openContainer.Name)
|
||||
local openContainerItemsMoved = stackFromOpenContainer(character, containers, openContainer)
|
||||
itemsMoved = itemsMoved + openContainerItemsMoved
|
||||
else
|
||||
debugPrint("No open container found to stack from")
|
||||
end
|
||||
|
||||
if itemsMoved > 0 then
|
||||
print("[QuickStack] Stacked " .. itemsMoved .. " items into containers")
|
||||
debugPrint("Stacked " .. itemsMoved .. " items into containers")
|
||||
pcall(function()
|
||||
Game.PlaySound("hit")
|
||||
end)
|
||||
showNotification("Stacked " .. itemsMoved .. " items")
|
||||
else
|
||||
print("[QuickStack] No matching items to stack")
|
||||
debugPrint("No matching items to stack")
|
||||
showNotification("No matching items to stack")
|
||||
end
|
||||
end
|
||||
|
||||
-- Show a small message to the user when the mod loads
|
||||
Hook.Add("think", "quickStackInitMessage", function()
|
||||
-- Use a safer method to show a message
|
||||
showNotification(MOD_NAME .. " loaded! Press F to stack items.")
|
||||
Hook.Remove("think", "quickStackInitMessage")
|
||||
end)
|
||||
|
||||
-- Hook into player control to listen for key press
|
||||
Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
|
||||
if not PlayerInput.KeyHit(Keys.F) then return end
|
||||
if not PlayerInput.KeyHit(CONFIG.TRIGGER_KEY) then return end
|
||||
|
||||
local character = instance
|
||||
if not character then return end
|
||||
|
||||
Reference in New Issue
Block a user