From ca2baf917e3811a48eff48bdc23afc62069ea542 Mon Sep 17 00:00:00 2001 From: Zeffuro Date: Wed, 31 Dec 2025 23:59:34 +0100 Subject: [PATCH] Open/Hide for SaddleBags/Retainers working --- .../AddonLifecycles/InventoryLifecycles.cs | 89 ++++++++++++++----- AetherBags/Addons/AddonRetainerWindow.cs | 18 ++++ AetherBags/Addons/AddonSaddleBagWindow.cs | 12 +++ .../Extensions/DragDropPayloadExtensions.cs | 9 ++ .../General/FunctionalConfigurationNode.cs | 62 +++++++++++++ .../Nodes/Inventory/InventoryCategoryNode.cs | 8 ++ AetherBags/Plugin.cs | 7 +- 7 files changed, 181 insertions(+), 24 deletions(-) diff --git a/AetherBags/AddonLifecycles/InventoryLifecycles.cs b/AetherBags/AddonLifecycles/InventoryLifecycles.cs index 41a65bb..aecdf3b 100644 --- a/AetherBags/AddonLifecycles/InventoryLifecycles.cs +++ b/AetherBags/AddonLifecycles/InventoryLifecycles.cs @@ -8,6 +8,7 @@ using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.NativeWrapper; using Dalamud.Utility; +using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using Lumina.Text.ReadOnly; using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; @@ -19,10 +20,18 @@ public class InventoryLifecycles : IDisposable public InventoryLifecycles() { + var bags = new[] { "Inventory", "InventoryLarge", "InventoryExpansion" }; + var saddle = new[] { "InventoryBuddy" }; + var retainer = new[] { "InventoryRetainer", "InventoryRetainerLarge" }; + + Services.AddonLifecycle.RegisterListener(AddonEvent.PostSetup, saddle, OnPostSetup); + Services.AddonLifecycle.RegisterListener(AddonEvent.PostSetup, retainer, OnPostSetup); + + Services.AddonLifecycle.RegisterListener(AddonEvent.PreFinalize, saddle, OnPreFinalize); + Services.AddonLifecycle.RegisterListener(AddonEvent.PreFinalize, retainer, OnPreFinalize); + // PreRefresh Handlers Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"], InventoryPreRefreshHandler); - Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"], InventoryBuddyPreRefreshHandler); - //Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["RetainerGrid0"], InventoryRetainerPreRefreshHandler); // PostRequestedUpdate Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "Inventory", OnInventoryUpdate); @@ -35,6 +44,58 @@ public class InventoryLifecycles : IDisposable Services.Logger.Verbose("InventoryLifecycles initialized"); } + private void OnPreFinalize(AddonEvent type, AddonArgs args) + { + CloseInventories(args.AddonName); + } + + private void OnPostSetup(AddonEvent type, AddonArgs args) + { + OpenInventories(args.AddonName); + } + + private unsafe void OpenInventories(string name) + { + GeneralSettings config = System.Config.General; + if (name.Contains("Retainer") && config.OpenRetainerWithGameInventory) + { + System.AddonRetainerWindow.Open(); + if (config.HideGameRetainer) + { + var addon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryRetainer"); + if (addon != null) + { + addon->IsVisible = false; + } + + addon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryRetainerLarge"); + if (addon != null) + { + addon->IsVisible = false; + } + } + } + + if (name.Contains("InventoryBuddy") && config.OpenSaddleBagsWithGameInventory) + { + System.AddonSaddleBagWindow.Open(); + if (config.HideGameSaddleBags) + { + var addon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryBuddy"); + if (addon != null) + { + addon->IsVisible = false; + } + } + } + } + + private void CloseInventories(string name) + { + if (name.Contains("Retainer")) System.AddonRetainerWindow.Close(); + if (name.Contains("InventoryBuddy")) System.AddonSaddleBagWindow.Close(); + } + private static bool IsInUnsafeState() { if (!Services.ClientState.IsLoggedIn) @@ -115,24 +176,6 @@ public class InventoryLifecycles : IDisposable } } - // TODO: Inventory/Retainers are not perma open, need some way to close it too. - // TODO: Don't have the right retainer prerefresh handler yet. - private void InventoryRetainerPreRefreshHandler(AddonEvent type, AddonArgs args) - { - if (args is not AddonRefreshArgs refreshArgs) - return; - - if (IsInUnsafeState()) - return; - - GeneralSettings config = System.Config.General; - - if (config.HideGameRetainer) refreshArgs.AtkValueCount = 0; - if (config.OpenRetainerWithGameInventory) - { - System.AddonRetainerWindow.Toggle(); - } - } private void OnInventoryUpdate(AddonEvent type, AddonArgs args) { @@ -166,6 +209,12 @@ public class InventoryLifecycles : IDisposable public void Dispose() { + Services.AddonLifecycle.UnregisterListener(AddonEvent.PostSetup, "InventoryBuddy", OnPostSetup); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PostSetup, "InventoryRetainer, InventoryRetainerLarge", OnPostSetup); + + Services.AddonLifecycle.UnregisterListener(AddonEvent.PreFinalize, "InventoryBuddy", OnPreFinalize); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PreFinalize, "InventoryRetainer, InventoryRetainerLarge", OnPreFinalize); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"]); Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"]); Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryRetainer, InventoryRetainerLarge"]); diff --git a/AetherBags/Addons/AddonRetainerWindow.cs b/AetherBags/Addons/AddonRetainerWindow.cs index 6db4251..15e3eee 100644 --- a/AetherBags/Addons/AddonRetainerWindow.cs +++ b/AetherBags/Addons/AddonRetainerWindow.cs @@ -200,6 +200,24 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase protected override void OnFinalize(AtkUnitBase* addon) { _isSetupComplete = false; + + if (System.Config.General.HideGameRetainer) + { + var retainerAddon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryRetainer"); + if (retainerAddon != null) + { + retainerAddon->IsVisible = true; + retainerAddon->Close(true); + } + + retainerAddon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryRetainerLarge"); + if (retainerAddon != null) + { + retainerAddon->IsVisible = true; + retainerAddon->Close(true); + } + } + base.OnFinalize(addon); } } \ No newline at end of file diff --git a/AetherBags/Addons/AddonSaddleBagWindow.cs b/AetherBags/Addons/AddonSaddleBagWindow.cs index 58d5481..9ee5036 100644 --- a/AetherBags/Addons/AddonSaddleBagWindow.cs +++ b/AetherBags/Addons/AddonSaddleBagWindow.cs @@ -3,6 +3,7 @@ using AetherBags.Inventory.State; using AetherBags.Nodes.Input; using AetherBags.Nodes.Inventory; using AetherBags.Nodes.Layout; +using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using KamiToolKit.Classes; using KamiToolKit.Nodes; @@ -139,6 +140,17 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase protected override void OnFinalize(AtkUnitBase* addon) { _isSetupComplete = false; + + if (System.Config.General.HideGameSaddleBags) + { + var saddleAddon = RaptureAtkUnitManager.Instance()->GetAddonByName("InventoryBuddy"); + if (saddleAddon != null) + { + saddleAddon->IsVisible = true; + saddleAddon->Close(true); + } + } + base.OnFinalize(addon); } } \ No newline at end of file diff --git a/AetherBags/Extensions/DragDropPayloadExtensions.cs b/AetherBags/Extensions/DragDropPayloadExtensions.cs index d1da0e6..197f6ed 100644 --- a/AetherBags/Extensions/DragDropPayloadExtensions.cs +++ b/AetherBags/Extensions/DragDropPayloadExtensions.cs @@ -18,6 +18,15 @@ public static unsafe class DragDropPayloadExtensions or DragDropType.RemoteInventory_Item or DragDropType.Item; + public bool IsSameBaseContainer(DragDropPayload otherPayload) { + if (payload.InventoryLocation.Container.IsSameContainerGroup(otherPayload.InventoryLocation.Container)) + { + return true; + } + + return false; + } + public InventoryLocation InventoryLocation { get diff --git a/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs b/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs index 243d4bd..d3b8d5d 100644 --- a/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs +++ b/AetherBags/Nodes/Configuration/General/FunctionalConfigurationNode.cs @@ -12,6 +12,8 @@ namespace AetherBags.Nodes.Configuration.General; internal sealed class FunctionalConfigurationNode : TabbedVerticalListNode { private readonly CheckboxNode _hideDefaultBagsCheckboxNode; + private readonly CheckboxNode _hideSaddlebagsCheckboxNode; + private readonly CheckboxNode _hideRetainerbagsCheckboxNode; private readonly LabeledDropdownNode _stackDropDown; public FunctionalConfigurationNode() @@ -57,6 +59,66 @@ internal sealed class FunctionalConfigurationNode : TabbedVerticalListNode AddNode(_hideDefaultBagsCheckboxNode); SubtractTab(1); + var showSaddleWithGameCheckBox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Auto-open Saddlebags with game Saddlebags", + IsChecked = config.OpenSaddleBagsWithGameInventory, + OnClick = isChecked => + { + config.OpenSaddleBagsWithGameInventory = isChecked; + _hideSaddlebagsCheckboxNode?.IsEnabled = isChecked; + } + }; + AddNode(showSaddleWithGameCheckBox); + + AddTab(1); + _hideSaddlebagsCheckboxNode = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Hide default Saddlebags", + IsEnabled = config.OpenSaddleBagsWithGameInventory, + IsChecked = config.HideGameSaddleBags, + OnClick = isChecked => + { + config.HideGameSaddleBags = isChecked; + } + }; + AddNode(_hideSaddlebagsCheckboxNode); + SubtractTab(1); + + var showRetainerWithGameCheckBox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Auto-open Retainer bags with game Retainer bags", + IsChecked = config.OpenRetainerWithGameInventory, + OnClick = isChecked => + { + config.OpenRetainerWithGameInventory = isChecked; + _hideRetainerbagsCheckboxNode?.IsEnabled = isChecked; + } + }; + AddNode(showRetainerWithGameCheckBox); + + AddTab(1); + _hideRetainerbagsCheckboxNode = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Hide default Retainer bags", + IsEnabled = config.OpenRetainerWithGameInventory, + IsChecked = config.HideGameRetainer, + OnClick = isChecked => + { + config.HideGameRetainer = isChecked; + } + }; + AddNode(_hideRetainerbagsCheckboxNode); + SubtractTab(1); + var linkItemCheckBox = new CheckboxNode { Size = Size with { Y = 18 }, diff --git a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs index 9071b06..567519b 100644 --- a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs +++ b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs @@ -297,6 +297,14 @@ public class InventoryCategoryNode : SimpleComponentNode return; } + if (acceptedPayload.IsSameBaseContainer(nodePayload)) + { + Services.Logger.Information("[OnPayload] Source and target are in the same base container, skipping move."); + node.IconId = targetItemInfo.IconId; + node.Payload = nodePayload; + return; + } + var sourceCopy = acceptedPayload; var targetCopy = nodePayload; diff --git a/AetherBags/Plugin.cs b/AetherBags/Plugin.cs index 6ccecbd..e80562f 100644 --- a/AetherBags/Plugin.cs +++ b/AetherBags/Plugin.cs @@ -6,8 +6,11 @@ using AetherBags.Helpers; using AetherBags.Hooks; using AetherBags.Inventory; using AetherBags.Inventory.State; +using Dalamud.Game.Gui; using Dalamud.Plugin; +using FFXIVClientStructs.FFXIV.Client.UI.Agent; using KamiToolKit; +using NotImplementedException = System.NotImplementedException; namespace AetherBags; @@ -26,7 +29,6 @@ public unsafe class Plugin : IDalamudPlugin BackupHelper.DoConfigBackup(pluginInterface); KamiToolKitLibrary.Initialize(pluginInterface); - System.Config = Util.LoadConfigOrDefault(); System.AddonInventoryWindow = new AddonInventoryWindow @@ -78,9 +80,6 @@ public unsafe class Plugin : IDalamudPlugin public void Dispose() { Util.SaveConfig(System.Config); - - // Services.GameInventory.InventoryChanged -= InventoryState.OnRawItemAdded; - Services.ClientState.Login -= OnLogin; Services.ClientState.Logout -= OnLogout;