diff --git a/QuestMap/Filters.cs b/QuestMap/Filters.cs index cfafcf9..32f23ed 100644 --- a/QuestMap/Filters.cs +++ b/QuestMap/Filters.cs @@ -1,6 +1,7 @@ using Lumina.Excel.GeneratedSheets; using System.Collections.Generic; using System.Linq; +using FFXIVClientStructs.FFXIV.Client.Game; namespace QuestMap { @@ -249,7 +250,7 @@ namespace QuestMap public bool IsObtainable(Quest quest) { - if (Plugin.Common.Functions.Journal.IsQuestCompleted(quest)) + if (QuestManager.IsQuestComplete(quest.RowId)) return true; if (FilterConditions.Any(f => f.IsUnobtainable(Plugin, quest.RowId))) @@ -274,7 +275,7 @@ namespace QuestMap public bool IsUnobtainable(Plugin plugin, uint quest) { - return QuestIds.Contains(quest) && QuestIds.Any(plugin.Common.Functions.Journal.IsQuestCompleted); + return QuestIds.Contains(quest) && QuestIds.Any(QuestManager.IsQuestComplete); } } @@ -291,7 +292,7 @@ namespace QuestMap public bool IsUnobtainable(Plugin plugin, uint quest) { - return quest == OriginalQuestId || (quest == NewQuestId && plugin.Common.Functions.Journal.IsQuestCompleted(OriginalQuestId)); + return quest == OriginalQuestId || (quest == NewQuestId && QuestManager.IsQuestComplete(OriginalQuestId)); } } @@ -308,7 +309,7 @@ namespace QuestMap public bool IsUnobtainable(Plugin plugin, uint quest) { - if (plugin.Common.Functions.Journal.IsQuestCompleted(RequiredQuest)) + if (QuestManager.IsQuestComplete(RequiredQuest)) return false; return FollowUpQuests.Contains(quest); @@ -328,7 +329,7 @@ namespace QuestMap public bool IsUnobtainable(Plugin plugin, uint quest) { - if (plugin.Common.Functions.Journal.IsQuestCompleted(StartingClassQuestId)) + if (QuestManager.IsQuestComplete(StartingClassQuestId)) return LaterClassQuestIds.Contains(quest); else return quest == StartingClassQuestId; @@ -357,7 +358,7 @@ namespace QuestMap // - Seeking Sanctuary is unlockable after 6.0 public bool IsUnobtainable(Plugin plugin, uint quest) { - return quest == 70_180 && plugin.Common.Functions.Journal.IsQuestCompleted(70_179); + return quest == 70_180 && QuestManager.IsQuestComplete(70_179); } } } diff --git a/QuestMap/Node.cs b/QuestMap/Node.cs index 439cce2..3d76060 100644 --- a/QuestMap/Node.cs +++ b/QuestMap/Node.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Dalamud.Plugin.Services; using Lumina.Excel.GeneratedSheets; namespace QuestMap { @@ -9,7 +8,7 @@ namespace QuestMap { internal uint Id { get; } internal List> Parents { get; set; } internal T Value { get; set; } - internal List> Children { get; } = new(); + internal List> Children { get; } = []; internal Node(List> parents, uint id, T value) { this.Id = id; @@ -19,7 +18,7 @@ namespace QuestMap { private Node(uint id) { this.Id = id; - this.Parents = new List>(); + this.Parents = []; this.Value = default!; } @@ -59,7 +58,7 @@ namespace QuestMap { var consolidated = consolidator(parent.Value); parents.Push(consolidated == null ? parent - : new Node(new List>(), parent.Id, consolidated) { + : new Node([], parent.Id, consolidated) { Children = { this }, }); } @@ -71,7 +70,7 @@ namespace QuestMap { var consolidated = consolidator(parent.Value); parents.Push(consolidated == null ? parent - : new Node(new List>(), parent.Id, consolidated) { + : new Node([], parent.Id, consolidated) { Children = { next }, }); } @@ -102,8 +101,7 @@ namespace QuestMap { } } - internal static (List>, Dictionary>) BuildTree(Dictionary layouts, - IDataManager dataManager) { + internal static (List>, Dictionary>) BuildTree(Dictionary layouts) { var lookup = new Dictionary>(); var rootNodes = new List>(); var allNodes = new Dictionary>(); @@ -112,12 +110,12 @@ namespace QuestMap { if (lookup.TryGetValue(item.Key, out var ourNode)) { ourNode.Value = item.Value; } else { - ourNode = new Node(new List>(), item.Key, item.Value); + ourNode = new Node([], item.Key, item.Value); lookup[item.Key] = ourNode; allNodes[item.Key] = ourNode; } - var previous = item.Value.PreviousQuests(dataManager).ToList(); + var previous = item.Value.PreviousQuests().ToList(); if (previous.Count == 0) { rootNodes.Add(ourNode); } else { @@ -152,19 +150,12 @@ namespace QuestMap { return null; } - internal static IEnumerable PreviousQuests(this Quest quest, IDataManager dataManager) { + internal static IEnumerable PreviousQuests(this Quest quest) { foreach (var previous in quest.PreviousQuest) { if (previous != null && previous.Row != 0) { yield return previous.Value!; } } - - if (quest.Unknown12 != 0) - { - var previous = dataManager.GetExcelSheet()!.GetRow(quest.Unknown12); - if (previous != null) - yield return previous; - } } } } diff --git a/QuestMap/Plugin.cs b/QuestMap/Plugin.cs index b3ba224..3beaff6 100644 --- a/QuestMap/Plugin.cs +++ b/QuestMap/Plugin.cs @@ -2,7 +2,6 @@ using Dalamud.IoC; using Dalamud.Plugin; using Dalamud.Plugin.Services; -using XivCommon; namespace QuestMap { // ReSharper disable once ClassNeverInstantiated.Global @@ -10,7 +9,7 @@ namespace QuestMap { internal static string Name => "Quest Map"; [PluginService] - internal DalamudPluginInterface Interface { get; init; } = null!; + internal IDalamudPluginInterface Interface { get; init; } = null!; [PluginService] internal IClientState ClientState { get; init; } = null!; @@ -27,15 +26,13 @@ namespace QuestMap { [PluginService] internal ITextureProvider TextureProvider { get; init; } = null!; - internal XivCommonBase Common { get; } internal Configuration Config { get; } internal Quests Quests { get; } internal PluginUi Ui { get; } private Commands Commands { get; } - public Plugin(DalamudPluginInterface pi) { + public Plugin(IDalamudPluginInterface pi) { pi.Inject(this); // not sure why [PluginInterface] above aren't initialized by dalamud, but they're null - this.Common = new XivCommonBase(this.Interface); this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration(); var graphChannel = Channel.CreateUnbounded(); @@ -48,7 +45,6 @@ namespace QuestMap { public void Dispose() { this.Commands.Dispose(); this.Ui.Dispose(); - this.Common.Dispose(); } internal void SaveConfig() { diff --git a/QuestMap/PluginUi.cs b/QuestMap/PluginUi.cs index db007e3..a19146c 100644 --- a/QuestMap/PluginUi.cs +++ b/QuestMap/PluginUi.cs @@ -5,11 +5,14 @@ using System.Numerics; using System.Reflection; using System.Threading; using System.Threading.Channels; -using Dalamud; +using Dalamud.Game; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Interface; -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures; +using Dalamud.Interface.Textures.TextureWraps; +using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI.Agent; using ImGuiNET; using Lumina.Data; using Lumina.Excel; @@ -42,9 +45,8 @@ namespace QuestMap { private Node? Centre { get; set; } private ChannelReader GraphChannel { get; } private CancellationTokenSource? CancellationTokenSource { get; set; } - private HashSet InfoWindows { get; } = new(); - private Dictionary Icons { get; } = new(); - private List<(Quest, bool, string)> FilteredQuests { get; } = new(); + private HashSet InfoWindows { get; } = []; + private List<(Quest, bool, string)> FilteredQuests { get; } = []; internal bool Show; @@ -70,17 +72,13 @@ namespace QuestMap { public void Dispose() { this.Plugin.Interface.UiBuilder.OpenConfigUi -= this.OpenConfig; this.Plugin.Interface.UiBuilder.Draw -= this.Draw; - - foreach (var icon in this.Icons.Values) { - icon.Dispose(); - } } private void OpenConfig() { this.Show = true; } - private void Refilter() { + private unsafe void Refilter() { this.FilteredQuests.Clear(); var filterLower = this._filter.ToLowerInvariant(); @@ -94,7 +92,7 @@ namespace QuestMap { return false; } - var completed = this.Plugin.Common.Functions.Journal.IsQuestCompleted(quest); + var completed = QuestManager.IsQuestComplete(quest.RowId); if (!this.Plugin.Config.ShowCompleted && completed) { return false; } @@ -197,7 +195,7 @@ namespace QuestMap { this.DrawMainWindow(); } - private void DrawMainWindow() { + private unsafe void DrawMainWindow() { if (!this.Show) { return; } @@ -296,13 +294,9 @@ namespace QuestMap { var (quest, indent, drawItem) = this.FilteredQuests[row]; void DrawSelectable(string name, Quest quest) { - var completed = this.Plugin.Common.Functions.Journal.IsQuestCompleted(quest) || !this.Filters.IsObtainable(quest); + var completed = QuestManager.IsQuestComplete(quest.RowId) || !this.Filters.IsObtainable(quest); if (completed) { - Vector4 disabled; - unsafe { - disabled = *ImGui.GetStyleColorVec4(ImGuiCol.TextDisabled); - } - + var disabled = *ImGui.GetStyleColorVec4(ImGuiCol.TextDisabled); ImGui.PushStyleColor(ImGuiCol.Text, disabled); } @@ -392,7 +386,7 @@ namespace QuestMap { return !open; } - var completed = this.Plugin.Common.Functions.Journal.IsQuestCompleted(quest); + var completed = QuestManager.IsQuestComplete(quest.RowId); ImGui.TextUnformatted($"Level: {quest.ClassJobLevel0}"); @@ -406,16 +400,7 @@ namespace QuestMap { } IDalamudTextureWrap? GetIcon(uint id) { - if (this.Icons.TryGetValue(id, out var wrap)) { - return wrap; - } - - wrap = this.Plugin.TextureProvider.GetIcon(id); - if (wrap != null) { - this.Icons[id] = wrap; - } - - return wrap; + return this.Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(id)).GetWrapOrDefault(); } var textWrap = ImGui.GetFontSize() * 20f; @@ -424,7 +409,7 @@ namespace QuestMap { var header = GetIcon(quest.Icon); if (header != null) { textWrap = header.Width; - ImGui.Image(header.ImGuiHandle, new Vector2(header.Width, header.Height)); + ImGui.Image(header.ImGuiHandle, new Vector2(header.Width / 2f, header.Height / 2f)); } } @@ -459,8 +444,8 @@ namespace QuestMap { var maxHeight = items .Select(entry => GetIcon(entry.icon)) - .Where(image => image != null) - .Max(image => image!.Height); + .Select(image => image?.Height ?? 0) + .Max(height => height / 2f); var originalY = ImGui.GetCursorPosY(); foreach (var (name, icon, qty) in items) { @@ -470,7 +455,7 @@ namespace QuestMap { ImGui.SetCursorPosY(originalY + (maxHeight - image.Height) / 2f); } - ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height)); + ImGui.Image(image.ImGuiHandle, new Vector2(image.Width / 2f, image.Height / 2f)); Util.Tooltip(name.ToString()); } @@ -570,7 +555,7 @@ namespace QuestMap { if (icon > 0) { var image = GetIcon(icon); if (image != null) { - ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height)); + ImGui.Image(image.ImGuiHandle, new Vector2(image.Width / 2f, image.Height / 2f)); Util.Tooltip(this.Convert(instance.Name).ToString()); } } else { @@ -590,7 +575,7 @@ namespace QuestMap { var image = GetIcon(tribe.Icon); if (image != null) { - ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height)); + ImGui.Image(image.ImGuiHandle, new Vector2(image.Width / 2f, image.Height / 2f)); Util.Tooltip(this.Convert(tribe.Name).ToString()); } @@ -613,11 +598,11 @@ namespace QuestMap { // ReSharper disable once ConstantConditionalAccessQualifier .MakeGenericMethod(typeof(QuestData))? // ReSharper disable once ConstantConditionalAccessQualifier - .Invoke(this.Plugin.DataManager.Excel, new object?[] { + .Invoke(this.Plugin.DataManager.Excel, [ path, lang, null, - }) as ExcelSheet; + ]) as ExcelSheet; // default to english if reflection failed sheet ??= this.Plugin.DataManager.Excel.GetSheet(path); var firstData = sheet?.GetRow(0); @@ -664,7 +649,9 @@ namespace QuestMap { ImGui.SameLine(); if (Util.IconButton(FontAwesomeIcon.Book)) { - this.Plugin.Common.Functions.Journal.OpenQuest(quest); + unsafe { + AgentQuestJournal.Instance()->OpenForQuest(quest.RowId & 0xFFFF, 1); + } } Util.Tooltip("Open quest in Journal"); @@ -843,7 +830,7 @@ namespace QuestMap { }; var textColour = Colours.Text; - var completed = this.Plugin.Common.Functions.Journal.IsQuestCompleted(quest.RowId); + var completed = QuestManager.IsQuestComplete(quest.RowId); if (completed) { colour.W = .5f; textColour = (uint) ((0x80 << 24) | (textColour & 0xFFFFFF)); @@ -895,7 +882,9 @@ namespace QuestMap { } if (right) { - this.Plugin.Common.Functions.Journal.OpenQuest(id); + unsafe { + AgentQuestJournal.Instance()->OpenForQuest(id, 1); + } } break; @@ -911,7 +900,7 @@ namespace QuestMap { // ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 5); } - private static readonly byte[] NewLinePayload = { 0x02, 0x10, 0x01, 0x03 }; + private static readonly byte[] NewLinePayload = [0x02, 0x10, 0x01, 0x03]; private SeString Convert(Lumina.Text.SeString lumina) { var se = (SeString) lumina; diff --git a/QuestMap/QuestMap.csproj b/QuestMap/QuestMap.csproj index 90d6ca4..d194fed 100755 --- a/QuestMap/QuestMap.csproj +++ b/QuestMap/QuestMap.csproj @@ -1,9 +1,9 @@ - net7-windows + net8-windows QuestMap - 1.4.7 + 1.4.8 enable latest true @@ -33,6 +33,10 @@ $(DalamudLibPath)\ImGui.NET.dll False + + $(DalamudLibPath)\FFXIVClientStructs.dll + False + $(DalamudLibPath)\Lumina.dll False @@ -45,9 +49,8 @@ - - - + + diff --git a/QuestMap/Quests.cs b/QuestMap/Quests.cs index 0a3b264..ad6a404 100644 --- a/QuestMap/Quests.cs +++ b/QuestMap/Quests.cs @@ -62,7 +62,7 @@ namespace QuestMap { if (itemRewards.TryGetValue(quest.RowId, out var items)) { rewards = items; } else { - rewards = new List(); + rewards = []; itemRewards[quest.RowId] = rewards; } @@ -76,7 +76,7 @@ namespace QuestMap { if (itemRewards.TryGetValue(quest.RowId, out var items)) { rewards = items; } else { - rewards = new List(); + rewards = []; itemRewards[quest.RowId] = rewards; } @@ -112,7 +112,7 @@ namespace QuestMap { this.BeastRewards = beastRewards; this.JobRewards = jobRewards; - var (_, nodes) = Node.BuildTree(allQuests, this.Plugin.DataManager); + var (_, nodes) = Node.BuildTree(allQuests); this.AllNodes = nodes; } @@ -254,6 +254,8 @@ namespace QuestMap { 70214 => "Gods Revel, Lands Tremble (6.3)", 70279 => "The Dark Throne (6.4)", 70286 => "Growing Light (6.5)", + 70289 => "The Coming Dawn (6.55)", + 70495 => "Dawntrail (7.0)", _ => null, }; @@ -272,7 +274,7 @@ namespace QuestMap { private HashSet InstanceUnlocks(Quest quest, ICollection others) { if (quest.IsRepeatable) { - return new HashSet(); + return []; } var unlocks = new HashSet(); diff --git a/QuestMap/packages.lock.json b/QuestMap/packages.lock.json old mode 100644 new mode 100755 index 47af76d..64f3cfe --- a/QuestMap/packages.lock.json +++ b/QuestMap/packages.lock.json @@ -1,7 +1,7 @@ { "version": 1, "dependencies": { - "net7.0-windows7.0": { + "net8.0-windows7.0": { "AutomaticGraphLayout": { "type": "Direct", "requested": "[1.1.12, )", @@ -10,21 +10,15 @@ }, "DalamudPackager": { "type": "Direct", - "requested": "[2.1.12, )", - "resolved": "2.1.12", - "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg==" + "requested": "[2.1.13, )", + "resolved": "2.1.13", + "contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ==" }, "System.Threading.Channels": { "type": "Direct", - "requested": "[7.0.0, )", - "resolved": "7.0.0", - "contentHash": "qmeeYNROMsONF6ndEZcIQ+VxR4Q/TX/7uIVLJqtwIWL7dDWeh0l1UIqgo4wYyjG//5lUNhwkLDSFl+pAWO6oiA==" - }, - "XivCommon": { - "type": "Direct", - "requested": "[9.0.0, )", - "resolved": "9.0.0", - "contentHash": "avaBp3FmSCi/PiQhntCeBDYOHejdyTWmFtz4pRBVQQ8vHkmRx+YTk1la9dkYBMlXxRXKckEdH1iI1Fu61JlE7w==" + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==" } } }