From 200c430f8f4d36d91f1a53641faaf12333790056 Mon Sep 17 00:00:00 2001 From: Zeffuro Date: Tue, 30 Dec 2025 17:42:38 +0100 Subject: [PATCH] Misc fixes and move lifecycles --- .../AddonLifecycles/InventoryLifecycles.cs | 67 +++++++++++++++++-- AetherBags/Addons/AddonInventoryWindow.cs | 13 ++-- AetherBags/Addons/AddonRetainerWindow.cs | 18 ++--- AetherBags/Addons/AddonSaddleBagWindow.cs | 20 ++---- AetherBags/Addons/InventoryAddonBase.cs | 24 +++++++ AetherBags/Inventory/Items/ItemInfo.cs | 7 +- .../Nodes/Inventory/InventoryCategoryNode.cs | 16 +++-- AetherBags/Plugin.cs | 6 +- 8 files changed, 122 insertions(+), 49 deletions(-) diff --git a/AetherBags/AddonLifecycles/InventoryLifecycles.cs b/AetherBags/AddonLifecycles/InventoryLifecycles.cs index fb35975..41a65bb 100644 --- a/AetherBags/AddonLifecycles/InventoryLifecycles.cs +++ b/AetherBags/AddonLifecycles/InventoryLifecycles.cs @@ -19,12 +19,30 @@ public class InventoryLifecycles : IDisposable public InventoryLifecycles() { + // 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); + Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate); + Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, ["InventoryRetainer", "InventoryRetainerLarge"], OnRetainerInventoryUpdate); + + // PreShow + Services.AddonLifecycle.RegisterListener(AddonEvent.PreOpen, "InventoryBuddy", OnSaddleBagOpen); + Services.Logger.Verbose("InventoryLifecycles initialized"); } + private static bool IsInUnsafeState() + { + if (!Services.ClientState.IsLoggedIn) + return true; + + return Services.Condition.Any(ConditionFlag.BetweenAreas, ConditionFlag.BetweenAreas51); + } + /* values[0] = OpenType values[1] = OpenTitleId @@ -41,10 +59,7 @@ public class InventoryLifecycles : IDisposable if (args is not AddonRefreshArgs refreshArgs) return; - if (!Services.ClientState.IsLoggedIn) - return; - - if (Services.Condition[ConditionFlag.BetweenAreas] || Services.Condition[ConditionFlag.BetweenAreas51]) + if (IsInUnsafeState()) return; GeneralSettings config = System.Config.General; @@ -88,6 +103,9 @@ public class InventoryLifecycles : IDisposable if (args is not AddonRefreshArgs refreshArgs) return; + if (IsInUnsafeState()) + return; + GeneralSettings config = System.Config.General; if (config.HideGameSaddleBags) refreshArgs.AtkValueCount = 0; @@ -104,6 +122,9 @@ public class InventoryLifecycles : IDisposable if (args is not AddonRefreshArgs refreshArgs) return; + if (IsInUnsafeState()) + return; + GeneralSettings config = System.Config.General; if (config.HideGameRetainer) refreshArgs.AtkValueCount = 0; @@ -113,10 +134,46 @@ public class InventoryLifecycles : IDisposable } } + private void OnInventoryUpdate(AddonEvent type, AddonArgs args) + { + if (IsInUnsafeState()) + return; + + System.AddonInventoryWindow?.RefreshFromLifecycle(); + } + + private void OnSaddleBagUpdate(AddonEvent type, AddonArgs args) + { + if (IsInUnsafeState()) + return; + + System.AddonSaddleBagWindow?.RefreshFromLifecycle(); + } + + private void OnRetainerInventoryUpdate(AddonEvent type, AddonArgs args) + { + if (IsInUnsafeState()) + return; + + System.AddonRetainerWindow?.RefreshFromLifecycle(); + } + + private void OnSaddleBagOpen(AddonEvent type, AddonArgs args) + { + if (args is not AddonShowArgs showArgs) + return; + } + public void Dispose() { Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"]); Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"]); - Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["RetainerGrid0"]); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryRetainer, InventoryRetainerLarge"]); + + Services.AddonLifecycle.UnregisterListener(AddonEvent.PostRequestedUpdate, "Inventory", OnInventoryUpdate); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate); + Services.AddonLifecycle.UnregisterListener(AddonEvent.PostRequestedUpdate, ["InventoryRetainer", "InventoryRetainerLarge"], OnRetainerInventoryUpdate); + + Services.AddonLifecycle.UnregisterListener(AddonEvent.PreShow, ["InventoryBuddy"], OnSaddleBagOpen); } } \ No newline at end of file diff --git a/AetherBags/Addons/AddonInventoryWindow.cs b/AetherBags/Addons/AddonInventoryWindow.cs index 5848543..82c2313 100644 --- a/AetherBags/Addons/AddonInventoryWindow.cs +++ b/AetherBags/Addons/AddonInventoryWindow.cs @@ -78,11 +78,12 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase LayoutContent(); - Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "Inventory", OnInventoryUpdate); addon->SubscribeAtkArrayData(1, (int)NumberArrayType.Inventory); + _isSetupComplete = true; + _inventoryState.RefreshFromGame(); - RefreshCategoriesCore(autosize: true); + RefreshCategoriesCore(autosize: true); base.OnSetup(addon); } @@ -107,12 +108,6 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase FooterNode.RefreshCurrencies(); } - private void OnInventoryUpdate(AddonEvent type, AddonArgs args) - { - _inventoryState.RefreshFromGame(); - RefreshCategoriesCore(autosize: true); - } - protected override void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData) { base.OnRequestedUpdate(addon, numberArrayData, stringArrayData); @@ -146,9 +141,9 @@ public unsafe class AddonInventoryWindow : InventoryAddonBase RaptureAtkModule.Instance()->CloseAddon(blockingAddonId); } - Services.AddonLifecycle.UnregisterListener(OnInventoryUpdate); addon->UnsubscribeAtkArrayData(1, (int)NumberArrayType.Inventory); + _isSetupComplete = false; base.OnFinalize(addon); } } \ No newline at end of file diff --git a/AetherBags/Addons/AddonRetainerWindow.cs b/AetherBags/Addons/AddonRetainerWindow.cs index d80e90c..6d836f7 100644 --- a/AetherBags/Addons/AddonRetainerWindow.cs +++ b/AetherBags/Addons/AddonRetainerWindow.cs @@ -109,9 +109,9 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase LayoutContent(); - Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, ["InventoryRetainer", "InventoryRetainerLarge"], OnRetainerInventoryUpdate); - _inventoryState.RefreshFromGame(); + _isSetupComplete = true; + RefreshCategoriesCore(autosize: true); base.OnSetup(addon); @@ -119,7 +119,10 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase protected override void RefreshCategoriesCore(bool autosize) { - _slotCounterNode. String = _inventoryState.GetEmptySlotsString(); + if (!_isSetupComplete) + return; + + _slotCounterNode.String = _inventoryState.GetEmptySlotsString(); _retainerNameNode.String = RetainerState.CurrentRetainerName; base.RefreshCategoriesCore(autosize); @@ -165,12 +168,6 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase agent->SendCommand(0, [0]); } - private void OnRetainerInventoryUpdate(AddonEvent type, AddonArgs args) - { - _inventoryState.RefreshFromGame(); - RefreshCategoriesCore(autosize: true); - } - protected override void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData) { base.OnRequestedUpdate(addon, numberArrayData, stringArrayData); @@ -190,8 +187,7 @@ public unsafe class AddonRetainerWindow : InventoryAddonBase protected override void OnFinalize(AtkUnitBase* addon) { - Services.AddonLifecycle.UnregisterListener(OnRetainerInventoryUpdate); - + _isSetupComplete = false; base.OnFinalize(addon); } } \ No newline at end of file diff --git a/AetherBags/Addons/AddonSaddleBagWindow.cs b/AetherBags/Addons/AddonSaddleBagWindow.cs index 361da3e..f4ecc4d 100644 --- a/AetherBags/Addons/AddonSaddleBagWindow.cs +++ b/AetherBags/Addons/AddonSaddleBagWindow.cs @@ -3,9 +3,6 @@ using AetherBags.Inventory.State; using AetherBags.Nodes.Input; using AetherBags.Nodes.Inventory; using AetherBags.Nodes.Layout; -using Dalamud.Game.Addon.Lifecycle; -using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; -using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using KamiToolKit.Classes; using KamiToolKit.Nodes; @@ -84,9 +81,10 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase LayoutContent(); - Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate); - _inventoryState.RefreshFromGame(); + + _isSetupComplete = true; + RefreshCategoriesCore(autosize: true); base.OnSetup(addon); @@ -94,6 +92,9 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase protected override void RefreshCategoriesCore(bool autosize) { + if (!_isSetupComplete) + return; + _slotCounterNode.String = _inventoryState.GetEmptySlotsString(); base.RefreshCategoriesCore(autosize); @@ -113,12 +114,6 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase base.OnUpdate(addon); } - private void OnSaddleBagUpdate(AddonEvent type, AddonArgs args) - { - _inventoryState.RefreshFromGame(); - RefreshCategoriesCore(autosize: true); - } - protected override void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData) { base.OnRequestedUpdate(addon, numberArrayData, stringArrayData); @@ -138,8 +133,7 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase protected override void OnFinalize(AtkUnitBase* addon) { - Services.AddonLifecycle.UnregisterListener(OnSaddleBagUpdate); - + _isSetupComplete = false; base.OnFinalize(addon); } } \ No newline at end of file diff --git a/AetherBags/Addons/InventoryAddonBase.cs b/AetherBags/Addons/InventoryAddonBase.cs index 83cd39f..9c4cb02 100644 --- a/AetherBags/Addons/InventoryAddonBase.cs +++ b/AetherBags/Addons/InventoryAddonBase.cs @@ -38,6 +38,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon protected bool RefreshQueued; protected bool RefreshAutosizeQueued; private bool _isRefreshing; + protected bool _isSetupComplete; protected abstract InventoryStateBase InventoryState { get; } @@ -50,6 +51,8 @@ public abstract unsafe class InventoryAddonBase : NativeAddon if (!IsOpen) return; if (!Services.ClientState.IsLoggedIn) return; if (_isRefreshing) return; + if (!_isSetupComplete) return; + try { _isRefreshing = true; @@ -72,8 +75,29 @@ public abstract unsafe class InventoryAddonBase : NativeAddon }, delayTicks: 2); } + public void RefreshFromLifecycle() + { + if (!_isSetupComplete) return; + if (!IsOpen) return; + if (_isRefreshing) return; + + try + { + _isRefreshing = true; + InventoryState.RefreshFromGame(); + RefreshCategoriesCore(autosize: true); + } + finally + { + _isRefreshing = false; + } + } + protected virtual void RefreshCategoriesCore(bool autosize) { + if (!_isSetupComplete) + return; + if (HasFooter) { FooterNode.SlotAmountText = InventoryState.GetEmptySlotsString(); diff --git a/AetherBags/Inventory/Items/ItemInfo.cs b/AetherBags/Inventory/Items/ItemInfo.cs index d3c5f7d..a6286e8 100644 --- a/AetherBags/Inventory/Items/ItemInfo.cs +++ b/AetherBags/Inventory/Items/ItemInfo.cs @@ -66,7 +66,7 @@ public sealed class ItemInfo : IEquatable public InventoryMappedLocation VisualLocation => IsMainInventory ? InventoryContextState.GetVisualLocation(InventoryPage, Item.Slot) - : new InventoryMappedLocation((int)Item.Container.AgentItemContainerId, Item. Slot); + : new InventoryMappedLocation((int)Item.Container.AgentItemContainerId, Item.Slot); public int InventoryPage => Item.Container switch @@ -87,7 +87,10 @@ public sealed class ItemInfo : IEquatable if (!InventoryContextState.HasActiveContext) return true; - return IsMainInventory && InventoryContextState.IsEligible(InventoryPage, Item.Slot); + if (!IsMainInventory) + return true; + + return InventoryContextState.IsEligible(InventoryPage, Item.Slot); } } diff --git a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs index b1a62fa..e2565fd 100644 --- a/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs +++ b/AetherBags/Nodes/Inventory/InventoryCategoryNode.cs @@ -222,12 +222,16 @@ public class InventoryCategoryNode : SimpleComponentNode private unsafe InventoryDragDropNode CreateInventoryDragDropNode(ItemInfo data) { InventoryItem item = data.Item; - InventoryMappedLocation location = data.VisualLocation; + InventoryMappedLocation visualLocation = data.VisualLocation; + + bool useVisualLocation = item.Container.IsMainInventory; + bool isSlotBlocked = item.Container.IsMainInventory && data.IsSlotBlocked; + float alpha = !isSlotBlocked && data.IsEligibleForContext ? 1.0f : 0.4f; return new InventoryDragDropNode { Size = new Vector2(42, 46), - Alpha = data.IsEligibleForContext || data.IsSlotBlocked ? 1.0f : 0.4f, + Alpha = alpha, IsVisible = true, IconId = item.IconId, AcceptedType = DragDropType.Item, @@ -235,8 +239,8 @@ public class InventoryCategoryNode : SimpleComponentNode Payload = new DragDropPayload { Type = DragDropType.Item, - Int1 = location.Container, - Int2 = location.Slot, + Int1 = useVisualLocation ? visualLocation.Container : (int)item.Container, + Int2 = useVisualLocation ? visualLocation.Slot : item.Slot, }, IsClickable = true, OnDiscard = node => OnDiscard(node, data), @@ -273,8 +277,8 @@ public class InventoryCategoryNode : SimpleComponentNode return; } - // Debug: log raw payload values - Services. Logger.Debug($"[OnPayload] Raw payload: Type={payload.Type} Int1={payload.Int1} Int2={payload.Int2}"); + // Debug:log raw payload values + Services.Logger.Debug($"[OnPayload] Raw payload: Type={payload.Type} Int1={payload.Int1} Int2={payload.Int2} Ref={payload.ReferenceIndex}"); InventoryLocation sourceLocation = payload.InventoryLocation; diff --git a/AetherBags/Plugin.cs b/AetherBags/Plugin.cs index a9eb598..6ccecbd 100644 --- a/AetherBags/Plugin.cs +++ b/AetherBags/Plugin.cs @@ -17,7 +17,7 @@ public unsafe class Plugin : IDalamudPlugin private readonly CommandHandler _commandHandler; private readonly InventoryHooks _inventoryHooks; - private readonly InventoryLifecycles _inventoryLifecycles; + private readonly InventoryLifecycles inventoryLifecycles; public Plugin(IDalamudPluginInterface pluginInterface) { @@ -72,7 +72,7 @@ public unsafe class Plugin : IDalamudPlugin } _inventoryHooks = new InventoryHooks(); - _inventoryLifecycles = new InventoryLifecycles(); + inventoryLifecycles = new InventoryLifecycles(); } public void Dispose() @@ -94,7 +94,7 @@ public unsafe class Plugin : IDalamudPlugin KamiToolKitLibrary.Dispose(); _inventoryHooks.Dispose(); - _inventoryLifecycles.Dispose(); + inventoryLifecycles.Dispose(); } private void OnLogin()