diff --git a/AetherBags/Configuration/CategorySettings.cs b/AetherBags/Configuration/CategorySettings.cs index 898a201..1a3d336 100644 --- a/AetherBags/Configuration/CategorySettings.cs +++ b/AetherBags/Configuration/CategorySettings.cs @@ -8,8 +8,10 @@ namespace AetherBags.Configuration; public class CategorySettings { + public bool CategoriesEnabled { get; set; } = true; public bool GameCategoriesEnabled { get; set; } = true; public bool UserCategoriesEnabled { get; set; } = true; + public bool AllaganToolsCategoriesEnabled { get; set; } = false; public List UserCategories { get; set; } = new(); } diff --git a/AetherBags/IPC/AllaganToolsIPC.cs b/AetherBags/IPC/AllaganToolsIPC.cs new file mode 100644 index 0000000..394187a --- /dev/null +++ b/AetherBags/IPC/AllaganToolsIPC.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using Dalamud.Plugin.Ipc; + +namespace AetherBags.IPC; + +public class AllaganToolsIPC : IDisposable +{ + private ICallGateSubscriber? _isInitialized; + private ICallGateSubscriber? _initialized; + private ICallGateSubscriber>? _getFilterItems; + private ICallGateSubscriber>? _getSearchFilters; + private ICallGateSubscriber? _enableUiFilter; + private ICallGateSubscriber? _toggleUiFilter; + + public bool IsReady { get; private set; } + + /// + /// Cached filter items. Key = filterKey, Value = (ItemId -> Quantity). + /// + public Dictionary> CachedFilterItems { get; } = new(); + + /// + /// Cached search filters. Key -> Name. + /// + public Dictionary CachedSearchFilters { get; } = new(); + + /// + /// Quick lookup: ItemId -> List of filter keys that contain this item. + /// + public Dictionary> ItemToFilters { get; } = new(); + + public event Action? OnInitialized; + public event Action? OnFiltersRefreshed; + + public AllaganToolsIPC() + { + try + { + _isInitialized = Services.PluginInterface.GetIpcSubscriber("AllaganTools.IsInitialized"); + _initialized = Services.PluginInterface.GetIpcSubscriber("AllaganTools.Initialized"); + _getFilterItems = Services.PluginInterface.GetIpcSubscriber>("AllaganTools.GetFilterItems"); + _getSearchFilters = Services.PluginInterface.GetIpcSubscriber>("AllaganTools.GetSearchFilters"); + _enableUiFilter = Services.PluginInterface.GetIpcSubscriber("AllaganTools.EnableUiFilter"); + _toggleUiFilter = Services.PluginInterface.GetIpcSubscriber("AllaganTools.ToggleUiFilter"); + + _initialized.Subscribe(OnAllaganInitialized); + + // Check if already initialized + try + { + IsReady = _isInitialized.InvokeFunc(); + if (IsReady) + { + RefreshFilters(); + } + } + catch + { + IsReady = false; + } + } + catch (Exception ex) + { + Services.Logger.Debug($"Allagan Tools not available: {ex.Message}"); + IsReady = false; + } + } + + private void OnAllaganInitialized(bool initialized) + { + IsReady = initialized; + if (initialized) + { + Services.Logger.Information("Allagan Tools IPC connected"); + RefreshFilters(); + OnInitialized?.Invoke(); + } + } + + /// + /// Refreshes all cached filter data from Allagan Tools. + /// Call this when you need updated filter information. + /// + public void RefreshFilters() + { + if (!IsReady) return; + + try + { + CachedSearchFilters.Clear(); + CachedFilterItems.Clear(); + ItemToFilters.Clear(); + + var filters = _getSearchFilters?.InvokeFunc(); + if (filters == null) return; + + foreach (var (key, name) in filters) + { + CachedSearchFilters[key] = name; + + var items = _getFilterItems?.InvokeFunc(key); + if (items != null && items.Count > 0) + { + CachedFilterItems[key] = items; + + // Build reverse lookup + foreach (var itemId in items.Keys) + { + if (!ItemToFilters.TryGetValue(itemId, out var filterList)) + { + filterList = new List(capacity: 4); + ItemToFilters[itemId] = filterList; + } + filterList.Add(key); + } + } + } + + Services.Logger.Debug($"Refreshed {CachedSearchFilters.Count} Allagan Tools filters, {ItemToFilters.Count} unique items"); + OnFiltersRefreshed?.Invoke(); + } + catch (Exception ex) + { + Services.Logger.Warning($"Failed to refresh Allagan Tools filters: {ex.Message}"); + } + } + + /// + /// Checks if an item is in any Allagan Tools filter. + /// + public bool IsItemInAnyFilter(uint itemId) + => ItemToFilters.ContainsKey(itemId); + + /// + /// Gets all filter keys that contain this item. + /// + public IReadOnlyList? GetFiltersForItem(uint itemId) + => ItemToFilters.TryGetValue(itemId, out var list) ? list : null; + + /// + /// Gets items from a specific filter. Returns ItemId -> Quantity. + /// + public Dictionary? GetFilterItems(string filterKey) + { + // Try cache first + if (CachedFilterItems.TryGetValue(filterKey, out var cached)) + return cached; + + if (!IsReady) return null; + + try + { + return _getFilterItems?.InvokeFunc(filterKey); + } + catch (Exception ex) + { + Services.Logger.Warning($"GetFilterItems failed: {ex.Message}"); + return null; + } + } + + /// + /// Gets all available search filters. Returns Key -> Name. + /// + public Dictionary? GetSearchFilters() + { + if (CachedSearchFilters.Count > 0) + return CachedSearchFilters; + + if (!IsReady) return null; + + try + { + return _getSearchFilters?.InvokeFunc(); + } + catch (Exception ex) + { + Services.Logger.Warning($"GetSearchFilters failed: {ex.Message}"); + return null; + } + } + + public void Dispose() + { + _initialized?.Unsubscribe(OnAllaganInitialized); + } +} \ No newline at end of file diff --git a/AetherBags/IPC/IPCService.cs b/AetherBags/IPC/IPCService.cs new file mode 100644 index 0000000..955e53f --- /dev/null +++ b/AetherBags/IPC/IPCService.cs @@ -0,0 +1,23 @@ +using System; +using Dalamud.Plugin; +using Dalamud.Plugin.Ipc; + +namespace AetherBags.IPC; + +public class IPCService : IDisposable +{ + public AllaganToolsIPC AllaganTools { get; } + public WotsItIPC WotsIt { get; } + // Future: public BiSBuddyIPC BiSBuddy { get; } + + public IPCService() + { + AllaganTools = new AllaganToolsIPC(); + WotsIt = new WotsItIPC(); + } + + public void Dispose() + { + AllaganTools.Dispose(); + } +} \ No newline at end of file diff --git a/AetherBags/IPC/WotsItIPC.cs b/AetherBags/IPC/WotsItIPC.cs new file mode 100644 index 0000000..0a5373d --- /dev/null +++ b/AetherBags/IPC/WotsItIPC.cs @@ -0,0 +1,80 @@ +using System; +using Dalamud.Plugin.Ipc; + +namespace AetherBags.IPC; + +public class WotsItIPC : IDisposable +{ + private ICallGateSubscriber? _registerWithSearch; + private ICallGateSubscriber? _invoke; + private ICallGateSubscriber? _unregisterAll; + + private string? _searchGuid; + + public WotsItIPC() + { + try + { + _registerWithSearch = Services.PluginInterface.GetIpcSubscriber("FA.RegisterWithSearch"); + _unregisterAll = Services.PluginInterface.GetIpcSubscriber("FA.UnregisterAll"); + _invoke = Services.PluginInterface.GetIpcSubscriber("FA.Invoke"); + + _invoke.Subscribe(OnInvoke); + + Register(); + } + catch (Exception ex) + { + Services.Logger.Debug($"WotsIt not available: {ex.Message}"); + } + } + + private void Register() + { + try + { + UnregisterAll(); + + _searchGuid = _registerWithSearch?.InvokeFunc( + Services.PluginInterface.InternalName, + "AetherBags: Search Inventory", + "AetherBags Search", + 66472 // Icon ID + ); + } + catch (Exception ex) + { + Services.Logger.Debug($"Failed to register with WotsIt: {ex.Message}"); + } + } + + private void OnInvoke(string guid) + { + if (guid == _searchGuid) + { + if (! System.AddonInventoryWindow.IsOpen) + { + System.AddonInventoryWindow.Open(); + } + } + } + + private bool UnregisterAll() + { + try + { + _unregisterAll?.InvokeFunc(Services.PluginInterface.InternalName); + return true; + } + catch + { + return false; + } + } + + public void Dispose() + { + _invoke?.Unsubscribe(OnInvoke); + UnregisterAll(); + } +} \ No newline at end of file diff --git a/AetherBags/Inventory/Categories/CategoryBucketManager.cs b/AetherBags/Inventory/Categories/CategoryBucketManager.cs index 886c1e4..8b60b31 100644 --- a/AetherBags/Inventory/Categories/CategoryBucketManager.cs +++ b/AetherBags/Inventory/Categories/CategoryBucketManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using AetherBags.Configuration; using AetherBags.Inventory.Items; +using KamiToolKit.Classes; namespace AetherBags.Inventory.Categories; @@ -18,6 +19,15 @@ public static class CategoryBucketManager public static bool IsUserCategoryKey(uint key) => (key & UserCategoryKeyFlag) != 0; + private const uint AllaganFilterKeyFlag = 0x4000_0000; + + public static uint MakeAllaganFilterKey(int index) + => AllaganFilterKeyFlag | (uint)(index & 0x3FFF_FFFF); + + public static bool IsAllaganFilterKey(uint key) + => (key & AllaganFilterKeyFlag) != 0 && (key & UserCategoryKeyFlag) == 0; + + /// /// Resets all buckets for a new refresh cycle. /// @@ -148,6 +158,74 @@ public static class CategoryBucketManager } } + public static void BucketByAllaganFilters( + Dictionary itemInfoByKey, + Dictionary bucketsByKey, + HashSet claimedKeys, + bool allaganCategoriesEnabled) + { + if (!allaganCategoriesEnabled) return; + if (! System.IPC.AllaganTools.IsReady) return; + + var filters = System.IPC.AllaganTools.CachedSearchFilters; + var filterItems = System.IPC.AllaganTools.CachedFilterItems; + + int index = 0; + foreach (var (filterKey, filterName) in filters) + { + if (!filterItems. TryGetValue(filterKey, out var itemIds)) + { + index++; + continue; + } + + uint bucketKey = MakeAllaganFilterKey(index); + + if (!bucketsByKey.TryGetValue(bucketKey, out CategoryBucket? bucket)) + { + bucket = new CategoryBucket + { + Key = bucketKey, + Category = new CategoryInfo + { + Name = $"[AT] {filterName}", + Description = $"Allagan Tools filter: {filterName}", + Color = ColorHelper.GetColor(32), + }, + Items = new List(capacity: 16), + FilteredItems = new List(capacity: 16), + Used = true, + }; + bucketsByKey. Add(bucketKey, bucket); + } + else + { + bucket.Used = true; + bucket.Category.Name = $"[AT] {filterName}"; + } + + foreach (var itemKvp in itemInfoByKey) + { + ulong itemKey = itemKvp.Key; + ItemInfo item = itemKvp.Value; + + if (claimedKeys.Contains(itemKey)) + continue; + + if (itemIds.ContainsKey(item.Item.ItemId)) + { + bucket.Items.Add(item); + claimedKeys.Add(itemKey); + } + } + + if (bucket.Items. Count == 0) + bucket.Used = false; + + index++; + } + } + public static void BucketUnclaimedToMisc( Dictionary itemInfoByKey, Dictionary bucketsByKey, @@ -215,9 +293,13 @@ public static class CategoryBucketManager sortedCategoryKeys.Sort((left, right) => { - bool leftCategory = IsUserCategoryKey(left); - bool rightCategory = IsUserCategoryKey(right); - if (leftCategory != rightCategory) return leftCategory ? -1 : 1; + bool leftUser = IsUserCategoryKey(left); + bool rightUser = IsUserCategoryKey(right); + bool leftAllagan = IsAllaganFilterKey(left); + bool rightAllagan = IsAllaganFilterKey(right); + if (leftUser != rightUser) return leftUser ? -1 : 1; + if (leftAllagan != rightAllagan) return leftAllagan ? -1 : 1; + return left.CompareTo(right); }); } diff --git a/AetherBags/Inventory/State/InventoryState.cs b/AetherBags/Inventory/State/InventoryState.cs index 795e9dd..2589469 100644 --- a/AetherBags/Inventory/State/InventoryState.cs +++ b/AetherBags/Inventory/State/InventoryState.cs @@ -3,7 +3,6 @@ using System.Linq; using AetherBags.Configuration; using AetherBags.Currency; using AetherBags.Inventory.Categories; -using AetherBags.Inventory.Context; using AetherBags.Inventory.Items; using AetherBags.Inventory.Scanning; using Dalamud.Game.Inventory; @@ -32,68 +31,6 @@ public static unsafe class InventoryState public static bool Contains(this IReadOnlyCollection inventoryTypes, GameInventoryType type) => inventoryTypes.Contains((InventoryType)type); - public static void RefreshFromGame() - { - FFXIVClientStructs.FFXIV.Client.Game.InventoryManager* inventoryManager = FFXIVClientStructs.FFXIV.Client.Game.InventoryManager.Instance(); - if (inventoryManager == null) - { - ClearAll(); - return; - } - - var config = System.Config; - InventoryStackMode stackMode = config.General.StackMode; - bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled; - bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled; - List userCategories = config.Categories.UserCategories.Where(category => category.Enabled).ToList(); - - Services.Logger.DebugOnly($"RefreshFromGame StackMode={stackMode}"); - - AggByKey.Clear(); - ItemInfoByKey.Clear(); - SortedCategoryKeys.Clear(); - AllCategories.Clear(); - FilteredCategories.Clear(); - ClaimedKeys.Clear(); - - InventoryScanner.ScanBags(inventoryManager, stackMode, AggByKey); - CategoryBucketManager.ResetBuckets(BucketsByKey); - InventoryScanner.BuildItemInfos(AggByKey, ItemInfoByKey); - InventoryContextState.RefreshMaps(); - InventoryContextState.RefreshBlockedSlots(); - - if (userCategoriesEnabled && userCategories.Count > 0) - { - CategoryBucketManager.BucketByUserCategories( - ItemInfoByKey, - userCategories, - BucketsByKey, - ClaimedKeys, - UserCategoriesSortedScratch); - } - - if (gameCategoriesEnabled) - { - CategoryBucketManager.BucketByGameCategories( - ItemInfoByKey, - BucketsByKey, - ClaimedKeys, - userCategoriesEnabled); - } - else - { - CategoryBucketManager.BucketUnclaimedToMisc( - ItemInfoByKey, - BucketsByKey, - ClaimedKeys, - userCategoriesEnabled); - } - - InventoryScanner.PruneStaleItemInfos(AggByKey, ItemInfoByKey, RemoveKeysScratch); - CategoryBucketManager.SortBucketsAndBuildKeyList(BucketsByKey, SortedCategoryKeys); - CategoryBucketManager.BuildCategorizedList(BucketsByKey, SortedCategoryKeys, AllCategories); - } - public static IReadOnlyList GetInventoryItemCategories(string filterString = "", bool invert = false) { return InventoryFilter.FilterCategories( diff --git a/AetherBags/Inventory/State/InventoryStateBase.cs b/AetherBags/Inventory/State/InventoryStateBase.cs index e922bd4..bca1822 100644 --- a/AetherBags/Inventory/State/InventoryStateBase.cs +++ b/AetherBags/Inventory/State/InventoryStateBase.cs @@ -25,14 +25,14 @@ public abstract class InventoryStateBase public virtual unsafe void RefreshFromGame() { - FFXIVClientStructs.FFXIV.Client.Game.InventoryManager* inventoryManager = FFXIVClientStructs.FFXIV.Client.Game.InventoryManager.Instance(); + InventoryManager* inventoryManager = InventoryManager.Instance(); if (inventoryManager == null) { ClearAll(); return; } - var config = AetherBags.System.Config; + var config = System.Config; InventoryStackMode stackMode = config.General.StackMode; AggByKey.Clear(); @@ -61,8 +61,10 @@ public abstract class InventoryStateBase protected virtual void ApplyCategories(SystemConfiguration config) { - bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled; - bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled; + bool categoriesEnabled = config.Categories.CategoriesEnabled; + bool userCategoriesEnabled = config.Categories.UserCategoriesEnabled && categoriesEnabled; + bool gameCategoriesEnabled = config.Categories.GameCategoriesEnabled && categoriesEnabled; + bool allaganCategoriesEnabled = config.Categories.AllaganToolsCategoriesEnabled && categoriesEnabled; var userCategories = config.Categories.UserCategories.Where(c => c.Enabled).ToList(); if (userCategoriesEnabled && userCategories.Count > 0) @@ -71,6 +73,12 @@ public abstract class InventoryStateBase ItemInfoByKey, userCategories, BucketsByKey, ClaimedKeys, UserCategoriesSortedScratch); } + if (allaganCategoriesEnabled) + { + CategoryBucketManager.BucketByAllaganFilters( + ItemInfoByKey, BucketsByKey, ClaimedKeys, allaganCategoriesEnabled); + } + if (gameCategoriesEnabled) { CategoryBucketManager.BucketByGameCategories( diff --git a/AetherBags/Nodes/Configuration/Category/CategoryGeneralConfigurationNode.cs b/AetherBags/Nodes/Configuration/Category/CategoryGeneralConfigurationNode.cs new file mode 100644 index 0000000..c7ec4af --- /dev/null +++ b/AetherBags/Nodes/Configuration/Category/CategoryGeneralConfigurationNode.cs @@ -0,0 +1,99 @@ +using System.Numerics; +using AetherBags.Configuration; +using AetherBags.Inventory; +using AetherBags.Nodes.Color; +using KamiToolKit.Classes; +using KamiToolKit.Nodes; + +namespace AetherBags.Nodes.Configuration.Category; + +public sealed class CategoryGeneralConfigurationNode : TabbedVerticalListNode +{ + private readonly CheckboxNode _allaganToolsCheckbox; + public CategoryGeneralConfigurationNode() + { + CategorySettings config = System.Config.Categories; + + LabelTextNode titleNode = new LabelTextNode + { + Size = Size with { Y = 18 }, + String = "Category Configuration", + TextColor = ColorHelper.GetColor(2), + TextOutlineColor = ColorHelper.GetColor(0), + }; + AddNode(titleNode); + + AddTab(1); + + CheckboxNode categoriesEnabled = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Categories Enabled", + IsChecked = config.CategoriesEnabled, + OnClick = isChecked => + { + config.CategoriesEnabled = isChecked; + RefreshInventory(); + } + }; + AddNode(categoriesEnabled); + + AddTab(1); + + CheckboxNode gameCategoriesEnabled = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "Game Categories", + IsChecked = config.GameCategoriesEnabled, + TextTooltip = "Use the game's built-in item categories (e.g., Arms, Tools, Armor).", + OnClick = isChecked => + { + config.GameCategoriesEnabled = isChecked; + RefreshInventory(); + } + }; + AddNode(gameCategoriesEnabled); + + CheckboxNode userCategoriesEnabled = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = "User Categories", + IsChecked = config.UserCategoriesEnabled, + TextTooltip = "Use your custom-defined categories.", + OnClick = isChecked => + { + config.UserCategoriesEnabled = isChecked; + RefreshInventory(); + } + }; + AddNode(userCategoriesEnabled); + + bool allaganReady = System.IPC.AllaganTools?.IsReady ?? false; + _allaganToolsCheckbox = new CheckboxNode + { + Size = Size with { Y = 18 }, + IsVisible = true, + String = allaganReady ? "Allagan Tools Filters" : "Allagan Tools Filters (Not Available)", + IsChecked = config.AllaganToolsCategoriesEnabled, + IsEnabled = allaganReady, + TextTooltip = allaganReady + ? "Use search filters from Allagan Tools as categories. Items matching a filter will be grouped together." + : "Allagan Tools is not installed or not initialized.", + OnClick = isChecked => + { + config.AllaganToolsCategoriesEnabled = isChecked; + if (isChecked) + { + System.IPC?.AllaganTools?.RefreshFilters(); + } + RefreshInventory(); + } + }; + AddNode(_allaganToolsCheckbox); + } + + private void RefreshInventory() => InventoryOrchestrator.RefreshAll(updateMaps: true); +} \ No newline at end of file diff --git a/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs b/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs index 7d489c9..ba1bbb4 100644 --- a/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs +++ b/AetherBags/Nodes/Configuration/Category/CategoryScrollingAreaNode.cs @@ -4,7 +4,7 @@ using KamiToolKit.Nodes; namespace AetherBags.Nodes.Configuration.Category; -public class CategoryScrollingAreaNode : ScrollingAreaNode +public sealed class CategoryScrollingAreaNode : ScrollingAreaNode { private AddonCategoryConfigurationWindow? _categoryConfigurationAddon; private readonly TextButtonNode _categoryConfigurationButtonNode; @@ -13,13 +13,15 @@ public class CategoryScrollingAreaNode : ScrollingAreaNode { InitializeCategoryAddon(); + ContentNode.AddNode(new CategoryGeneralConfigurationNode()); + _categoryConfigurationButtonNode = new TextButtonNode { Size = new Vector2(300, 28), String = "Configure Categories", OnClick = () => _categoryConfigurationAddon?.Toggle(), }; - _categoryConfigurationButtonNode.AttachNode(this); + ContentNode.AddNode(_categoryConfigurationButtonNode); } private void InitializeCategoryAddon() { diff --git a/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs b/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs index 363f90b..4994b2c 100644 --- a/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs +++ b/AetherBags/Nodes/Configuration/Currency/CurrencyGeneralConfigurationNode.cs @@ -55,8 +55,9 @@ public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode { Size = Size with { Y = 18 }, IsVisible = true, - String = "Color When Capped", + String = "Color Weekly Cap", IsChecked = config.ColorWhenCapped, + TextTooltip = "Changes the color of the currency display when you have reached the maximum amount earnable for the current week (e.g., 450/450).", OnClick = isChecked => { config.ColorWhenCapped = isChecked; @@ -69,7 +70,7 @@ public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode ColorInputRow cappedCurrencyColorNode = new ColorInputRow { - Label = "Capped Currency Color", + Label = "Weekly Cap Color", Size = new Vector2(300, 24), CurrentColor = config.CappedColor, DefaultColor = new CurrencySettings().CappedColor, @@ -87,8 +88,9 @@ public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode { Size = Size with { Y = 18 }, IsVisible = true, - String = "Limited Currency Color", + String = "Color Max Capacity", IsChecked = config.ColorWhenLimited, + TextTooltip = "Changes the color of the currency display when your total held amount has reached its maximum capacity (e.g., 2000/2000).", OnClick = isChecked => { config.ColorWhenLimited = isChecked; @@ -101,7 +103,7 @@ public sealed class CurrencyGeneralConfigurationNode : TabbedVerticalListNode ColorInputRow limitCurrencyColorNode = new ColorInputRow { - Label = "Color Weekly Limit", + Label = "Max Capacity Color", Size = new Vector2(300, 24), CurrentColor = config.LimitColor, DefaultColor = new CurrencySettings().LimitColor, diff --git a/AetherBags/Plugin.cs b/AetherBags/Plugin.cs index e80562f..d39c2d6 100644 --- a/AetherBags/Plugin.cs +++ b/AetherBags/Plugin.cs @@ -6,11 +6,11 @@ using AetherBags.Helpers; using AetherBags.Hooks; using AetherBags.Inventory; using AetherBags.Inventory.State; +using AetherBags.IPC; using Dalamud.Game.Gui; using Dalamud.Plugin; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using KamiToolKit; -using NotImplementedException = System.NotImplementedException; namespace AetherBags; @@ -31,6 +31,8 @@ public unsafe class Plugin : IDalamudPlugin KamiToolKitLibrary.Initialize(pluginInterface); System.Config = Util.LoadConfigOrDefault(); + System.IPC = new IPCService(); + System.AddonInventoryWindow = new AddonInventoryWindow { InternalName = "AetherBags_MainBags", @@ -79,6 +81,7 @@ public unsafe class Plugin : IDalamudPlugin public void Dispose() { + System.IPC.Dispose(); Util.SaveConfig(System.Config); Services.ClientState.Login -= OnLogin; Services.ClientState.Logout -= OnLogout; diff --git a/AetherBags/System.cs b/AetherBags/System.cs index bc10aa3..0821faa 100644 --- a/AetherBags/System.cs +++ b/AetherBags/System.cs @@ -1,5 +1,6 @@ using AetherBags.Addons; using AetherBags.Configuration; +using AetherBags.IPC; namespace AetherBags; @@ -9,5 +10,6 @@ public static class System public static AddonSaddleBagWindow AddonSaddleBagWindow { get; set; } = null!; public static AddonRetainerWindow AddonRetainerWindow { get; set; } = null!; public static AddonConfigurationWindow AddonConfigurationWindow { get; set; } = null!; + public static IPCService IPC { get; set; } = null!; public static SystemConfiguration Config { get; set; } = null!; } \ No newline at end of file