diff --git a/CriticalCommonLib b/CriticalCommonLib index bd94c362..53da2979 160000 --- a/CriticalCommonLib +++ b/CriticalCommonLib @@ -1 +1 @@ -Subproject commit bd94c3624c75ebe79544f7778b38899c218670f9 +Subproject commit 53da2979f5bf0c3b2f536639dbd25c6b65bbe737 diff --git a/InventoryTools/Enums/ShopType.cs b/InventoryTools/Enums/ShopType.cs new file mode 100644 index 00000000..29a76e89 --- /dev/null +++ b/InventoryTools/Enums/ShopType.cs @@ -0,0 +1,10 @@ +namespace InventoryTools.Enums; + +public enum ShopType +{ + Gil, + SpecialShop, + Collectable, + InclusionShop, + FreeCompanyShop, +} \ No newline at end of file diff --git a/InventoryTools/Highlighting/ShopHighlighting.cs b/InventoryTools/Highlighting/ShopHighlighting.cs new file mode 100644 index 00000000..aa59f0d4 --- /dev/null +++ b/InventoryTools/Highlighting/ShopHighlighting.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Component.GUI; +using ImGuiNET; +using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; + +namespace InventoryTools.Highlighting; + +public class ShopHighlighting : IDisposable +{ + private readonly IGameGui gameGui; + private readonly IAddonLifecycle addonLifecycle; + private readonly IPluginLog pluginLog; + private uint shopItemsAtkIndex = 441; + private uint shopCountAtkIndex = 2; + private HashSet highlightedItems = new HashSet(); + private Dictionary? itemIndexMap = null; + + public ShopHighlighting(IGameGui gameGui, IAddonLifecycle addonLifecycle, IPluginLog pluginLog) + { + this.gameGui = gameGui; + this.addonLifecycle = addonLifecycle; + this.pluginLog = pluginLog; + addonLifecycle.RegisterListener(AddonEvent.PostSetup, "Shop", AddonSetup); + addonLifecycle.RegisterListener(AddonEvent.PostDraw, "Shop", AddonPostDraw); + } + + public void AddItem(uint itemId) + { + highlightedItems.Add(itemId); + } + + public void RemoveItem(uint itemId) + { + highlightedItems.Remove(itemId); + } + + public void SetItems(List items) + { + highlightedItems = [..items]; + } + + public void SetItems(HashSet items) + { + highlightedItems = items; + } + + public void ClearItems() + { + highlightedItems.Clear(); + } + + private string itemIdString = ""; + private uint itemId; + + public unsafe void DrawDebug() + { + var addon = gameGui.GetAddonByName("Shop"); + if (addon != IntPtr.Zero) + { + var atkUnitBase = (AtkUnitBase*)addon; + var atkComponentBase = atkUnitBase->GetComponentByNodeId(16); + if (atkComponentBase != null) + { + var listNode = (AtkComponentList*)atkComponentBase; + var listItemIndex = listNode->ItemRendererList->AtkComponentListItemRenderer->ListItemIndex; + ImGui.TextUnformatted($"List Item Index: {listItemIndex}"); + if (itemIndexMap != null) + { + foreach (var item in itemIndexMap) + { + ImGui.TextUnformatted(item.Key + ": " + item.Value); + } + } + + if (ImGui.InputText("Item", ref itemIdString, 128)) + { + if (uint.TryParse(itemIdString, out itemId)) + { + itemId = itemId; + } + itemIdString = itemId.ToString(); + } + if (ImGui.Button("Add Item")) + { + if (uint.TryParse(itemIdString, out itemId)) + { + highlightedItems.Add(itemId); + } + } + if (ImGui.Button("Remove Item")) + { + if (uint.TryParse(itemIdString, out itemId)) + { + highlightedItems.Remove(itemId); + } + } + } + } + } + + + private unsafe void AddonPostDraw(AddonEvent type, AddonArgs args) + { + if (args.Addon != IntPtr.Zero) + { + var atkUnitBase = (AtkUnitBase*)args.Addon; + var atkComponentBase = atkUnitBase->GetComponentByNodeId(16); + if (atkComponentBase != null) + { + var listNode = (AtkComponentList*)atkComponentBase; + if (this.itemIndexMap == null) + { + CalculateItemIndexMap(atkUnitBase); + } + + for (int i = 0; i < listNode->ListLength; i++) + { + if (!highlightedItems.Any()) + { + listNode->SetItemDisabledState(i, false); + listNode->SetItemHighlightedState(i, false); + } + else if (itemIndexMap!.ContainsKey(i)) + { + if (highlightedItems.Contains(itemIndexMap[i])) + { + if (!listNode->GetItemHighlightedState(i)) + { + listNode->SetItemHighlightedState(i, true); + } + if (listNode->GetItemDisabledState(i)) + { + listNode->SetItemDisabledState(i, false); + } + } + else + { + if (!listNode->GetItemDisabledState(i)) + { + listNode->SetItemDisabledState(i, true); + } + if (listNode->GetItemHighlightedState(i)) + { + listNode->SetItemHighlightedState(i, false); + } + } + } + } + } + } + } + + private unsafe void CalculateItemIndexMap(AtkUnitBase* atkUnitBase) + { + var itemIndexMap = new Dictionary(); + var shopLength = atkUnitBase->AtkValues[shopCountAtkIndex].UInt; + for (var i = shopItemsAtkIndex; i < shopItemsAtkIndex + shopLength; i++) + { + var atkValue = atkUnitBase->AtkValues[i]; + if (atkValue.Type != ValueType.UInt) + { + break; + } + + itemIndexMap[(int)(i - shopItemsAtkIndex)] = atkValue.UInt; + } + this.itemIndexMap = itemIndexMap; + } + + private unsafe void AddonSetup(AddonEvent type, AddonArgs args) + { + if (args.Addon != IntPtr.Zero) + { + var atkUnitBase = (AtkUnitBase*)args.Addon; + CalculateItemIndexMap(atkUnitBase); + } + } + + public void Dispose() + { + addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "Shop", AddonSetup); + addonLifecycle.UnregisterListener(AddonEvent.PostDraw, "Shop", AddonPostDraw); + } +} \ No newline at end of file diff --git a/InventoryTools/InventoryTools.csproj b/InventoryTools/InventoryTools.csproj index 7ef495dc..a81db0c8 100644 --- a/InventoryTools/InventoryTools.csproj +++ b/InventoryTools/InventoryTools.csproj @@ -17,7 +17,7 @@ - + @@ -155,7 +155,6 @@ - diff --git a/InventoryTools/InventoryToolsPlugin.cs b/InventoryTools/InventoryToolsPlugin.cs index 14047547..930fccb3 100644 --- a/InventoryTools/InventoryToolsPlugin.cs +++ b/InventoryTools/InventoryToolsPlugin.cs @@ -31,6 +31,7 @@ using Dalamud.Plugin; using Dalamud.Plugin.Services; using InventoryTools.Commands; +using InventoryTools.Highlighting; using InventoryTools.Host; using InventoryTools.Hotkeys; using InventoryTools.IPC; @@ -122,7 +123,6 @@ public InventoryToolsPlugin(IDalamudPluginInterface pluginInterface, IPluginLog typeof(IPCService), typeof(HostedCraftMonitor), typeof(ItemSearchService), - }; public List GetHostedServices() @@ -288,6 +288,7 @@ public override void PreBuild(IHostBuilder hostBuilder) builder.RegisterType().As().As(); builder.RegisterType().As().As(); builder.RegisterType().As().As(); + builder.RegisterType().As().As(); }); //Hosted service registrations @@ -336,6 +337,8 @@ public override void PreBuild(IHostBuilder hostBuilder) builder.RegisterType().SingleInstance(); builder.RegisterType().SingleInstance(); builder.RegisterType().SingleInstance(); + builder.RegisterType().SingleInstance(); + builder.RegisterType().SingleInstance(); builder.Register(c => c.Resolve().GameData).SingleInstance().ExternallyOwned(); builder.RegisterGameSheetManager(new SheetManagerStartupOptions() { diff --git a/InventoryTools/Lists/ListFilterService.cs b/InventoryTools/Lists/ListFilterService.cs index bc9d2b61..df27bc2b 100644 --- a/InventoryTools/Lists/ListFilterService.cs +++ b/InventoryTools/Lists/ListFilterService.cs @@ -186,6 +186,7 @@ private List GenerateFilterResult(FilterConfiguration filter, List var displayDestinationCrossCharacter = filter.DestinationIncludeCrossCharacter ?? _configuration.DisplayCrossCharacter; Logger.LogTrace("Filter Information:"); + Logger.LogTrace("Filter Name:" + filter.NameFilter); Logger.LogTrace("Filter Type: " + filter.FilterType); if (filter.FilterType == FilterType.SortingFilter || filter.FilterType == FilterType.CraftFilter) diff --git a/InventoryTools/Lists/ListService.cs b/InventoryTools/Lists/ListService.cs index 326d1ccc..0ac77454 100644 --- a/InventoryTools/Lists/ListService.cs +++ b/InventoryTools/Lists/ListService.cs @@ -66,6 +66,8 @@ public ListService(ILogger logger, MediatorService mediatorService, _mediatorService.Subscribe(this, message => ListUpdated(message.FilterConfiguration) ); _mediatorService.Subscribe(this, AddToCraftListMessageRecv ); _mediatorService.Subscribe(this, AddToNewCraftListMessageRecv ); + _mediatorService.Subscribe(this, AddToNewCuratedListMessageRecv ); + _mediatorService.Subscribe(this, AddToCuratedListMessageRecv ); _framework.Update += OnUpdate; } @@ -88,12 +90,24 @@ private void AddToCraftListMessageRecv(AddToCraftListMessage obj) } } + private void AddToCuratedListMessageRecv(AddToCuratedListMessage obj) + { + var filter = GetListByKey(obj.FilterKey); + filter?.AddCuratedItem(new CuratedItem(obj.ItemId, obj.Quantity, obj.Flags)); + } + private void AddToNewCraftListMessageRecv(AddToNewCraftListMessage obj) { var craftList = AddNewCraftList(null, obj.IsEphemeral); craftList.CraftList.AddCraftItem(obj.ItemId, obj.Quantity, obj.Flags); } + private void AddToNewCuratedListMessageRecv(AddToNewCuratedListMessage obj) + { + var craftList = AddNewCuratedList(); + craftList.AddCuratedItem(new CuratedItem(obj.ItemId, obj.Quantity, obj.Flags)); + } + private ConcurrentDictionary LoadListsFromConfiguration() { var savedLists = _configuration.GetSavedFilters(); diff --git a/InventoryTools/Lists/TableService.cs b/InventoryTools/Lists/TableService.cs index a9e08067..6ecaf4f6 100644 --- a/InventoryTools/Lists/TableService.cs +++ b/InventoryTools/Lists/TableService.cs @@ -28,7 +28,7 @@ public class TableService : DisposableMediatorBackgroundService public delegate void TableRefreshedDelegate(RenderTableBase table); public event TableRefreshedDelegate TableRefreshed; public IBackgroundTaskQueue TableQueue { get; } - + public TableService(ILogger logger, MediatorService mediatorService, IListService listService, IBackgroundTaskQueue filterQueue, IFramework framework, Func craftItemTableFactory, Func filterTableFactory) : base(logger, mediatorService) { _listService = listService; @@ -110,13 +110,13 @@ public void RefreshCraftColumns(RenderTableBase renderTableBase, CancellationTok public async Task RefreshTable(CraftItemTable craftItemTable, CancellationToken cancellationToken) { var filterConfiguration = craftItemTable.FilterConfiguration; - + RefreshCraftColumns(craftItemTable, cancellationToken); - + if (filterConfiguration.SearchResults != null && filterConfiguration.CraftList.BeenGenerated && filterConfiguration.CraftList.BeenUpdated) { Logger.LogTrace("CraftTable: Refreshing"); - craftItemTable.CraftItems = filterConfiguration.CraftList.GetFlattenedMergedMaterials(true).Select(c => new SearchResult(c)).ToList(); + craftItemTable.CraftItems = filterConfiguration.CraftList.GetFlattenedMergedMaterials().Select(c => new SearchResult(c)).ToList(); filterConfiguration.CraftList.ClearGroupCache(); var outputList = filterConfiguration.CraftList.GetOutputList(); craftItemTable.CraftGroups = outputList.Select(c => (c, c.CraftItems.Select(d => new SearchResult(d)).ToList())).ToList(); @@ -124,7 +124,7 @@ public async Task RefreshTable(CraftItemTable craftItemTable, CancellationToken craftItemTable.NeedsRefresh = false; craftItemTable.Refreshing = false; TableRefreshed?.Invoke(craftItemTable); - } + } else { craftItemTable.NeedsRefresh = false; @@ -135,13 +135,13 @@ public async Task RefreshTable(CraftItemTable craftItemTable, CancellationToken public async Task RefreshTable(FilterTable filterTable, CancellationToken cancellationToken) { RefreshColumns(filterTable, cancellationToken); - + var filterConfiguration = filterTable.FilterConfiguration; if (filterConfiguration.SearchResults != null) { - if (filterConfiguration.FilterType == FilterType.SearchFilter - || filterConfiguration.FilterType == FilterType.SortingFilter + if (filterConfiguration.FilterType == FilterType.SearchFilter + || filterConfiguration.FilterType == FilterType.SortingFilter || filterConfiguration.FilterType == FilterType.CraftFilter) { var items = filterConfiguration.SearchResults.AsEnumerable(); @@ -246,10 +246,10 @@ public async Task RefreshTable(FilterTable filterTable, CancellationToken cancel } - + public CraftItemTable GetCraftTable(FilterConfiguration configuration) { - + var filterKey = configuration.Key; if (!_craftItemTables.ContainsKey(filterKey)) { @@ -316,7 +316,7 @@ public void InvalidateTables(FilterConfiguration filterConfiguration) } } } - + public Task RequestRefresh(FilterTable filterTable) { if (filterTable is { NeedsRefresh: true, Refreshing: false, FilterConfiguration.AllowRefresh: true }) @@ -327,7 +327,7 @@ public Task RequestRefresh(FilterTable filterTable) return Task.CompletedTask; } - + public Task RequestRefresh(CraftItemTable craftItemTable) { if (craftItemTable is { NeedsRefresh: true, Refreshing: false, FilterConfiguration.AllowRefresh: true }) @@ -338,12 +338,12 @@ public Task RequestRefresh(CraftItemTable craftItemTable) return Task.CompletedTask; } - + private async Task BackgroundProcessing(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { - var workItem = + var workItem = await TableQueue.DequeueAsync(stoppingToken); try @@ -352,7 +352,7 @@ private async Task BackgroundProcessing(CancellationToken stoppingToken) } catch (Exception ex) { - Logger.LogError(ex, + Logger.LogError(ex, "Error occurred executing {WorkItem}.", nameof(workItem)); } } diff --git a/InventoryTools/Logic/Columns/CraftAmountRequiredColumn.cs b/InventoryTools/Logic/Columns/CraftAmountRequiredColumn.cs index b2195399..32679c29 100644 --- a/InventoryTools/Logic/Columns/CraftAmountRequiredColumn.cs +++ b/InventoryTools/Logic/Columns/CraftAmountRequiredColumn.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using AllaganLib.GameSheets.Sheets; using CriticalCommonLib.Crafting; using CriticalCommonLib.Services.Mediator; - +using DalaMock.Shared.Interfaces; +using Dalamud.Interface; using ImGuiNET; using InventoryTools.Logic.Columns.Abstract; using InventoryTools.Services; @@ -14,8 +16,13 @@ namespace InventoryTools.Logic.Columns { public class CraftAmountRequiredColumn : DoubleIntegerColumn { - public CraftAmountRequiredColumn(ILogger logger, ImGuiService imGuiService) : base(logger, imGuiService) + private readonly IFont _font; + private readonly ItemSheet _itemSheet; + + public CraftAmountRequiredColumn(ILogger logger, ImGuiService imGuiService, IFont font, ItemSheet itemSheet) : base(logger, imGuiService) { + _font = font; + _itemSheet = itemSheet; } public override ColumnCategory ColumnCategory => ColumnCategory.Crafting; @@ -38,6 +45,9 @@ public override (int, int)? CurrentValue(ColumnConfiguration columnConfiguration ImGui.TableNextColumn(); if (!ImGui.TableGetColumnFlags().HasFlag(ImGuiTableColumnFlags.IsEnabled)) return null; + var originalCursorPosY = ImGui.GetCursorPosY(); + var itemHovered = false; + if (searchResult.CraftItem.IsOutputItem) { if (configuration.CraftList.CraftListMode == CraftListMode.Normal) @@ -94,13 +104,7 @@ public override (int, int)? CurrentValue(ColumnConfiguration columnConfiguration if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { - using (var tooltip = ImRaii.Tooltip()) - { - if (tooltip) - { - ImGui.Text("The amount you currently have in your inventory."); - } - } + itemHovered = true; } var toStock = searchResult.CraftItem.QuantityToStock.ToString(); @@ -139,6 +143,50 @@ public override (int, int)? CurrentValue(ColumnConfiguration columnConfiguration { ImGuiUtil.VerticalAlignText(searchResult.CraftItem.QuantityNeeded + "/" + searchResult.CraftItem.QuantityNeededPreUpdate, configuration.TableHeight, false); } + ImGui.SameLine(); + ImGui.SetCursorPosY(originalCursorPosY); + ImGui.PushFont(_font.IconFont); + ImGuiUtil.VerticalAlignTextDisabled(FontAwesomeIcon.InfoCircle.ToIconString(), configuration.TableHeight, false); + ImGui.PopFont(); + if (itemHovered || ImGui.IsItemHovered(ImGuiHoveredFlags.None)) + { + using var tt = ImRaii.Tooltip(); + ImGui.Text("Ingredient Breakdown:"); + ImGui.TextUnformatted("Amount Originally Required: " + searchResult.CraftItem.QuantityRequired); + ImGui.TextUnformatted("Amount Required: " + searchResult.CraftItem.QuantityNeededPreUpdate); + ImGui.TextUnformatted("Amount in Inventory: " + searchResult.CraftItem.QuantityReady); + ImGui.TextUnformatted("Amount to Retrieve: " + searchResult.CraftItem.QuantityAvailable); + ImGui.Separator(); + ImGui.TextUnformatted("Amount Missing: " + searchResult.CraftItem.QuantityMissingOverall); + if (searchResult.Item.CanBeCrafted) + { + ImGui.TextUnformatted("Amount Craftable: " + searchResult.CraftItem.QuantityCanCraft); + if (searchResult.CraftItem.Yield != 1) + { + ImGui.Separator(); + ImGui.TextUnformatted("Craft Operations Required: " + + searchResult.CraftItem.QuantityNeeded / searchResult.CraftItem.Yield); + ImGui.TextUnformatted("Recipe Yield: " + searchResult.CraftItem.Yield); + } + } + + + if (searchResult.CraftItem.Recipe != null) + { + ImGui.Separator(); + ImGui.TextUnformatted("Ingredients: "); + using (ImRaii.PushIndent()) + { + foreach (var ingredient in searchResult.CraftItem.Ingredients) + { + var item = _itemSheet.GetRow(ingredient.Key.Item1); + var quantityRequired = ingredient.Value; + ImGui.TextUnformatted(item.NameString + ": " + quantityRequired); + } + } + } + + } return null; } public override FilterType AvailableIn { get; } = Logic.FilterType.CraftFilter; diff --git a/InventoryTools/Logic/Columns/IColumn.cs b/InventoryTools/Logic/Columns/IColumn.cs index 347c92f4..6b45ae3c 100644 --- a/InventoryTools/Logic/Columns/IColumn.cs +++ b/InventoryTools/Logic/Columns/IColumn.cs @@ -49,7 +49,6 @@ public IEnumerable Sort(ColumnConfiguration columnConfiguration, I public void SetupFilter(string tableKey) { - ImGui.TableSetupColumn(tableKey + "Filter" + Name, ImGuiTableColumnFlags.NoSort); } public IFilterEvent? DrawFooterFilter(ColumnConfiguration columnConfiguration, FilterTable filterTable); diff --git a/InventoryTools/Logic/Columns/IconColumn.cs b/InventoryTools/Logic/Columns/IconColumn.cs index 63db05f4..24fc2bec 100644 --- a/InventoryTools/Logic/Columns/IconColumn.cs +++ b/InventoryTools/Logic/Columns/IconColumn.cs @@ -2,6 +2,7 @@ using System.Numerics; using CriticalCommonLib.Services.Mediator; using Dalamud.Game.ClientState.Keys; +using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Services; using ImGuiNET; using InventoryTools.Logic.Columns.Abstract; @@ -56,23 +57,28 @@ public override IEnumerable Sort(ColumnConfiguration columnConfigu var messages = new List(); if (currentValue != null) { - ImGui.PushID("icon" + rowIndex); - if (ImGui.ImageButton(ImGuiService.GetIconTexture(currentValue.Value.Item1, currentValue.Value.Item2).ImGuiHandle, new Vector2(filterConfiguration.TableHeight - 1, filterConfiguration.TableHeight - 1) * ImGui.GetIO().FontGlobalScale,new Vector2(0,0), new Vector2(1,1), 2)) + using (ImRaii.PushId("icon" + rowIndex)) { - ImGui.PopID(); - if (!this._keyState[VirtualKey.CONTROL] && !this._keyState[VirtualKey.SHIFT] && !this._keyState[VirtualKey.MENU]) + if (ImGui.ImageButton( + ImGuiService.GetIconTexture(currentValue.Value.Item1, currentValue.Value.Item2).ImGuiHandle, + new Vector2(filterConfiguration.TableHeight - 1, filterConfiguration.TableHeight - 1) * + ImGui.GetIO().FontGlobalScale, new Vector2(0, 0), new Vector2(1, 1), 2)) { - messages.Add(new OpenUintWindowMessage(typeof(ItemWindow), searchResult.Item.RowId)); + if (!this._keyState[VirtualKey.CONTROL] && !this._keyState[VirtualKey.SHIFT] && + !this._keyState[VirtualKey.MENU]) + { + messages.Add(new OpenUintWindowMessage(typeof(ItemWindow), searchResult.Item.RowId)); + } } - } - if (_tooltipModeSetting.CurrentValue(_configuration) == ImGuiTooltipMode.Icons) - { - if (ImGui.IsItemHovered()) + + if (_tooltipModeSetting.CurrentValue(_configuration) == ImGuiTooltipMode.Icons) { - _tooltipService.DrawItemTooltip(searchResult); + if (ImGui.IsItemHovered()) + { + _tooltipService.DrawItemTooltip(searchResult); + } } } - ImGui.PopID(); } return messages; diff --git a/InventoryTools/Logic/CraftItemTable.cs b/InventoryTools/Logic/CraftItemTable.cs index 359f2152..34618117 100644 --- a/InventoryTools/Logic/CraftItemTable.cs +++ b/InventoryTools/Logic/CraftItemTable.cs @@ -92,8 +92,9 @@ public override List Draw(Vector2 size, bool shouldDraw = true) using var tabItem = ImRaii.TabItem( groupedCraft.Item1.FormattedName()); if (!tabItem.Success) continue; + if (Columns.Count == 0) continue; using var table = ImRaii.Table(Key + "CraftTable", Columns.Count, _tableFlags); - if (!table.Success || Columns.Count == 0) continue; + if (!table.Success) continue; var refresh = false; ImGui.TableSetupScrollFreeze(Math.Min(FreezeCols ?? 0, Columns.Count), FreezeRows ?? (ShowFilterRow ? 2 : 1)); diff --git a/InventoryTools/Logic/Features/ContextMenuFeature.cs b/InventoryTools/Logic/Features/ContextMenuFeature.cs index 8b99b28c..5bec5ddb 100644 --- a/InventoryTools/Logic/Features/ContextMenuFeature.cs +++ b/InventoryTools/Logic/Features/ContextMenuFeature.cs @@ -11,6 +11,7 @@ public ContextMenuFeature(IEnumerable settings) : base(new[] typeof(ContextMenuMoreInformationSetting), typeof(ContextMenuAddToCraftListSetting), typeof(ContextMenuAddToActiveCraftListSetting), + typeof(ContextMenuAddToCuratedListSetting), typeof(ContextMenuOpenCraftingLogSetting), typeof(ContextMenuOpenGatheringLogSetting), typeof(ContextMenuOpenFishingLogSetting), diff --git a/InventoryTools/Logic/FilterState.cs b/InventoryTools/Logic/FilterState.cs index f7bebacb..26ceeda2 100644 --- a/InventoryTools/Logic/FilterState.cs +++ b/InventoryTools/Logic/FilterState.cs @@ -2,7 +2,9 @@ using System.Collections.Immutable; using System.Linq; using System.Numerics; +using AllaganLib.GameSheets.Model; using CriticalCommonLib; +using CriticalCommonLib.Crafting; using CriticalCommonLib.Enums; using CriticalCommonLib.Extensions; using CriticalCommonLib.Models; @@ -183,80 +185,65 @@ public bool ShouldHighlight } } - public List GetSelectIconStringItems(List? resultOverride = null) + public List GetSelectIconStringItems(List shops, List? resultOverride = null) { var itemHighlights = new List(); - return itemHighlights; - //TODO: Rework - - // if (_characterMonitor.ActiveCharacterId == 0) - // { - // return itemHighlights; - // } - // var filterResult = resultOverride ?? FilterResult; - // if (filterResult != null) - // { - // HashSet requiredItems; - // if (FilterConfiguration.FilterType == FilterType.CraftFilter) - // { - // _logger.LogTrace("Craft filter, getting flattened materials"); - // requiredItems = FilterConfiguration.CraftList.GetFlattenedMaterials().Select(c => c.Item.RowId).Distinct() - // .ToHashSet(); - // } - // else if (filterResult.Count != 0) - // { - // requiredItems = filterResult.Select(c => c.Item.RowId).Distinct().ToHashSet(); - // } - // else - // { - // return itemHighlights; - // } - // - // - // var target = Service.Targets.Target; - // if (target != null) - // { - // _logger.LogTrace("Target found for SelectIconString"); - // - // var npcId = target.DataId; - // var npc = _excelCache.ENpcCollection?.Get(npcId); - // if (npc != null && npc.Base != null) - // { - // _logger.LogTrace("NPC found for SelectIconString"); - // //TODO: Probably need to deal with custom talk and shit - // for (var index = 0; index < npc.Base.ENpcData.Length; index++) - // { - // var talkItem = npc.Base.ENpcData[index]; - // var preHandler = _excelCache.GetPreHandlerSheet().GetRow(talkItem); - // if (preHandler != null) - // { - // talkItem = preHandler.Target; - // } - // var shop = _excelCache.ShopCollection?.GetShop(talkItem); - // if (shop != null) - // { - // _logger.LogTrace("Shop found for SelectIconString"); - // var shouldHighlight = shop.Items.Any(c => requiredItems.Contains(c.Row)); - // if (shouldHighlight) - // { - // _logger.LogTrace("Found item for shop" + shop.RowId); - // itemHighlights.Add(FilterConfiguration.RetainerListColor ?? _configuration.RetainerListColor); - // } - // else - // { - // _logger.LogTrace("Did not find item for shop" + shop.RowId); - // itemHighlights.Add(null); - // } - // } - // } - // } - // } - // return itemHighlights; - // } + if (_characterMonitor.ActiveCharacterId == 0) + { + return itemHighlights; + } + var filterResult = resultOverride ?? FilterResult; + if (filterResult != null) + { + HashSet requiredItems; + if (FilterConfiguration.FilterType == FilterType.CraftFilter) + { + requiredItems = FilterConfiguration.CraftList.GetFlattenedMergedMaterials().Where(c => c.IngredientPreference.Type is IngredientPreferenceType.Buy or IngredientPreferenceType.Item or IngredientPreferenceType.HouseVendor ).Select(c => c.Item.RowId).Distinct() + .ToHashSet(); + } + else if (filterResult.Count != 0) + { + requiredItems = filterResult.Select(c => c.Item.RowId).Distinct().ToHashSet(); + } + else + { + requiredItems = new HashSet(); + } + + foreach (var shop in shops) + { + var shouldHighlight = shop.Items.Any(c => requiredItems.Contains(c.RowId)); + itemHighlights.Add(shouldHighlight ? FilterConfiguration.RetainerListColor ?? _configuration.RetainerListColor : null); + } + } return itemHighlights; } + public HashSet GetItemIds(List? resultOverride = null) + { + var itemIds = new HashSet(); + if (_characterMonitor.ActiveCharacterId == 0) + { + return itemIds; + } + var filterResult = resultOverride ?? FilterResult; + if (filterResult != null) + { + if (FilterConfiguration.FilterType == FilterType.CraftFilter) + { + itemIds = FilterConfiguration.CraftList.GetFlattenedMergedMaterials().Where(c => c.IngredientPreference.Type is IngredientPreferenceType.Buy or IngredientPreferenceType.Item or IngredientPreferenceType.HouseVendor).Select(c => c.Item.RowId).Distinct() + .ToHashSet(); + } + else if (filterResult.Count != 0) + { + itemIds = filterResult.Select(c => c.Item.RowId).Distinct().ToHashSet(); + } + } + + return itemIds; + } + public Dictionary GetArmoireHighlights(List? resultOverride = null) { var bagHighlights = new Dictionary(); diff --git a/InventoryTools/Logic/Filters/CanBeEquippedFilter.cs b/InventoryTools/Logic/Filters/CanBeEquippedFilter.cs index d97cc726..d58bf08d 100644 --- a/InventoryTools/Logic/Filters/CanBeEquippedFilter.cs +++ b/InventoryTools/Logic/Filters/CanBeEquippedFilter.cs @@ -33,6 +33,11 @@ public class CanBeEquippedFilter : BooleanFilter return true; } + if (!currentValue.Value && item.Base.EquipSlotCategory.RowId == 0) + { + return true; + } + return false; } diff --git a/InventoryTools/Logic/Filters/FavouritesFilter.cs b/InventoryTools/Logic/Filters/FavouritesFilter.cs index bed4047a..9ca21483 100644 --- a/InventoryTools/Logic/Filters/FavouritesFilter.cs +++ b/InventoryTools/Logic/Filters/FavouritesFilter.cs @@ -20,7 +20,7 @@ public class FavouritesFilter : BooleanFilter var currentValue = CurrentValue(configuration); if (currentValue != null) { - return currentValue.Value && _configuration.IsFavouriteItem(item.ItemId); + return currentValue.Value && _configuration.IsFavouriteItem(item.ItemId) || !currentValue.Value && !_configuration.IsFavouriteItem(item.ItemId); } return null; @@ -31,7 +31,7 @@ public class FavouritesFilter : BooleanFilter var currentValue = CurrentValue(configuration); if (currentValue != null) { - return currentValue.Value && _configuration.IsFavouriteItem(item.RowId); + return currentValue.Value && _configuration.IsFavouriteItem(item.RowId) || !currentValue.Value && !_configuration.IsFavouriteItem(item.RowId); } return null; diff --git a/InventoryTools/Logic/ItemRenderers/ItemGardeningCrossbreedSourceRenderer.cs b/InventoryTools/Logic/ItemRenderers/ItemGardeningCrossbreedSourceRenderer.cs new file mode 100644 index 00000000..469f7141 --- /dev/null +++ b/InventoryTools/Logic/ItemRenderers/ItemGardeningCrossbreedSourceRenderer.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using AllaganLib.GameSheets.Caches; +using AllaganLib.GameSheets.ItemSources; +using CriticalCommonLib.Models; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace InventoryTools.Logic.ItemRenderers; + +public class ItemGardeningCrossbreedSourceRenderer : ItemInfoRenderer +{ + public override RendererType RendererType => RendererType.Source; + public override ItemInfoType Type => ItemInfoType.GardeningCrossbreed; + public override string SingularName => "Gardening Crossbreed"; + public override string HelpText => "Is this item created by crossbreeding 2 seeds?"; + public override bool ShouldGroup => true; + + public override Action DrawTooltip => source => + { + var asSource = AsSource(source); + ImGui.Text($"Result: {asSource.SeedResult.NameString}"); + ImGui.Text($"{asSource.Seed1.NameString} + {asSource.Seed2.NameString}"); + }; + public override Func GetName => source => + { + var asSource = AsSource(source); + return $"{asSource.SeedResult.NameString} - {asSource.Seed1.NameString} + {asSource.Seed2.NameString}"; + }; + + public override Action>? DrawTooltipGrouped => sources => + { + var actualSources = AsSource(sources); + ImGui.Text("Crossbreeds:"); + var chunkedSources = actualSources.OrderBy(c =>c.Seed1.NameString).Chunk(actualSources.Count / MaxColumns); + using (var table = ImRaii.Table("CrossbreedTable", this.MaxColumns, ImGuiTableFlags.SizingStretchProp)) + { + if (table) + { + ImGui.TableNextRow(); + foreach (var chunkedSource in chunkedSources) + { + ImGui.TableNextColumn(); + foreach (var source in chunkedSource) + { + ImGui.Text($"{source.Seed1.NameString} + {source.Seed2.NameString}"); + } + } + } + } + // + // using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, new Vector2(5, 5)); + // using (var table = ImRaii.Table("CrossbreedTable", this.MaxColumns, ImGuiTableFlags.SizingStretchProp)) + // { + // if (table) + // { + // ImGui.TableNextRow(); + // var count = 0; + // foreach (var groupedSource in actualSources.GroupBy(c => c.Seed1).OrderBy(c => c.Key.NameString)) + // { + // ImGui.TableNextColumn(); + // foreach (var source in groupedSource) + // { + // ImGui.Text($"{source.Seed1.NameString} + {source.Seed2.NameString}"); + // } + // count++; + // if (count == this.MaxColumns) + // { + // count = 0; + // ImGui.TableNextRow(); + // } + // } + // } + // } + }; + + public override Func GetIcon => _ => Icons.SeedBagIcon; +} + +public class ItemGardeningCrossbreedSourceUseRenderer : ItemGardeningCrossbreedSourceRenderer +{ + public override RendererType RendererType => RendererType.Use; + public override string SingularName => "Gardening Crossbreed Seed"; + public override string HelpText => "Is this item part of a crossbreed when gardening?"; +} \ No newline at end of file diff --git a/InventoryTools/Logic/ItemRenderers/ItemMonsterDropSourceRenderer.cs b/InventoryTools/Logic/ItemRenderers/ItemMonsterDropSourceRenderer.cs index fec5fa78..7cc38642 100644 --- a/InventoryTools/Logic/ItemRenderers/ItemMonsterDropSourceRenderer.cs +++ b/InventoryTools/Logic/ItemRenderers/ItemMonsterDropSourceRenderer.cs @@ -81,7 +81,7 @@ public ItemMonsterDropSourceRenderer(TerritoryTypeSheet territoryTypeSheet, MapS foreach (var npcGroup in positionsGroupedByNpcId) { - ImGui.Text("Monster: " + _bnpcNameSheet.GetRow(npcGroup.Key).Base.Singular.ExtractText().ToTitleCase()); + ImGui.Text("Map: " + _mapSheet.GetRow(npcGroup.Key).FormattedName); ImGui.Text("Locations:"); using (ImRaii.PushIndent()) { diff --git a/InventoryTools/Logic/Settings/ContextMenuAddToCuratedListSetting.cs b/InventoryTools/Logic/Settings/ContextMenuAddToCuratedListSetting.cs new file mode 100644 index 00000000..23634a15 --- /dev/null +++ b/InventoryTools/Logic/Settings/ContextMenuAddToCuratedListSetting.cs @@ -0,0 +1,22 @@ +using InventoryTools.Logic.Settings.Abstract; +using InventoryTools.Logic.Settings.Abstract.Generic; +using InventoryTools.Services; +using Microsoft.Extensions.Logging; + +namespace InventoryTools.Logic.Settings; + +public class ContextMenuAddToCuratedListSetting : GenericBooleanSetting +{ + public ContextMenuAddToCuratedListSetting(ILogger logger, + ImGuiService imGuiService) : base("AddToCuratedListContextMenu", + "Context Menu - Add to Curated List", + "Add a submenu to add the item to a curated list?", + false, + SettingCategory.ContextMenu, + SettingSubCategory.General, + "1.7.0.21", + logger, + imGuiService) + { + } +} \ No newline at end of file diff --git a/InventoryTools/Mediator/Messages.cs b/InventoryTools/Mediator/Messages.cs index 82ee3955..bc1caa0f 100644 --- a/InventoryTools/Mediator/Messages.cs +++ b/InventoryTools/Mediator/Messages.cs @@ -33,7 +33,9 @@ public record ListUpdatedMessage(FilterConfiguration FilterConfiguration) : Mess public record RequestListUpdateMessage(FilterConfiguration FilterConfiguration) : MessageBase; public record TeamCraftDataImported(List<(uint, uint)> listData) : MessageBase; public record AddToCraftListMessage(string FilterKey, uint ItemId, uint Quantity, InventoryItem.ItemFlags Flags) : MessageBase; +public record AddToCuratedListMessage(string FilterKey, uint ItemId, uint Quantity, InventoryItem.ItemFlags Flags) : MessageBase; public record AddToNewCraftListMessage(uint ItemId, uint Quantity, InventoryItem.ItemFlags Flags, bool IsEphemeral) : MessageBase; +public record AddToNewCuratedListMessage(uint ItemId, uint Quantity, InventoryItem.ItemFlags Flags) : MessageBase; public record FocusListMessage(Type windowType, FilterConfiguration FilterConfiguration) : MessageBase; public record RequestTeleportMessage(uint aetheryteId) : MessageBase; public record RequestTeleportToTerritoryMessage(uint territoryTypeId, Vector2 mapCoordinates) : MessageBase; diff --git a/InventoryTools/Overlays/InventoryShopOverlay.cs b/InventoryTools/Overlays/InventoryShopOverlay.cs new file mode 100644 index 00000000..d8b6b0cd --- /dev/null +++ b/InventoryTools/Overlays/InventoryShopOverlay.cs @@ -0,0 +1,61 @@ +using System.Linq; +using CriticalCommonLib.Services.Ui; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Plugin.Services; +using InventoryTools.Highlighting; +using InventoryTools.Logic; +using Microsoft.Extensions.Logging; + +namespace InventoryTools.Overlays; + +public class InventoryShopOverlay : GameOverlay, IAtkOverlayState +{ + private readonly ShopHighlighting _shopHighlighting; + + public InventoryShopOverlay(ILogger logger, ShopHighlighting shopHighlighting, AtkShop overlay) : base(logger, overlay) + { + _shopHighlighting = shopHighlighting; + } + + + public override bool ShouldDraw { get; set; } + public override bool Draw() + { + if (!HasState || !AtkOverlay.HasAddon) + { + return false; + } + + return true; + } + + public override void Setup() + { + } + + public override bool HasState { get; set; } + public override bool NeedsStateRefresh { get; set; } + public override void UpdateState(FilterState? newState) + { + if (newState != null && newState.FilterResult != null) + { + HasState = true; + Clear(); + _shopHighlighting.SetItems(newState.GetItemIds()); + return; + } + + if (HasState) + { + Clear(); + } + + HasState = false; + } + + public override void Clear() + { + this._shopHighlighting.ClearItems(); + } +} \ No newline at end of file diff --git a/InventoryTools/Overlays/SelectIconStringOverlay.cs b/InventoryTools/Overlays/SelectIconStringOverlay.cs index 2960c409..785ce50a 100644 --- a/InventoryTools/Overlays/SelectIconStringOverlay.cs +++ b/InventoryTools/Overlays/SelectIconStringOverlay.cs @@ -1,20 +1,36 @@ +using System; using System.Collections.Generic; using System.Numerics; using CriticalCommonLib.Services; using CriticalCommonLib.Services.Ui; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Plugin.Services; using InventoryTools.Logic; +using InventoryTools.Services; using Microsoft.Extensions.Logging; namespace InventoryTools.Overlays { - public class SelectIconStringOverlay: GameOverlay, IAtkOverlayState + public class SelectIconStringOverlay: GameOverlay, IAtkOverlayState, IDisposable { private readonly ICharacterMonitor _characterMonitor; + private readonly ShopTrackerService _shopTrackerService; + private readonly IAddonLifecycle _addonLifecycle; - public SelectIconStringOverlay(ILogger logger, AtkSelectIconString overlay, ICharacterMonitor characterMonitor) : base(logger,overlay) + public SelectIconStringOverlay(ILogger logger, AtkSelectIconString overlay, ICharacterMonitor characterMonitor, ShopTrackerService shopTrackerService, IAddonLifecycle addonLifecycle) : base(logger,overlay) { _characterMonitor = characterMonitor; + _shopTrackerService = shopTrackerService; + _addonLifecycle = addonLifecycle; + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, this.WindowName.ToString(),AddonPostSetup); } + + private void AddonPostSetup(AddonEvent type, AddonArgs args) + { + NeedsStateRefresh = true; + } + public override bool ShouldDraw { get; set; } public override bool Draw() @@ -34,7 +50,7 @@ public override bool Draw() return false; } - + public List SelectItems = new(); public override void Setup() @@ -58,13 +74,21 @@ public override void UpdateState(FilterState? newState) if (filterResult != null) { Logger.LogTrace("Attempting to update state for SelectIconString"); + var currentShopTypes = _shopTrackerService.GetCurrentShopType(); + if (currentShopTypes != null) + { + SelectItems = newState.GetSelectIconStringItems(currentShopTypes.Value.shops); + } + else + { + SelectItems = new List(); + } - SelectItems = newState.GetSelectIconStringItems(); Draw(); return; } } - + if (HasState) { Logger.LogTrace("Clearing select items"); @@ -83,5 +107,20 @@ public override void Clear() this.AtkOverlay.ResetColors(); } } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, this.WindowName.ToString(),AddonPostSetup); + } + } + + public new void Dispose() + { + Dispose(true); + base.Dispose(); + GC.SuppressFinalize(this); + } } } \ No newline at end of file diff --git a/InventoryTools/PluginLogic.cs b/InventoryTools/PluginLogic.cs index d59dce1f..144e1e19 100644 --- a/InventoryTools/PluginLogic.cs +++ b/InventoryTools/PluginLogic.cs @@ -221,6 +221,8 @@ public void LoadDefaultData() AddFreeCompanyFilter(); + AddHousingFilter(); + AddAllGameItemsFilter(); AddFavouritesFilter(); @@ -280,6 +282,15 @@ public void AddFreeCompanyFilter(string newName = "Free Company") _listService.AddList(newFilter); } + public void AddHousingFilter(string newName = "Housing") + { + var newFilter = new FilterConfiguration(newName, FilterType.SearchFilter); + newFilter.DisplayInTabs = true; + newFilter.SourceAllHouses = true; + _listService.AddDefaultColumns(newFilter); + _listService.AddList(newFilter); + } + public void AddAllGameItemsFilter(string newName = "All Game Items") { var allGameItemsFilter = new FilterConfiguration(newName, FilterType.GameItemFilter); @@ -369,7 +380,7 @@ private void InventoryMonitorOnOnInventoryChanged(List inventor { _logger.LogTrace("PluginLogic: Inventory changed, saving to config."); var allItems = _inventoryMonitor.AllItems.ToList(); - _configurationManagerService.SaveInventories(allItems); + _configurationManagerService.SaveInventoriesAsync(allItems); if (_configuration.AutomaticallyDownloadMarketPrices) { var activeCharacter = _characterMonitor.ActiveCharacter; @@ -438,7 +449,7 @@ public Task StopAsync(CancellationToken cancellationToken) _craftMonitor.CraftCompleted -= CraftMonitorOnCraftCompleted ; _configurationManagerService.ConfigurationChanged -= ConfigOnConfigurationChanged; _configurationManagerService.Save(); - _configurationManagerService.SaveInventories(_inventoryMonitor.AllItems.ToList()); + _configurationManagerService.SaveInventoriesAsync(_inventoryMonitor.AllItems.ToList()).Wait(TimeSpan.FromSeconds(2)); _configurationManagerService.SaveHistory(_hostedInventoryHistory.GetHistory()); if (_configuration.TrackMobSpawns) { diff --git a/InventoryTools/Services/ConfigurationManagerService.cs b/InventoryTools/Services/ConfigurationManagerService.cs index 1271cc11..e6aa373b 100644 --- a/InventoryTools/Services/ConfigurationManagerService.cs +++ b/InventoryTools/Services/ConfigurationManagerService.cs @@ -29,6 +29,7 @@ public class ConfigurationManagerService : BackgroundService public delegate void ConfigurationChangedDelegate(); private readonly IFramework _framework; private bool _configurationLoaded = false; + private Task? _currentInventorySaveTask = null; public event ConfigurationChangedDelegate? ConfigurationChanged; @@ -309,6 +310,15 @@ public void SaveInventoriesToJson( } + public Task SaveInventoriesAsync(List items) + { + if (_currentInventorySaveTask == null || _currentInventorySaveTask.IsCompleted || _currentInventorySaveTask.IsFaulted) + { + _currentInventorySaveTask = Task.Run(() => SaveInventories(items)); + } + return _currentInventorySaveTask; + } + public bool SaveInventories(List items) { return CsvLoader.ToCsvRaw(items, Path.Join(_pluginInterfaceService.ConfigDirectory.FullName, "inventories.csv")); diff --git a/InventoryTools/Services/ContextMenuService.cs b/InventoryTools/Services/ContextMenuService.cs index d3b7e7f2..10cd241a 100644 --- a/InventoryTools/Services/ContextMenuService.cs +++ b/InventoryTools/Services/ContextMenuService.cs @@ -13,6 +13,7 @@ using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using InventoryTools.Logic; +using InventoryTools.Logic.Settings; using InventoryTools.Mediator; using InventoryTools.Services.Interfaces; using InventoryTools.Ui; @@ -29,6 +30,7 @@ public class ContextMenuService : DisposableMediatorSubscriberBase, IHostedServi private readonly InventoryToolsConfiguration _configuration; private readonly ItemSheet _itemSheet; private readonly IGameInterface _gameInterface; + private readonly ContextMenuAddToCuratedListSetting _curatedListSetting; public const int SatisfactionSupplyItemIdx = 84; public const int SatisfactionSupplyItem1Id = 128 + 1 * 60; public const int SatisfactionSupplyItem2Id = 128 + 2 * 60; @@ -48,7 +50,7 @@ public class ContextMenuService : DisposableMediatorSubscriberBase, IHostedServi public const int GrandCompanySupplyListContextItemId = 84; public const int GrandCompanyExchangeContextItemId = 84; - public ContextMenuService(ILogger logger, IListService listService, IContextMenu contextMenu, IGameGui gameGui, MediatorService mediatorService, InventoryToolsConfiguration configuration, ItemSheet itemSheet, IGameInterface gameInterface) : base(logger, mediatorService) + public ContextMenuService(ILogger logger, IListService listService, IContextMenu contextMenu, IGameGui gameGui, MediatorService mediatorService, InventoryToolsConfiguration configuration, ItemSheet itemSheet, IGameInterface gameInterface, ContextMenuAddToCuratedListSetting curatedListSetting) : base(logger, mediatorService) { ContextMenu = contextMenu; _listService = listService; @@ -56,6 +58,7 @@ public ContextMenuService(ILogger logger, IListService listS _configuration = configuration; _itemSheet = itemSheet; _gameInterface = gameInterface; + _curatedListSetting = curatedListSetting; } private void MenuOpened(IMenuOpenedArgs args) @@ -110,6 +113,17 @@ private void MenuOpened(IMenuOpenedArgs args) args.AddMenuItem(menuItem); } + if (_curatedListSetting.CurrentValue(_configuration)) + { + var menuItem = new MenuItem(); + menuItem.Name = "Add to Curated List"; + menuItem.PrefixChar = 'A'; + menuItem.IsSubmenu = true; + menuItem.OnClicked += clickedArgs => OpenAddCuratedListSubmenu(clickedArgs, itemId); + args.AddMenuItem(menuItem); + } + + if (_configuration.OpenCraftingLogContextMenu) { var item = _itemSheet.GetRowOrDefault(itemId.Value); @@ -263,6 +277,29 @@ private void OpenAddCraftListSubmenu(IMenuItemClickedArgs obj, uint? itemId = nu obj.OpenSubmenu(menuItems); } + private void OpenAddCuratedListSubmenu(IMenuItemClickedArgs obj, uint? itemId = null) + { + var curatedLists = _listService.Lists.Where(c => c.FilterType == FilterType.CuratedList).ToList(); + var menuItems = new List(); + foreach (var curatedList in curatedLists) + { + var menuItem = new MenuItem(); + menuItem.Name = curatedList.Name; + menuItem.OnClicked += args => + { + AddToCuratedList(curatedList, args, itemId); + }; + menuItems.Add(menuItem); + } + + var newButton = new MenuItem(); + newButton.Name = "Add to New Curated List"; + newButton.OnClicked += args => AddToNewCuratedList(args, itemId); + menuItems.Add(newButton); + + obj.OpenSubmenu(menuItems); + } + private unsafe IntPtr AgentById(AgentId id) { var uiModule = (UIModule*)_gameGui.GetUIModule(); @@ -287,6 +324,22 @@ private void AddToNewCraftList(IMenuItemClickedArgs obj, uint? itemId = null) } } + private void AddToNewCuratedList(IMenuItemClickedArgs obj, uint? itemId = null) + { + if (obj.Target is MenuTargetInventory inventory) + { + if (inventory.TargetItem != null) + { + itemId ??= inventory.TargetItem.Value.ItemId; + MediatorService.Publish(new AddToNewCuratedListMessage(itemId.Value, 1, inventory.TargetItem.Value.IsHq ? InventoryItem.ItemFlags.HighQuality : InventoryItem.ItemFlags.None)); + } + } + else if(itemId != null) + { + MediatorService.Publish(new AddToNewCuratedListMessage(itemId.Value, 1, InventoryItem.ItemFlags.None)); + } + } + private void AddToNewEphemeralCraftList(IMenuItemClickedArgs obj, uint? itemId = null) { if (obj.Target is MenuTargetInventory inventory) @@ -319,6 +372,22 @@ private void AddToCraftList(FilterConfiguration craftList, IMenuItemClickedArgs } } + private void AddToCuratedList(FilterConfiguration craftList, IMenuItemClickedArgs obj, uint? itemId = null) + { + if (obj.Target is MenuTargetInventory inventory) + { + if (inventory.TargetItem != null) + { + itemId ??= inventory.TargetItem.Value.ItemId; + MediatorService.Publish(new AddToCuratedListMessage(craftList.Key, itemId.Value, 1, inventory.TargetItem.Value.IsHq ? InventoryItem.ItemFlags.HighQuality : InventoryItem.ItemFlags.None)); + } + } + else if(itemId != null) + { + MediatorService.Publish(new AddToCuratedListMessage(craftList.Key, itemId.Value, 1, InventoryItem.ItemFlags.None)); + } + } + private void MoreInformationClicked(IMenuItemClickedArgs obj, uint? itemId = null) { if (obj.Target is MenuTargetInventory inventory) diff --git a/InventoryTools/Services/ImGuiMenuService.cs b/InventoryTools/Services/ImGuiMenuService.cs index c9489c32..1204492d 100644 --- a/InventoryTools/Services/ImGuiMenuService.cs +++ b/InventoryTools/Services/ImGuiMenuService.cs @@ -534,7 +534,7 @@ public List DrawMenuItems(SearchResult searchResult, List c.Locations.Any(d => d.Map.RowId == groupedShop.Key)); var firstLocation = eNpcBaseRow?.Locations.FirstOrDefault(); if (firstLocation != null && eNpcBaseRow != null) { diff --git a/InventoryTools/Services/ShopTrackerService.cs b/InventoryTools/Services/ShopTrackerService.cs new file mode 100644 index 00000000..fb144c22 --- /dev/null +++ b/InventoryTools/Services/ShopTrackerService.cs @@ -0,0 +1,463 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using AllaganLib.GameSheets.Model; +using AllaganLib.GameSheets.Sheets; +using AllaganLib.GameSheets.Sheets.Rows; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Game.ClientState.Objects; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game.Event; +using FFXIVClientStructs.FFXIV.Client.UI; +using FFXIVClientStructs.FFXIV.Client.UI.Agent; +using InventoryTools.Enums; +using Lumina.Excel; +using Lumina.Excel.Sheets; + +namespace InventoryTools.Services; + +public class ShopTrackerService : IDisposable +{ + private readonly ITargetManager targetManager; + private readonly GilShopSheet _gilShopSheet; + private readonly SpecialShopSheet _specialShopSheet; + private readonly InclusionShopSheet _inclusionShopSheet; + private readonly FccShopSheet _fccShopSheet; + private readonly ENpcBaseSheet _enpcBaseSheet; + private readonly IAddonLifecycle _addonLifecycle; + private HashSet specialShops = new(); + private HashSet gilShops = new(); + private HashSet inclusionShops = new(); + private HashSet collectableShops = new(); + private HashSet fccShops = new(); + + private Dictionary gilShopPreHandlers = new(); + private Dictionary specialShopPreHandlers = new(); + private Dictionary collectableShopPreHandlers = new(); + private Dictionary inclusionShopPreHandlers = new(); + + private Dictionary> gilShopCustomTalk = new(); + private Dictionary> specialShopCustomTalk = new(); + private Dictionary> collectableShopCustomTalk = new(); + private Dictionary> inclusionShopCustomTalk = new(); + private Dictionary> fccShopCustomTalk = new(); + + private Dictionary> gilShopTopicSelect = new(); + private Dictionary> specialShopTopicSelect = new(); + private Dictionary> collectableShopTopicSelect = new(); + private Dictionary> inclusionShopTopicSelect = new(); + private Dictionary> fccShopTopicSelect = new(); + + public delegate void ShopChangedDelegate(); + + public event ShopChangedDelegate? OnShopChanged; + + public ShopTrackerService(IDataManager dataManager, ITargetManager targetManager, GilShopSheet gilShopSheet, SpecialShopSheet specialShopSheet, InclusionShopSheet inclusionShopSheet, FccShopSheet fccShopSheet, ENpcBaseSheet enpcBaseSheet, IAddonLifecycle addonLifecycle) + { + this.targetManager = targetManager; + _gilShopSheet = gilShopSheet; + _specialShopSheet = specialShopSheet; + _inclusionShopSheet = inclusionShopSheet; + _fccShopSheet = fccShopSheet; + _enpcBaseSheet = enpcBaseSheet; + _addonLifecycle = addonLifecycle; + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, ["Shop", "FreeCompanyCreditShop", "ShopExchangeItem", "ShopExchangeCurrency", "InclusionShop", "CollectablesShop"], AddonPostSetup); + foreach (var item in dataManager.GetExcelSheet()) + { + specialShops.Add(item.RowId); + } + + foreach (var item in dataManager.GetExcelSheet()) + { + gilShops.Add(item.RowId); + } + + foreach (var item in dataManager.GetExcelSheet()) + { + inclusionShops.Add(item.RowId); + } + + foreach (var item in dataManager.GetExcelSheet()) + { + collectableShops.Add(item.RowId); + } + + foreach (var item in dataManager.GetExcelSheet()) + { + fccShops.Add(item.RowId); + } + + ReadOnlySpan readOnlySpan = [typeof(Lumina.Excel.Sheets.CollectablesShop), typeof(InclusionShop), typeof(GilShop), typeof(SpecialShop), typeof(FccShop)]; + var typeHash = RowRef.CreateTypeHash(readOnlySpan); + + foreach (var customTalk in dataManager.GetExcelSheet()) + { + foreach (var scriptStruct in customTalk.Script) + { + var rowRef = RowRef.GetFirstValidRowOrUntyped(dataManager.Excel, scriptStruct.ScriptArg, readOnlySpan, typeHash, dataManager.GameData.Options.DefaultExcelLanguage); + if (rowRef.Is()) + { + collectableShops.Add(rowRef.RowId); + collectableShopCustomTalk.TryAdd(customTalk.RowId, new()); + collectableShopCustomTalk[customTalk.RowId].Add(rowRef.RowId); + } + else if (rowRef.Is()) + { + inclusionShops.Add(rowRef.RowId); + inclusionShopCustomTalk.TryAdd(customTalk.RowId, new()); + inclusionShopCustomTalk[customTalk.RowId].Add(rowRef.RowId); + } + else if (rowRef.Is()) + { + gilShops.Add(rowRef.RowId); + gilShopCustomTalk.TryAdd(customTalk.RowId, new()); + gilShopCustomTalk[customTalk.RowId].Add(rowRef.RowId); + } + else if (rowRef.Is()) + { + specialShops.Add(rowRef.RowId); + specialShopCustomTalk.TryAdd(customTalk.RowId, new()); + specialShopCustomTalk[customTalk.RowId].Add(rowRef.RowId); + } + else if (rowRef.Is()) + { + fccShops.Add(rowRef.RowId); + fccShopCustomTalk.TryAdd(customTalk.RowId, new()); + fccShopCustomTalk[customTalk.RowId].Add(rowRef.RowId); + } + } + } + + foreach (var prehandler in dataManager.GetExcelSheet()) + { + if (prehandler.Target.Is()) + { + collectableShopPreHandlers[prehandler.RowId] = prehandler.Target.RowId; + } + else if (prehandler.Target.Is()) + { + inclusionShopPreHandlers[prehandler.RowId] = prehandler.Target.RowId; + } + else if (prehandler.Target.Is()) + { + gilShopPreHandlers[prehandler.RowId] = prehandler.Target.RowId; + } + else if (prehandler.Target.Is()) + { + specialShopPreHandlers[prehandler.RowId] = prehandler.Target.RowId; + } + } + + foreach (var topicSelect in dataManager.GetExcelSheet()) + { + foreach (var shop in topicSelect.Shop) + { + if (shop.Is()) + { + var prehandler = shop.GetValueOrDefault(); + if (prehandler != null) + { + if (prehandler.Value.Target.Is()) + { + collectableShopTopicSelect.TryAdd(prehandler.Value.RowId, new()); + collectableShopTopicSelect[prehandler.Value.RowId].Add(prehandler.Value.Target.RowId); + } + else if (prehandler.Value.Target.Is()) + { + inclusionShopTopicSelect.TryAdd(prehandler.Value.RowId, new()); + inclusionShopTopicSelect[prehandler.Value.RowId].Add(prehandler.Value.Target.RowId); + } + else if (prehandler.Value.Target.Is()) + { + gilShopTopicSelect.TryAdd(prehandler.Value.RowId, new()); + gilShopTopicSelect[prehandler.Value.RowId].Add(prehandler.Value.Target.RowId); + } + else if (prehandler.Value.Target.Is()) + { + specialShopTopicSelect.TryAdd(prehandler.Value.RowId, new()); + specialShopTopicSelect[prehandler.Value.RowId].Add(prehandler.Value.Target.RowId); + } + } + } + else if (shop.Is()) + { + gilShopTopicSelect.TryAdd(topicSelect.RowId, new()); + gilShopTopicSelect[topicSelect.RowId].Add(shop.RowId); + } + else if (shop.Is()) + { + specialShopTopicSelect.TryAdd(topicSelect.RowId, new()); + specialShopTopicSelect[topicSelect.RowId].Add(shop.RowId); + } + } + } + } + + private void AddonPostSetup(AddonEvent type, AddonArgs args) + { + OnShopChanged?.Invoke(); + } + + public (ENpcBaseRow npc, List shops, IShop? activeShop)? GetCurrentShopType() + { + var currentShopIds = GetCurrentShopTypeIds(); + if (currentShopIds == null) + { + return null; + } + + var shopIds = currentShopIds.Value.shops; + var activeShopId = currentShopIds.Value.activeShopId; + + var shops = new List(); + IShop? activeShop = null; + var enpcBaseRow = _enpcBaseSheet.GetRowOrDefault(currentShopIds.Value.npcId); + if (enpcBaseRow == null) + { + return null; + } + foreach (var shopId in shopIds) + { + var shop = GetShopByIdAndType(shopId.Item2, shopId.Item1); + if (shop != null) + { + shops.Add(shop); + } + } + + if (activeShopId != null) + { + var shop = GetShopByIdAndType(activeShopId.Value.Item2, activeShopId.Value.Item1); + if (shop != null) + { + activeShop = shop; + } + } + + + return (enpcBaseRow, shops, activeShop); + } + + public IShop? GetShopByIdAndType(uint shopId, ShopType type) + { + switch (type) + { + case ShopType.Gil: + var gilShop = _gilShopSheet.GetRowOrDefault(shopId); + if (gilShop != null) + { + return gilShop; + } + break; + case ShopType.SpecialShop: + var specialShop = _specialShopSheet.GetRowOrDefault(shopId); + if (specialShop != null) + { + return specialShop; + } + break; + case ShopType.Collectable: + //TODO + break; + case ShopType.InclusionShop: + var inclusionShop = _inclusionShopSheet.GetRowOrDefault(shopId); + if (inclusionShop != null) + { + //TODO + //shops.Add(inclusionShop); + } + break; + case ShopType.FreeCompanyShop: + var fccShop = _inclusionShopSheet.GetRowOrDefault(shopId); + if (fccShop != null) + { + //shops.Add(fccShop); + } + break; + } + + return null; + } + + public unsafe (uint npcId, List<(ShopType, uint)> shops, (ShopType, uint)? activeShopId)? GetCurrentShopTypeIds() + { + var eventFramework = EventFramework.Instance(); + if (eventFramework != null) + { + uint? npcId = null; + List<(ShopType,uint)> shops = new(); + (ShopType, uint)? shopId = null; + + foreach (var eventHandler in eventFramework->EventHandlerModule.EventHandlerMap) + { + if (eventHandler.Item2.Value != null) + { + var activeTarget = false; + foreach (var eventObject in eventHandler.Item2.Value->EventObjects) + { + if (targetManager.Target?.DataId == eventObject.Value->BaseId) + { + npcId = targetManager.Target?.DataId; + activeTarget = true; + } + } + + if (!activeTarget) + { + continue; + } + if (collectableShops.Contains(eventHandler.Item1)) + { + shops.Add((ShopType.Collectable,eventHandler.Item1)); + } + else if (inclusionShops.Contains(eventHandler.Item1)) + { + shops.Add((ShopType.InclusionShop,eventHandler.Item1)); + } + else if (gilShops.Contains(eventHandler.Item1)) + { + shops.Add((ShopType.Gil,eventHandler.Item1)); + } + else if (specialShops.Contains(eventHandler.Item1)) + { + shops.Add((ShopType.SpecialShop,eventHandler.Item1)); + } + else if (fccShops.Contains(eventHandler.Item1)) + { + shops.Add((ShopType.FreeCompanyShop,eventHandler.Item1)); + } + else if (collectableShopCustomTalk.ContainsKey(eventHandler.Item1)) + { + foreach (var customTalkShopId in collectableShopCustomTalk[eventHandler.Item1]) + { + shops.Add((ShopType.Collectable,customTalkShopId)); + } + } + else if (inclusionShopCustomTalk.ContainsKey(eventHandler.Item1)) + { + foreach (var customTalkShopId in inclusionShopCustomTalk[eventHandler.Item1]) + { + shops.Add((ShopType.InclusionShop,customTalkShopId)); + } + } + else if (gilShopCustomTalk.ContainsKey(eventHandler.Item1)) + { + foreach (var customTalkShopId in gilShopCustomTalk[eventHandler.Item1]) + { + shops.Add((ShopType.Gil,customTalkShopId)); + } + } + else if (specialShopCustomTalk.ContainsKey(eventHandler.Item1)) + { + foreach (var customTalkShopId in specialShopCustomTalk[eventHandler.Item1]) + { + shops.Add((ShopType.SpecialShop,customTalkShopId)); + } + } + else if (fccShopCustomTalk.ContainsKey(eventHandler.Item1)) + { + foreach (var customTalkShopId in fccShopCustomTalk[eventHandler.Item1]) + { + shops.Add((ShopType.FreeCompanyShop,customTalkShopId)); + } + } + else if (collectableShopPreHandlers.ContainsKey(eventHandler.Item1)) + { + shops.Add((ShopType.Collectable,collectableShopPreHandlers[eventHandler.Item1])); + } + else if (inclusionShopPreHandlers.ContainsKey(eventHandler.Item1)) + { + shops.Add((ShopType.InclusionShop,inclusionShopPreHandlers[eventHandler.Item1])); + } + else if (gilShopPreHandlers.ContainsKey(eventHandler.Item1)) + { + shops.Add((ShopType.Gil,gilShopPreHandlers[eventHandler.Item1])); + } + else if (specialShopPreHandlers.ContainsKey(eventHandler.Item1)) + { + shops.Add((ShopType.SpecialShop,specialShopPreHandlers[eventHandler.Item1])); + } + else if (collectableShopTopicSelect.ContainsKey(eventHandler.Item1)) + { + foreach (var topicSelectShopId in collectableShopTopicSelect[eventHandler.Item1]) + { + shops.Add((ShopType.Collectable,topicSelectShopId)); + } + } + else if (inclusionShopTopicSelect.ContainsKey(eventHandler.Item1)) + { + foreach (var topicSelectShopId in inclusionShopTopicSelect[eventHandler.Item1]) + { + shops.Add((ShopType.InclusionShop,topicSelectShopId)); + } + } + else if (gilShopTopicSelect.ContainsKey(eventHandler.Item1)) + { + foreach (var topicSelectShopId in gilShopTopicSelect[eventHandler.Item1]) + { + shops.Add((ShopType.Gil,topicSelectShopId)); + } + } + else if (specialShopTopicSelect.ContainsKey(eventHandler.Item1)) + { + foreach (var topicSelectShopId in specialShopTopicSelect[eventHandler.Item1]) + { + shops.Add((ShopType.SpecialShop,topicSelectShopId)); + } + } + else if (fccShopTopicSelect.ContainsKey(eventHandler.Item1)) + { + foreach (var topicSelectShopId in fccShopTopicSelect[eventHandler.Item1]) + { + shops.Add((ShopType.FreeCompanyShop,topicSelectShopId)); + } + } + + if (activeTarget) + { + var freeCompanyShopAgent = UIModule.Instance()->GetAgentModule()->GetAgentByInternalId(AgentId.FreeCompanyCreditShop); + if (freeCompanyShopAgent != null && freeCompanyShopAgent->IsAgentActive() && eventHandler.Item2.Value != null && eventHandler.Item2.Value->Info.EventId.ContentId == EventHandlerType.FreeCompanyCreditShop) + { + shopId = shops.FirstOrDefault(c => c.Item2 == eventHandler.Item1); + } + else + { + var agent = (AgentShop*)UIModule.Instance()->GetAgentModule()->GetAgentByInternalId(AgentId.Shop); + if (agent != null && agent->IsAgentActive() && agent->EventReceiver != null && + agent->IsAddonReady()) + { + var proxy = (ShopEventHandler.AgentProxy*)agent->EventReceiver; + if (proxy != null && proxy->Handler != null) + { + shopId = shops.FirstOrDefault(c => c.Item2 == proxy->Handler->Info.EventId.Id); + } + } + + var agentProxy = ShopEventHandler.AgentProxy.Instance(); + if (agentProxy != null && agentProxy->Handler != null) + { + if (agentProxy->Handler == eventHandler.Item2.Value) + { + shopId = shops.FirstOrDefault(c => c.Item2 == eventHandler.Item1); + } + } + } + } + } + } + + if (npcId != null) + { + return (npcId.Value, shops, shopId); + } + } + + return null; + } + + public void Dispose() + { + _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, ["Shop", "FreeCompanyCreditShop", "ShopExchangeItem", "ShopExchangeCurrency", "InclusionShop", "CollectablesShop"], AddonPostSetup); + } +} \ No newline at end of file diff --git a/InventoryTools/Services/WindowService.cs b/InventoryTools/Services/WindowService.cs index 24255e37..d603a981 100644 --- a/InventoryTools/Services/WindowService.cs +++ b/InventoryTools/Services/WindowService.cs @@ -107,7 +107,7 @@ public bool HasFilterWindowOpen public IWindowSystem WindowSystem => _windowSystem; - public T GetWindow() where T: GenericWindow + public T GetWindow() where T: GenericWindow { if (_genericWindows.ContainsKey(typeof(T))) { @@ -130,7 +130,7 @@ public GenericWindow GetWindow(Type type) AddWindow(type, newWindow); return newWindow; } - + public UintWindow GetWindow(Type type, uint windowId) { if (_uintWindows.ContainsKey((type,windowId))) @@ -142,7 +142,7 @@ public UintWindow GetWindow(Type type, uint windowId) AddWindow(type, newWindow, windowId); return newWindow; } - + public StringWindow GetWindow(Type type, string windowId) { if (_stringWindows.ContainsKey((type,windowId))) @@ -182,7 +182,7 @@ public bool ToggleWindow() where T: GenericWindow GetWindow().Toggle(); return true; } - + public bool ToggleWindow(uint windowId) where T: UintWindow { GetWindow(windowId).Toggle(); @@ -293,7 +293,7 @@ public bool OpenWindow(string windowId, bool refocus = true) where T: StringW return true; } - + private bool CloseWindow(Type windowType) { if (_genericWindows.ContainsKey(windowType)) @@ -303,7 +303,7 @@ private bool CloseWindow(Type windowType) } return false; } - + private bool CloseWindow(Type windowType, uint windowId) { if (_uintWindows.ContainsKey((windowType,windowId))) @@ -313,7 +313,7 @@ private bool CloseWindow(Type windowType, uint windowId) } return false; } - + private bool CloseWindow(Type windowType, string windowId) { if (_stringWindows.ContainsKey((windowType,windowId))) @@ -323,7 +323,7 @@ private bool CloseWindow(Type windowType, string windowId) } return false; } - + private bool CloseWindows() { foreach (var window in _allWindows) @@ -333,7 +333,7 @@ private bool CloseWindows() return true; } - + private bool CloseWindows(Type type) { foreach (var window in _allWindows) @@ -346,7 +346,7 @@ private bool CloseWindows(Type type) return true; } - + private bool AddWindow(Type windowType, GenericWindow window) { window.Logger = Logger; @@ -360,7 +360,7 @@ private bool AddWindow(Type windowType, GenericWindow window) } return false; } - + private bool AddWindow(Type windowType, UintWindow window, uint windowId) { window.Logger = Logger; @@ -374,7 +374,7 @@ private bool AddWindow(Type windowType, UintWindow window, uint windowId) } return false; } - + private bool AddWindow(Type windowType, StringWindow window, string windowId) { window.Logger = Logger; @@ -469,7 +469,7 @@ private void WindowOnClosed(IWindow window) hasOtherWindowOpen = true; } } - + if (hasOtherWindowOpen == false) { _configuration.SavedWindowPositions[window.GetType().ToString()] = window.CurrentPosition; @@ -485,6 +485,18 @@ private void WindowOnClosed(IWindow window) MediatorService.Publish(new OverlaysRequestRefreshMessage()); } + private void SaveWindowStates() + { + foreach (var window in _allWindows) + { + if (window.SaveState && window.SavePosition && window.IsOpen) + { + _configuration.SavedWindowPositions[window.GetType().ToString()] = window.CurrentPosition; + } + } + _configuration.IsDirty = true; + } + public void RemoveWindow(IWindow window) { _allWindows.Remove(window); @@ -507,8 +519,8 @@ public void RemoveWindow(IWindow window) } window.Dispose(); } - - + + protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -536,7 +548,7 @@ public Task StartAsync(CancellationToken cancellationToken) _mediatorService.Subscribe(this, new Action(CloseWindows) ); _mediatorService.Subscribe(this, new Action(OpenSavedWindows) ); _mediatorService.Subscribe(this, new Action(close => UpdateRespectCloseHotkey(close.windowType, close.newSetting)) ); - + return Task.CompletedTask; } @@ -592,6 +604,7 @@ private void ToggleGenericWindow(ToggleGenericWindowMessage obj) public Task StopAsync(CancellationToken cancellationToken) { + SaveWindowStates(); Logger.LogTrace("Stopping service {type} ({this})", GetType().Name, this); return Task.CompletedTask; } diff --git a/InventoryTools/Tooltips/LocationDisplayTooltip.cs b/InventoryTools/Tooltips/LocationDisplayTooltip.cs index e585713e..6d3b3179 100644 --- a/InventoryTools/Tooltips/LocationDisplayTooltip.cs +++ b/InventoryTools/Tooltips/LocationDisplayTooltip.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using AllaganLib.GameSheets.Sheets; +using CriticalCommonLib.Crafting; using CriticalCommonLib.Enums; using CriticalCommonLib.Services; using Dalamud.Game.Text.SeStringHandling; @@ -85,7 +86,13 @@ public override unsafe void OnGenerateItemTooltip(NumberArrayData* numberArrayDa var willRetrieve = craftItem.QuantityWillRetrieve; if (missingOverall != 0 || willRetrieve != 0) { - var needText = "Need: " + missingOverall; + var missingText = "Missing: "; + if (craftItem.IngredientPreference.Type is IngredientPreferenceType.Buy + or IngredientPreferenceType.Item or IngredientPreferenceType.HouseVendor) + { + missingText = "Buy: "; + } + var needText = missingText + missingOverall; if (filterResult != null) { var sortedItems = filterResult.Where(c => c.InventoryItem != null && @@ -95,7 +102,7 @@ public override unsafe void OnGenerateItemTooltip(NumberArrayData* numberArrayDa var sortedItem = sortedItems.First(); if (sortedItem.InventoryItem!.Quantity != 0) { - needText += " / (" + Math.Min(willRetrieve,sortedItem.InventoryItem!.Quantity) + " can be retrieved)"; + needText += " / (" + Math.Min(willRetrieve,sortedItem.InventoryItem!.Quantity) + " should be retrieved)"; } } } diff --git a/InventoryTools/Ui/Pages/CharacterRetainerPage.cs b/InventoryTools/Ui/Pages/CharacterRetainerPage.cs index 295df9ae..fe3b9e7e 100644 --- a/InventoryTools/Ui/Pages/CharacterRetainerPage.cs +++ b/InventoryTools/Ui/Pages/CharacterRetainerPage.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using AllaganLib.Shared.Extensions; using CriticalCommonLib.Extensions; using CriticalCommonLib.Models; using CriticalCommonLib.Services; @@ -111,7 +112,7 @@ private void ClearInventories(string arg1, bool arg2) var tooltip = character.Value.FormattedName; if (character.Value.ActualClassJob != null) { - tooltip += "\n" + character.Value.ActualClassJob?.Base.Name.ExtractText(); + tooltip += "\n" + character.Value.ActualClassJob?.Base.Name.ExtractText().ToTitleCase(); } tooltip += "\n\nRight Click: Options"; @@ -213,7 +214,7 @@ private void ClearInventories(string arg1, bool arg2) var tooltip = characterRetainer.Value.FormattedName; if (characterRetainer.Value.ActualClassJob != null) { - tooltip += "\n" + characterRetainer.Value.ActualClassJob?.Base.NameEnglish.ExtractText(); + tooltip += "\n" + characterRetainer.Value.ActualClassJob?.Base.Name.ExtractText().ToTitleCase(); } tooltip += "\n\nRight Click: Options"; @@ -249,7 +250,7 @@ private void ClearInventories(string arg1, bool arg2) var tooltip = characterRetainer.Value.FormattedName; if (characterRetainer.Value.ActualClassJob != null) { - tooltip += "\n" + characterRetainer.Value.ActualClassJob?.Base.NameEnglish.ExtractText(); + tooltip += "\n" + characterRetainer.Value.ActualClassJob?.Base.Name.ExtractText().ToTitleCase(); } tooltip += "\n\nRight Click: Options"; @@ -362,7 +363,7 @@ private void ClearInventories(string arg1, bool arg2) ImGui.Text("Free Company: " + character.FreeCompanyName); ImGui.Text("World: " + (character.World?.Name.ExtractText() ?? "Unknown")); ImGui.Text("Class/Job: " + - (character.ActualClassJob?.Base.NameEnglish.ExtractText() ?? "Unknown")); + (character.ActualClassJob?.Base.Name.ExtractText().ToTitleCase() ?? "Unknown")); } else if (character.CharacterType is CharacterType.Housing) { diff --git a/InventoryTools/Ui/Windows/CraftOverlayWindow.cs b/InventoryTools/Ui/Windows/CraftOverlayWindow.cs index de09bf35..e7c1b351 100644 --- a/InventoryTools/Ui/Windows/CraftOverlayWindow.cs +++ b/InventoryTools/Ui/Windows/CraftOverlayWindow.cs @@ -44,6 +44,7 @@ public class CraftOverlayWindow : OverlayWindow private readonly CraftOverlayRememberStateSetting _rememberStateSetting; private readonly CraftOverlayWindowStateSetting _windowStateSetting; private readonly CraftOverlayHideSetting _overlayHideSetting; + private readonly ShopTrackerService _shopTrackerService; private readonly MapSheet _mapSheet; public CraftOverlayWindow(ILogger logger, @@ -64,7 +65,8 @@ public CraftOverlayWindow(ILogger logger, CraftOverlayMaxExpandedItemsSetting maxExpandedItemsSetting, CraftOverlayRememberStateSetting rememberStateSetting, CraftOverlayWindowStateSetting windowStateSetting, - CraftOverlayHideSetting overlayHideSetting) : base(logger, + CraftOverlayHideSetting overlayHideSetting, + ShopTrackerService shopTrackerService) : base(logger, configuration, addonLifecycle, gameGui, @@ -85,6 +87,7 @@ public CraftOverlayWindow(ILogger logger, _rememberStateSetting = rememberStateSetting; _windowStateSetting = windowStateSetting; _overlayHideSetting = overlayHideSetting; + _shopTrackerService = shopTrackerService; } public override void Initialize() @@ -110,6 +113,10 @@ public override bool DrawConditions() public override void Draw() { + if (ImGui.GetWindowPos() != CurrentPosition) + { + CurrentPosition = ImGui.GetWindowPos(); + } var collapsed = this.WindowState; var currentCursorPosX = ImGui.GetCursorPosX(); @@ -452,6 +459,8 @@ public override void Invalidate() public override bool DestroyOnClose { get; } = false; public override bool SaveState => this._rememberStateSetting.CurrentValue(Configuration); + + public override bool SavePosition => true; public override Vector2? DefaultSize { get; } = null; public override Vector2? MaxSize { get; } = null; public override Vector2? MinSize { get; } = null; diff --git a/InventoryTools/Ui/Windows/DebugWindow.cs b/InventoryTools/Ui/Windows/DebugWindow.cs index 69305de8..826db5e3 100644 --- a/InventoryTools/Ui/Windows/DebugWindow.cs +++ b/InventoryTools/Ui/Windows/DebugWindow.cs @@ -1690,6 +1690,20 @@ public unsafe void DrawAddons() } } } + + if (ImGui.CollapsingHeader("Housing Goods")) + { + var addon = this.gameGui.GetAddonByName("HousingGoods"); + if (addon != IntPtr.Zero) + { + var housingGoods = (AddonHousingGoods*)addon; + if (housingGoods != null) + { + ImGui.Text($"Current Tab: { (housingGoods->CurrentTab) }"); + } + } + + } } public unsafe void DrawCraftAgentTab() @@ -1810,7 +1824,7 @@ private void DrawInventoriesDebugTab() // ImGui.EndTable(); } - private void DrawCharacterDebugTab() + private unsafe void DrawCharacterDebugTab() { ImGui.TextUnformatted("Character Information:"); ImGui.TextUnformatted(_characterMonitor.ActiveCharacter?.Name.ToString() ?? @@ -1826,8 +1840,29 @@ private void DrawCharacterDebugTab() ImGui.TextUnformatted("Cached Division Id:" + _characterMonitor.InternalDivisionId.ToString()); ImGui.TextUnformatted("Cached Room Id:" + _characterMonitor.InternalRoomId.ToString()); ImGui.TextUnformatted("Cached House Id:" + _characterMonitor.InternalHouseId.ToString()); + + var ot = HousingManager.Instance()->OutdoorTerritory; + if(ot != null) + { + ImGui.TextUnformatted(ot->HouseId.ToString()); + } + var it = HousingManager.Instance()->IndoorTerritory; + if(it != null) + { + ImGui.TextUnformatted(it->HouseId.ToString()); + } + var ct = HousingManager.Instance()->CurrentTerritory; + if(ct != null) + { + ImGui.TextUnformatted($"{(ulong)ct:X}"); + } + ImGui.TextUnformatted("Owned House IDS:"); + foreach (var id in _characterMonitor.GetOwnedHouseIds()) + { + ImGui.TextUnformatted(id.ToString()); + } ImGui.TextUnformatted("Has Housing Permission:" + - (_characterMonitor.InternalHasHousePermission ? "Yes" : "No")); + (_characterMonitor.InternalHasHousePermission || _characterMonitor.GetOwnedHouseIds().Contains(_characterMonitor.InternalHouseId) ? "Yes" : "No")); ImGui.NewLine(); ImGui.TextUnformatted("Retainers:"); ImGui.BeginTable("retainerTable", 6); diff --git a/InventoryTools/Ui/Windows/ItemWindow.cs b/InventoryTools/Ui/Windows/ItemWindow.cs index 04b814c2..c556df11 100644 --- a/InventoryTools/Ui/Windows/ItemWindow.cs +++ b/InventoryTools/Ui/Windows/ItemWindow.cs @@ -616,37 +616,38 @@ private bool DrawCraftRecipe() var item = _itemSheet.GetRowOrDefault(craftItem.ItemId); if (item != null) { - ImGui.PushID(index); - if (ImGui.ImageButton(ImGuiService.GetIconTexture(item.Icon).ImGuiHandle, new(32, 32))) + using (ImRaii.PushId(index)) { - MediatorService.Publish(new OpenUintWindowMessage(typeof(ItemWindow), item.RowId)); - } + if (ImGui.ImageButton(ImGuiService.GetIconTexture(item.Icon).ImGuiHandle, new(32, 32))) + { + MediatorService.Publish(new OpenUintWindowMessage(typeof(ItemWindow), item.RowId)); + } - if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & - ImGuiHoveredFlags.AllowWhenOverlapped & - ImGuiHoveredFlags.AllowWhenBlockedByPopup & - ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & - ImGuiHoveredFlags.AnyWindow) && - ImGui.IsMouseReleased(ImGuiMouseButton.Right)) - { - ImGui.OpenPopup("RightClick" + item.RowId); - } + if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & + ImGuiHoveredFlags.AllowWhenOverlapped & + ImGuiHoveredFlags.AllowWhenBlockedByPopup & + ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & + ImGuiHoveredFlags.AnyWindow) && + ImGui.IsMouseReleased(ImGuiMouseButton.Right)) + { + ImGui.OpenPopup("RightClick" + item.RowId); + } - if (ImGui.BeginPopup("RightClick" + item.RowId)) - { - MediatorService.Publish(ImGuiService.ImGuiMenuService.DrawRightClickPopup(item)); - ImGui.EndPopup(); - } + if (ImGui.BeginPopup("RightClick" + item.RowId)) + { + MediatorService.Publish(ImGuiService.ImGuiMenuService.DrawRightClickPopup(item)); + ImGui.EndPopup(); + } - float lastButtonX2 = ImGui.GetItemRectMax().X; - float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; - ImGuiUtil.HoverTooltip(item.NameString + " - " + craftItem.QuantityRequired); - if (index + 1 < _craftItem.ChildCrafts.Count && nextButtonX2 < windowVisibleX2) - { - ImGui.SameLine(); + float lastButtonX2 = ImGui.GetItemRectMax().X; + float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; + ImGuiUtil.HoverTooltip(item.NameString + " - " + craftItem.QuantityRequired); + if (index + 1 < _craftItem.ChildCrafts.Count && nextButtonX2 < windowVisibleX2) + { + ImGui.SameLine(); + } } - ImGui.PopID(); index++; } } @@ -671,32 +672,40 @@ private bool DrawSharedModels() float windowVisibleX2 = ImGui.GetWindowPos().X + ImGui.GetWindowContentRegionMax().X; for (var index = 0; index < SharedModels.Count; index++) { - ImGui.PushID(index); - var sharedModel = SharedModels[index]; - if (ImGui.ImageButton(ImGuiService.GetIconTexture(sharedModel.Icon).ImGuiHandle, new(32, 32))) + using (ImRaii.PushId(index)) { - MediatorService.Publish(new OpenUintWindowMessage(typeof(ItemWindow), sharedModel.RowId)); - } - if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & ImGuiHoveredFlags.AllowWhenOverlapped & ImGuiHoveredFlags.AllowWhenBlockedByPopup & ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & ImGuiHoveredFlags.AnyWindow) && ImGui.IsMouseReleased(ImGuiMouseButton.Right)) - { - ImGui.OpenPopup("RightClick" + sharedModel.RowId); - } + var sharedModel = SharedModels[index]; + if (ImGui.ImageButton(ImGuiService.GetIconTexture(sharedModel.Icon).ImGuiHandle, + new(32, 32))) + { + MediatorService.Publish( + new OpenUintWindowMessage(typeof(ItemWindow), sharedModel.RowId)); + } - if (ImGui.BeginPopup("RightClick"+ sharedModel.RowId)) - { - MediatorService.Publish(ImGuiService.ImGuiMenuService.DrawRightClickPopup(sharedModel)); - ImGui.EndPopup(); - } + if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & + ImGuiHoveredFlags.AllowWhenOverlapped & + ImGuiHoveredFlags.AllowWhenBlockedByPopup & + ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & + ImGuiHoveredFlags.AnyWindow) && + ImGui.IsMouseReleased(ImGuiMouseButton.Right)) + { + ImGui.OpenPopup("RightClick" + sharedModel.RowId); + } - float lastButtonX2 = ImGui.GetItemRectMax().X; - float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; - ImGuiUtil.HoverTooltip(sharedModel.NameString); - if (index + 1 < SharedModels.Count && nextButtonX2 < windowVisibleX2) - { - ImGui.SameLine(); - } + if (ImGui.BeginPopup("RightClick" + sharedModel.RowId)) + { + MediatorService.Publish(ImGuiService.ImGuiMenuService.DrawRightClickPopup(sharedModel)); + ImGui.EndPopup(); + } - ImGui.PopID(); + float lastButtonX2 = ImGui.GetItemRectMax().X; + float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; + ImGuiUtil.HoverTooltip(sharedModel.NameString); + if (index + 1 < SharedModels.Count && nextButtonX2 < windowVisibleX2) + { + ImGui.SameLine(); + } + } } } } @@ -716,42 +725,50 @@ private bool DrawRecipes() float windowVisibleX2 = ImGui.GetWindowPos().X + ImGui.GetWindowContentRegionMax().X; for (var index = 0; index < RecipesAsRequirement.Length; index++) { - ImGui.PushID(index); - var recipe = RecipesAsRequirement[index]; - if (recipe.ItemResult != null) + using (ImRaii.PushId(index)) { - var icon = ImGuiService.GetIconTexture(recipe.ItemResult.Icon); - if (ImGui.ImageButton(icon.ImGuiHandle, - new Vector2(32, 32) * ImGui.GetIO().FontGlobalScale, new(0, 0), new(1, 1), 0)) - { - MediatorService.Publish(new OpenUintWindowMessage(typeof(ItemWindow), recipe.ItemResult.RowId)); - } - if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & ImGuiHoveredFlags.AllowWhenOverlapped & ImGuiHoveredFlags.AllowWhenBlockedByPopup & ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & ImGuiHoveredFlags.AnyWindow) && ImGui.IsMouseReleased(ImGuiMouseButton.Right)) + var recipe = RecipesAsRequirement[index]; + if (recipe.ItemResult != null) { - ImGui.OpenPopup("RightClick" + recipe.RowId); - } + var icon = ImGuiService.GetIconTexture(recipe.ItemResult.Icon); + if (ImGui.ImageButton(icon.ImGuiHandle, + new Vector2(32, 32) * ImGui.GetIO().FontGlobalScale, new(0, 0), new(1, 1), 0)) + { + MediatorService.Publish(new OpenUintWindowMessage(typeof(ItemWindow), + recipe.ItemResult.RowId)); + } - if (ImGui.BeginPopup("RightClick"+ recipe.RowId)) - { - if (recipe.ItemResult != null) + if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled & + ImGuiHoveredFlags.AllowWhenOverlapped & + ImGuiHoveredFlags.AllowWhenBlockedByPopup & + ImGuiHoveredFlags.AllowWhenBlockedByActiveItem & + ImGuiHoveredFlags.AnyWindow) && + ImGui.IsMouseReleased(ImGuiMouseButton.Right)) { - MediatorService.Publish(ImGuiService.ImGuiMenuService.DrawRightClickPopup(recipe.ItemResult)); + ImGui.OpenPopup("RightClick" + recipe.RowId); } - ImGui.EndPopup(); - } + if (ImGui.BeginPopup("RightClick" + recipe.RowId)) + { + if (recipe.ItemResult != null) + { + MediatorService.Publish( + ImGuiService.ImGuiMenuService.DrawRightClickPopup(recipe.ItemResult)); + } - float lastButtonX2 = ImGui.GetItemRectMax().X; - float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; - ImGuiUtil.HoverTooltip(recipe.ItemResult!.NameString + " - " + - (recipe.CraftType?.FormattedName ?? "Unknown")); - if (index + 1 < RecipesAsRequirement.Length && nextButtonX2 < windowVisibleX2) - { - ImGui.SameLine(); + ImGui.EndPopup(); + } + + float lastButtonX2 = ImGui.GetItemRectMax().X; + float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + 32; + ImGuiUtil.HoverTooltip(recipe.ItemResult!.NameString + " - " + + (recipe.CraftType?.FormattedName ?? "Unknown")); + if (index + 1 < RecipesAsRequirement.Length && nextButtonX2 < windowVisibleX2) + { + ImGui.SameLine(); + } } } - - ImGui.PopID(); } } } @@ -1065,16 +1082,18 @@ private void DrawMobDrops() var mobSpawns = bnpcName.MobSpawnPositions.GroupBy(c => c.TerritoryType.RowId).ToList(); if (mobSpawns.Count != 0) { - ImGui.PushID("MobDrop" + index); - if (ImGui.CollapsingHeader(" " + - bnpcName.Base.Singular.ExtractText() + "(" + mobSpawns.Count + ")",ImGuiTreeNodeFlags.CollapsingHeader)) + using (ImRaii.PushId("MobDrop" + index)) { - ImGuiTable.DrawTable("MobSpawns" + index, mobSpawns, DrawMobSpawn, - ImGuiTableFlags.None, - new[] { "Map", "Spawn Locations" }); + if (ImGui.CollapsingHeader(" " + + bnpcName.Base.Singular.ExtractText() + "(" + + mobSpawns.Count + ")", + ImGuiTreeNodeFlags.CollapsingHeader)) + { + ImGuiTable.DrawTable("MobSpawns" + index, mobSpawns, DrawMobSpawn, + ImGuiTableFlags.None, + new[] { "Map", "Spawn Locations" }); + } } - - ImGui.PopID(); } } } @@ -1121,26 +1140,29 @@ private void DrawMobSpawn(IGrouping mobSpawnPositions) var territory = position.TerritoryType; if (territory.ValueNullable?.PlaceName.ValueNullable != null) { - ImGui.PushID("" + index); - if (ImGui.ImageButton(ImGuiService.GetIconTexture(60561).ImGuiHandle, - new Vector2(32 * ImGui.GetIO().FontGlobalScale, 32 * ImGui.GetIO().FontGlobalScale), - new Vector2(0, 0), new Vector2(1, 1), 0)) + using (ImRaii.PushId(index)) { - _chatUtilities.PrintFullMapLink(position, position.TerritoryType.Value.PlaceName.Value.Name.ExtractText()); - } + if (ImGui.ImageButton(ImGuiService.GetIconTexture(60561).ImGuiHandle, + new Vector2(32 * ImGui.GetIO().FontGlobalScale, + 32 * ImGui.GetIO().FontGlobalScale), + new Vector2(0, 0), new Vector2(1, 1), 0)) + { + _chatUtilities.PrintFullMapLink(position, + position.TerritoryType.Value.PlaceName.Value.Name.ExtractText()); + } - if (ImGui.IsItemHovered()) - { - using var tt = ImRaii.Tooltip(); - ImGui.TextUnformatted(position.TerritoryType.Value.PlaceName.Value.Name.ExtractText()); - } + if (ImGui.IsItemHovered()) + { + using var tt = ImRaii.Tooltip(); + ImGui.TextUnformatted( + position.TerritoryType.Value.PlaceName.Value.Name.ExtractText()); + } - if ((count + 1) % maxItems != 0) - { - ImGui.SameLine(); + if ((count + 1) % maxItems != 0) + { + ImGui.SameLine(); + } } - - ImGui.PopID(); } count++; @@ -1152,29 +1174,30 @@ private void DrawMobSpawn(IGrouping mobSpawnPositions) private void DrawGatheringRow(ItemGatheringSource obj) { ImGui.TableNextColumn(); - ImGui.PushID(obj.GetHashCode()); - var source = obj.Item; - if (ImGui.ImageButton(ImGuiService.GetIconTexture(source.Icon).ImGuiHandle, new(32, 32))) + using (ImRaii.PushId(obj.GetHashCode())) { - _gameInterface.OpenGatheringLog(_itemId); - } - ImGuiUtil.HoverTooltip(source.NameString + " - Open in Gathering Log"); - ImGui.TableNextColumn(); - ImGui.TextUnformatted(obj.GatheringItem.Base.GatheringItemLevel.RowId.ToString()); - ImGui.TableNextColumn(); - if (obj.MapIds != null) - { - foreach (var location in obj.MapIds) + var source = obj.Item; + if (ImGui.ImageButton(ImGuiService.GetIconTexture(source.Icon).ImGuiHandle, new(32, 32))) + { + _gameInterface.OpenGatheringLog(_itemId); + } + + ImGuiUtil.HoverTooltip(source.NameString + " - Open in Gathering Log"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(obj.GatheringItem.Base.GatheringItemLevel.RowId.ToString()); + ImGui.TableNextColumn(); + if (obj.MapIds != null) { - var map = _mapSheet.GetRowOrDefault(location); - if (map != null) + foreach (var location in obj.MapIds) { - ImGui.TextWrapped(map.FormattedName); + var map = _mapSheet.GetRowOrDefault(location); + if (map != null) + { + ImGui.TextWrapped(map.FormattedName); + } } } } - - ImGui.PopID(); } private void DrawRetainerRow(RetainerTaskRow obj) diff --git a/InventoryTools/Ui/Windows/OverlayWindow.cs b/InventoryTools/Ui/Windows/OverlayWindow.cs index 4c37b30a..96022c0e 100644 --- a/InventoryTools/Ui/Windows/OverlayWindow.cs +++ b/InventoryTools/Ui/Windows/OverlayWindow.cs @@ -39,8 +39,7 @@ protected OverlayWindow( this.pluginLog = pluginLog; this.AttachedAddons = []; this.MediatorService.Subscribe(this, this.PluginLoaded); - this.Flags = ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize | - ImGuiWindowFlags.NoSavedSettings; + this.Flags = ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize; this.Size = null; this.RespectCloseHotkey = false; } diff --git a/InventoryTools/packages.lock.json b/InventoryTools/packages.lock.json index e67b49c0..37208174 100644 --- a/InventoryTools/packages.lock.json +++ b/InventoryTools/packages.lock.json @@ -29,12 +29,12 @@ }, "DalaMock.Host": { "type": "Direct", - "requested": "[2.1.5, )", - "resolved": "2.1.5", - "contentHash": "292Fx954HO4AJnKQ16KzlyCaudhL0E4tW9Ytjmt1aO8CUzWqteybEfaZGieFkfzC3UCaq/3AsbWl4mJX6bRU6Q==", + "requested": "[2.1.6, )", + "resolved": "2.1.6", + "contentHash": "wCS8xL11kzT39jyMkNo9+kf/JmF3gcGaF1bk2avuf59+121xjv4lj/a5jTwjzOqZLomSVVKLxWdSEsk5EuRrjA==", "dependencies": { "Autofac.Extensions.DependencyInjection": "9.0.0", - "DalaMock.Shared": "2.1.5", + "DalaMock.Shared": "2.1.6", "Microsoft.Extensions.Hosting": "8.0.0", "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", "Microsoft.Extensions.ObjectPool": "9.0.0-preview.6.24328.4" @@ -120,13 +120,13 @@ }, "AllaganLib.GameSheets": { "type": "Transitive", - "resolved": "1.1.15", - "contentHash": "pis0YWRcG5OjhIxsAc712TpavdQerjjnN9Ii9ASm71ldqju8cOgHTTZ18f9EtrEv06xHvA1EdG3NLKvi4Z93QA==", + "resolved": "1.1.17", + "contentHash": "ViziJLY97Wsxs8k52zVBzchdFUU3bnW7jJZX8fuL0bmYQD4D5lErTyZimrVUmZS2nKwicgBTl/e+EtvyHXIE3Q==", "dependencies": { "AllaganLib.Shared": "1.1.12", "Autofac.Extensions.DependencyInjection": "9.0.0", "CSVFile": "3.2.0", - "LuminaSupplemental.Excel": "2.1.6" + "LuminaSupplemental.Excel": "2.1.8" } }, "AllaganLib.Shared": { @@ -145,8 +145,8 @@ }, "DalaMock.Shared": { "type": "Transitive", - "resolved": "2.1.5", - "contentHash": "Pv6iR9D9BY1V9wvsKDwh868L26AysJ0WeEbPVPTbc7ino/UaNQ0gcty5MCDrVy9Mp7QchqrcgbX/O/BNGpO4ow==", + "resolved": "2.1.6", + "contentHash": "F6LtlbpWN6H1tpZaXpg0JcXEsnmeVg+1UMahKsmxtPKipqhu8/BEcXz6T1HbKF/p/ZHFGiFfpXwR5ooIMt2nXw==", "dependencies": { "Autofac.Extensions.DependencyInjection": "9.0.0", "Microsoft.Extensions.Hosting": "8.0.0", @@ -160,8 +160,8 @@ }, "LuminaSupplemental.Excel": { "type": "Transitive", - "resolved": "2.1.6", - "contentHash": "h/rGvwCbQJ3xBDApu77xpZWgmr98EGjcXbsOyfIaCnzi5MUh3IQRIPyD+qQTEE9Tcw8unw3gEiJNxd/s0syhuw==", + "resolved": "2.1.8", + "contentHash": "erJ2gwQvLU83jucUXa/aM+mJcFMdyDmpb328DFs5cO1VL2S+pgCx3m52+bFtULgkDVZnGCcR2EFYSQj9TlocIg==", "dependencies": { "CSVFile": "3.1.0", "CsvHelper": "30.0.1" @@ -564,7 +564,7 @@ "criticalcommonlib": { "type": "Project", "dependencies": { - "AllaganLib.GameSheets": "[1.1.15, )", + "AllaganLib.GameSheets": "[1.1.17, )", "Humanizer.Core": "[3.0.0-beta.54, )", "Microsoft.Extensions.Hosting": "[8.0.1, )", "NaturalSort.Extension": "[3.2.0, )", diff --git a/InventoryToolsMock/InventoryToolsMock.csproj b/InventoryToolsMock/InventoryToolsMock.csproj index 8423fe58..fe60d1a6 100644 --- a/InventoryToolsMock/InventoryToolsMock.csproj +++ b/InventoryToolsMock/InventoryToolsMock.csproj @@ -53,7 +53,7 @@ - + diff --git a/InventoryToolsMock/MockCharacterMonitor.cs b/InventoryToolsMock/MockCharacterMonitor.cs index 90221c52..b602ad32 100644 --- a/InventoryToolsMock/MockCharacterMonitor.cs +++ b/InventoryToolsMock/MockCharacterMonitor.cs @@ -57,7 +57,7 @@ public void RefreshActiveCharacter() Service.Framework.RunOnFrameworkThread(() => { OnCharacterUpdated?.Invoke(null); }); } } - + private Dictionary _characters; private bool _isLoggedIn; public Dictionary Characters => _characters; @@ -117,6 +117,11 @@ public bool BelongsToActiveCharacter(ulong characterId) return false; } + public unsafe List GetOwnedHouseIds() + { + return new(); + } + public KeyValuePair[] GetRetainerCharacters(ulong retainerId) { return Characters.Where(c => c.Value.OwnerId == retainerId && c.Value.CharacterType == CharacterType.Retainer && c.Key != 0 && c.Value.Name != "").ToArray(); @@ -131,8 +136,8 @@ public KeyValuePair[] GetCharacterHouses(ulong characterId) { return Characters.Where(c => c.Value.Owners.Contains(characterId) && c.Value.CharacterType == CharacterType.Housing && c.Key != 0 && c.Value.Name != "").ToArray(); } - - + + public KeyValuePair[] GetCharacterHouses() { return Characters.Where(c => c.Value.Owners.Count != 0 && c.Value.CharacterType == CharacterType.Housing && c.Key != 0 && c.Value.HousingName != "").ToArray(); @@ -182,7 +187,7 @@ public bool IsHousing(ulong characterId) } return null; } - + public Character? GetParentCharacterById(ulong characterId) { var character = GetCharacterById(characterId); @@ -195,7 +200,7 @@ public bool IsHousing(ulong characterId) return null; } - + public string GetCharacterNameById(ulong characterId, bool owner = false) { if (!owner) return GetCharacterById(characterId)?.FormattedName ?? "Unknown"; @@ -261,9 +266,9 @@ public KeyValuePair[] GetFreeCompanyCharacters(ulong freeCompa public Character? ActiveFreeCompany => _characters.ContainsKey(_activeFreeCompanyId) ? _characters[_activeFreeCompanyId] : null; - + public Character? ActiveRetainer => - _characters.ContainsKey(_activeRetainerId) ? _characters[_activeRetainerId] : null; + _characters.ContainsKey(_activeRetainerId) ? _characters[_activeRetainerId] : null; public bool IsLoggedIn { diff --git a/InventoryToolsMock/Program.cs b/InventoryToolsMock/Program.cs index f385d4ab..5e45f117 100644 --- a/InventoryToolsMock/Program.cs +++ b/InventoryToolsMock/Program.cs @@ -1,5 +1,7 @@ -using DalaMock.Core.DI; +using System.Numerics; +using DalaMock.Core.DI; using DalaMock.Core.Mocks; +using ImGuiNET; using Lumina.Excel.Sheets; namespace InventoryToolsMock diff --git a/InventoryToolsMock/packages.lock.json b/InventoryToolsMock/packages.lock.json index 33bd64fd..307eabba 100644 --- a/InventoryToolsMock/packages.lock.json +++ b/InventoryToolsMock/packages.lock.json @@ -4,9 +4,9 @@ "net8.0-windows7.0": { "DalaMock.Core": { "type": "Direct", - "requested": "[2.1.6, )", - "resolved": "2.1.6", - "contentHash": "DPcQd43UvUvvKlosFt1TIm1u1m1r+gxliJTWSDWTKOJzIInu5m2uGrlKGGsWxzdqtfHFk6a6H2/xIwqVXtnStQ==", + "requested": "[2.1.7, )", + "resolved": "2.1.7", + "contentHash": "NDgZXtdUo9M1p6hWfJfMcWbfJV/AjTAncWG0LogFInQyd6w499LWlUkQDbRRfa12u6RrhF0dvraZhZxG5e5pxw==", "dependencies": { "Autofac": "8.0.0", "DalaMock.Shared": "2.1.6", @@ -176,13 +176,13 @@ }, "AllaganLib.GameSheets": { "type": "Transitive", - "resolved": "1.1.15", - "contentHash": "pis0YWRcG5OjhIxsAc712TpavdQerjjnN9Ii9ASm71ldqju8cOgHTTZ18f9EtrEv06xHvA1EdG3NLKvi4Z93QA==", + "resolved": "1.1.17", + "contentHash": "ViziJLY97Wsxs8k52zVBzchdFUU3bnW7jJZX8fuL0bmYQD4D5lErTyZimrVUmZS2nKwicgBTl/e+EtvyHXIE3Q==", "dependencies": { "AllaganLib.Shared": "1.1.12", "Autofac.Extensions.DependencyInjection": "9.0.0", "CSVFile": "3.2.0", - "LuminaSupplemental.Excel": "2.1.6" + "LuminaSupplemental.Excel": "2.1.8" } }, "AllaganLib.Shared": { @@ -223,11 +223,11 @@ }, "DalaMock.Host": { "type": "Transitive", - "resolved": "2.1.5", - "contentHash": "292Fx954HO4AJnKQ16KzlyCaudhL0E4tW9Ytjmt1aO8CUzWqteybEfaZGieFkfzC3UCaq/3AsbWl4mJX6bRU6Q==", + "resolved": "2.1.6", + "contentHash": "wCS8xL11kzT39jyMkNo9+kf/JmF3gcGaF1bk2avuf59+121xjv4lj/a5jTwjzOqZLomSVVKLxWdSEsk5EuRrjA==", "dependencies": { "Autofac.Extensions.DependencyInjection": "9.0.0", - "DalaMock.Shared": "2.1.5", + "DalaMock.Shared": "2.1.6", "Microsoft.Extensions.Hosting": "8.0.0", "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", "Microsoft.Extensions.ObjectPool": "9.0.0-preview.6.24328.4" @@ -255,8 +255,8 @@ }, "LuminaSupplemental.Excel": { "type": "Transitive", - "resolved": "2.1.6", - "contentHash": "h/rGvwCbQJ3xBDApu77xpZWgmr98EGjcXbsOyfIaCnzi5MUh3IQRIPyD+qQTEE9Tcw8unw3gEiJNxd/s0syhuw==", + "resolved": "2.1.8", + "contentHash": "erJ2gwQvLU83jucUXa/aM+mJcFMdyDmpb328DFs5cO1VL2S+pgCx3m52+bFtULgkDVZnGCcR2EFYSQj9TlocIg==", "dependencies": { "CSVFile": "3.1.0", "CsvHelper": "30.0.1" @@ -827,7 +827,7 @@ "criticalcommonlib": { "type": "Project", "dependencies": { - "AllaganLib.GameSheets": "[1.1.15, )", + "AllaganLib.GameSheets": "[1.1.17, )", "Humanizer.Core": "[3.0.0-beta.54, )", "Microsoft.Extensions.Hosting": "[8.0.1, )", "NaturalSort.Extension": "[3.2.0, )", @@ -842,7 +842,7 @@ "Autofac.Extensions.DependencyInjection": "[9.0.0, )", "CriticalCommonLib": "[1.0.0, )", "CsvHelper": "[30.0.1, )", - "DalaMock.Host": "[2.1.5, )", + "DalaMock.Host": "[2.1.6, )", "DalamudPackager": "[11.0.0, )", "Humanizer.Core": "[3.0.0-beta.54, )", "Microsoft.AspNetCore.SignalR.Client": "[7.0.11, )",