diff --git a/Gearsetter/Gearsetter.csproj b/Gearsetter/Gearsetter.csproj index 29b15c3..595d731 100644 --- a/Gearsetter/Gearsetter.csproj +++ b/Gearsetter/Gearsetter.csproj @@ -1,6 +1,6 @@ - 1.0 + 1.1 dist diff --git a/Gearsetter/GearsetterPlugin.cs b/Gearsetter/GearsetterPlugin.cs index dfa26ee..28c1d8c 100644 --- a/Gearsetter/GearsetterPlugin.cs +++ b/Gearsetter/GearsetterPlugin.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading.Tasks; using Dalamud.Game.Command; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; @@ -121,6 +122,7 @@ public sealed class GearsetterPlugin : IDalamudPlugin private unsafe void ShowUpgrades(byte? level = null) { + DateTime start = DateTime.Now; var inventoryItems = GetAllInventoryItems(); var gearsetModule = RaptureGearsetModule.Instance(); @@ -131,7 +133,7 @@ public sealed class GearsetterPlugin : IDalamudPlugin if (onlyCurrentJob) _chatGui.Print("Checking only gearsets for your current class/job..."); - bool anyUpgrade = false; + List gearsets = new List(); for (int i = 0; i < 100; ++i) { var gearset = gearsetModule->GetGearset(i); @@ -140,44 +142,65 @@ public sealed class GearsetterPlugin : IDalamudPlugin if (onlyCurrentJob && gearset->ClassJob != _clientState.LocalPlayer!.ClassJob.Id) continue; - anyUpgrade |= HandleGearset(gearset, inventoryItems, level); + var gearsetData = PrepareGearset(gearset); + if (gearsetData != null) + gearsets.Add(gearsetData); } } - if (!anyUpgrade) - _chatGui.Print("All your gearsets are OK."); + _pluginLog.Information($"Preparing gearsets took {DateTime.Now - start}"); + + Task.Run(() => + { + start = DateTime.Now; + bool anyUpgrade = false; + foreach (GearsetData gearset in gearsets) + anyUpgrade |= HandleGearset(gearset, inventoryItems, level); + + if (!anyUpgrade) + _chatGui.Print("All your gearsets are OK."); + + _pluginLog.Information($"Evaluating gearsets took {DateTime.Now - start}"); + }); } - private unsafe bool HandleGearset(RaptureGearsetModule.GearsetEntry* gearset, - Dictionary<(uint ItemId, bool Hq), List> inventoryItems, byte? level) + private unsafe GearsetData? PrepareGearset(RaptureGearsetModule.GearsetEntry* gearset) { string name = GetGearsetName(gearset); if (name.Contains('_', StringComparison.Ordinal) || name.Contains("Eureka", StringComparison.OrdinalIgnoreCase) || name.Contains("Bozja", StringComparison.OrdinalIgnoreCase)) - return false; + return null; - List Handle(string label, RaptureGearsetModule.GearsetItemIndex[] spanIds, EEquipSlotCategory category) + return new GearsetData(_dataManager, gearset, name); + } + + private bool HandleGearset(GearsetData gearset, + Dictionary<(uint ItemId, bool Hq), List> inventoryItems, byte? level) + { + List Handle(string label, EquipmentItem?[] gearsetItems, + EEquipSlotCategory category) { - return HandleGearsetItem(label, gearset, spanIds.Select(x => gearset->GetItem(x)).ToArray(), - inventoryItems, category, level); + return HandleGearsetItem(label, gearset, gearsetItems, inventoryItems, category, level); } List> upgrades = new() { - Handle("Main Hand", [RaptureGearsetModule.GearsetItemIndex.MainHand], EEquipSlotCategory.None), + Handle("Main Hand", [gearset.MainHand], EEquipSlotCategory.None), HandleOffHand(gearset, inventoryItems, level), - Handle("Head", [RaptureGearsetModule.GearsetItemIndex.Head], EEquipSlotCategory.Head), - Handle("Body", [RaptureGearsetModule.GearsetItemIndex.Body], EEquipSlotCategory.Body), - Handle("Hands", [RaptureGearsetModule.GearsetItemIndex.Hands], EEquipSlotCategory.Hands), - Handle("Legs", [RaptureGearsetModule.GearsetItemIndex.Legs], EEquipSlotCategory.Legs), - Handle("Feet", [RaptureGearsetModule.GearsetItemIndex.Feet], EEquipSlotCategory.Feet), + Handle("Head", [gearset.Head], EEquipSlotCategory.Head), + Handle("Body", [gearset.Body], EEquipSlotCategory.Body), + Handle("Hands", [gearset.Hands], EEquipSlotCategory.Hands), + Handle("Legs", [gearset.Legs], EEquipSlotCategory.Legs), + Handle("Feet", [gearset.Feet], EEquipSlotCategory.Feet), - Handle("Ears", [RaptureGearsetModule.GearsetItemIndex.Ears], EEquipSlotCategory.Ears), - Handle("Neck", [RaptureGearsetModule.GearsetItemIndex.Neck], EEquipSlotCategory.Neck), - Handle("Wrists", [RaptureGearsetModule.GearsetItemIndex.Wrists], EEquipSlotCategory.Wrists), - Handle("Rings", [RaptureGearsetModule.GearsetItemIndex.RingLeft, RaptureGearsetModule.GearsetItemIndex.RingRight], EEquipSlotCategory.Rings), + Handle("Ears", [gearset.Ears], EEquipSlotCategory.Ears), + Handle("Neck", [gearset.Neck], EEquipSlotCategory.Neck), + Handle("Wrists", [gearset.Wrists], EEquipSlotCategory.Wrists), + Handle("Rings", + [gearset.RingLeft, gearset.RingRight], + EEquipSlotCategory.Rings), }; List flatUpgrades = upgrades.SelectMany(x => x).ToList(); @@ -188,9 +211,9 @@ public sealed class GearsetterPlugin : IDalamudPlugin new SeStringBuilder() .Append("Gearset ") .AddUiForeground(1) - .Add(_linkPayloads[gearset->Id]) - .Append($"#{gearset->Id + 1}: ") - .Append(name) + .Add(_linkPayloads[gearset.Id]) + .Append($"#{gearset.Id + 1}: ") + .Append(gearset.Name) .Add(RawPayload.LinkTerminator) .AddUiForegroundOff() .AddText(level != null ? $" at {level}" : "") @@ -209,20 +232,18 @@ public sealed class GearsetterPlugin : IDalamudPlugin private unsafe string GetGearsetName(RaptureGearsetModule.GearsetEntry* gearset) => gearset->NameString.Split((char)0)[0]; - private unsafe List HandleGearsetItem(string label, RaptureGearsetModule.GearsetEntry* gearset, - RaptureGearsetModule.GearsetItem[] gearsetItem, + private List HandleGearsetItem(string label, GearsetData gearset, + EquipmentItem?[] gearsetItems, Dictionary<(uint ItemId, bool Hq), List> inventoryItems, EEquipSlotCategory equipSlotCategory, byte? level) { - EClassJob classJob = (EClassJob)gearset->ClassJob; + EClassJob classJob = gearset.ClassJob; var itemLists = _gameDataHolder.GetItemLists(classJob); - if (gearsetItem.Any(x => x.ItemId > 0)) + if (equipSlotCategory == EEquipSlotCategory.None && gearsetItems.Any(x => x != null)) { - var firstEquippedItem = gearsetItem.First(x => x.ItemId > 0); - equipSlotCategory = (EEquipSlotCategory)(_dataManager.GetExcelSheet()! - .GetRow(firstEquippedItem.ItemId % 1_000_000) - ?.EquipSlotCategory?.Row ?? 0); + var firstEquippedItem = gearsetItems.First(x => x != null); + equipSlotCategory = firstEquippedItem!.EquipSlotCategory; } if (equipSlotCategory == EEquipSlotCategory.None) @@ -231,14 +252,10 @@ public sealed class GearsetterPlugin : IDalamudPlugin return new List(); } - BaseItem?[] currentItems = gearsetItem.Select(x => new - { - ItemId = x.ItemId % 1_000_000, - Hq = x.ItemId > 1_000_000 - }) + BaseItem?[] currentItems = gearsetItems .Select(x => { - if (x.ItemId == 0) + if (x == null) return null; return itemLists @@ -261,7 +278,7 @@ public sealed class GearsetterPlugin : IDalamudPlugin var bestItems = availableList.Items .Where(x => x.Level <= level) .Where(x => x is Model.InventoryItem) - .Take(gearsetItem.Length) + .Take(gearsetItems.Length) .ToList(); //_pluginLog.Debug( // $"{equipSlotCategory}: {string.Join(" ", currentItems.Select(x => $"{x?.ItemId}|{x?.Hq}"))}"); @@ -284,20 +301,20 @@ public sealed class GearsetterPlugin : IDalamudPlugin } - private unsafe List HandleOffHand(RaptureGearsetModule.GearsetEntry* gearset, + private unsafe List HandleOffHand(GearsetData gearset, Dictionary<(uint ItemId, bool Hq), List> inventoryItems, byte? level) { - var mainHand = gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.MainHand); - if (mainHand.ItemId == 0) + var mainHand = gearset.MainHand; + if (mainHand == null) return new List(); // if it's a twohanded weapon, ignore it - EEquipSlotCategory equipSlotCategory = - (EEquipSlotCategory)(_dataManager.GetExcelSheet()!.GetRow(mainHand.ItemId % 1_000_000)?.RowId ?? 0); + EEquipSlotCategory equipSlotCategory = mainHand.EquipSlotCategory; if (equipSlotCategory != EEquipSlotCategory.OneHandedMainHand) return new List(); - return HandleGearsetItem("Off Hand", gearset, [gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.OffHand)], inventoryItems, + return HandleGearsetItem("Off Hand", gearset, [gearset.OffHand], + inventoryItems, EEquipSlotCategory.Shield, level); } diff --git a/Gearsetter/Model/GearsetData.cs b/Gearsetter/Model/GearsetData.cs new file mode 100644 index 0000000..d576bfa --- /dev/null +++ b/Gearsetter/Model/GearsetData.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.UI.Misc; +using Gearsetter.GameData; +using Lumina.Excel.GeneratedSheets; + +namespace Gearsetter.Model; + +internal sealed class GearsetData +{ + public unsafe GearsetData(IDataManager dataManager, RaptureGearsetModule.GearsetEntry* gearset, string name) + { + Id = gearset->Id; + ClassJob = (EClassJob)gearset->ClassJob; + Name = name; + MainHand = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.MainHand); + OffHand = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.OffHand); + Head = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Head); + Body = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Body); + Hands = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Hands); + Legs = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Legs); + Feet = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Feet); + Ears = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Ears); + Neck = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Neck); + Wrists = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.Wrists); + RingLeft = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.RingLeft); + RingRight = GetItem(dataManager, gearset, RaptureGearsetModule.GearsetItemIndex.RingRight); + } + + private static unsafe EquipmentItem? GetItem(IDataManager dataManager, RaptureGearsetModule.GearsetEntry* gearset, + RaptureGearsetModule.GearsetItemIndex index) + { + var gearsetItem = gearset->GetItem(index); + if (gearsetItem.ItemId == 0) + return null; + + var item = dataManager.GetExcelSheet()!.GetRow(gearsetItem.ItemId % 1_000_000)!; + return new EquipmentItem(item, gearsetItem.ItemId > 1_000_000); + } + + public byte Id { get; } + public EClassJob ClassJob { get; } + public string Name { get; } + public EquipmentItem? MainHand { get; } + public EquipmentItem? OffHand { get; } + public EquipmentItem? Head { get; } + public EquipmentItem? Body { get; } + public EquipmentItem? Hands { get; } + public EquipmentItem? Legs { get; } + public EquipmentItem? Feet { get; } + public EquipmentItem? Ears { get; set; } + public EquipmentItem? Neck { get; set; } + public EquipmentItem? Wrists { get; } + public EquipmentItem? RingLeft { get; } + public EquipmentItem? RingRight { get; } +} diff --git a/Gearsetter/Windows/EquipmentBrowserWindow.cs b/Gearsetter/Windows/EquipmentBrowserWindow.cs index cba4844..9b2f8e5 100644 --- a/Gearsetter/Windows/EquipmentBrowserWindow.cs +++ b/Gearsetter/Windows/EquipmentBrowserWindow.cs @@ -141,7 +141,8 @@ internal sealed class EquipmentBrowserWindow : LWindow ImGui.TableHeadersRow(); ImGui.PushStyleColor(ImGuiCol.HeaderHovered, hoverColor); - foreach (var item in itemList.Items.DistinctBy(x => new { x.ItemId, x.Hq, Materia = x.MateriaStats?.GetHashCode() })) + foreach (var item in itemList.Items.DistinctBy(x => new + { x.ItemId, x.Hq, Materia = x.MateriaStats?.GetHashCode() })) { if (item is not InventoryItem) {