1
0
Fork 0

Merge remote-tracking branch 'anna/main'

# Conflicts:
#	QuestMap/Plugin.cs
#	QuestMap/PluginUi.cs
main
Liza 2024-07-12 19:55:10 +02:00
commit 5511e36921
Signed by: liza
GPG Key ID: 7199F8D727D55F67
7 changed files with 68 additions and 92 deletions

View File

@ -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);
}
}
}

View File

@ -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<Node<T>> Parents { get; set; }
internal T Value { get; set; }
internal List<Node<T>> Children { get; } = new();
internal List<Node<T>> Children { get; } = [];
internal Node(List<Node<T>> 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<Node<T>>();
this.Parents = [];
this.Value = default!;
}
@ -59,7 +58,7 @@ namespace QuestMap {
var consolidated = consolidator(parent.Value);
parents.Push(consolidated == null
? parent
: new Node<T>(new List<Node<T>>(), parent.Id, consolidated) {
: new Node<T>([], parent.Id, consolidated) {
Children = { this },
});
}
@ -71,7 +70,7 @@ namespace QuestMap {
var consolidated = consolidator(parent.Value);
parents.Push(consolidated == null
? parent
: new Node<T>(new List<Node<T>>(), parent.Id, consolidated) {
: new Node<T>([], parent.Id, consolidated) {
Children = { next },
});
}
@ -102,8 +101,7 @@ namespace QuestMap {
}
}
internal static (List<Node<Quest>>, Dictionary<uint, Node<Quest>>) BuildTree(Dictionary<uint, Quest> layouts,
IDataManager dataManager) {
internal static (List<Node<Quest>>, Dictionary<uint, Node<Quest>>) BuildTree(Dictionary<uint, Quest> layouts) {
var lookup = new Dictionary<uint, Node<Quest>>();
var rootNodes = new List<Node<Quest>>();
var allNodes = new Dictionary<uint, Node<Quest>>();
@ -112,12 +110,12 @@ namespace QuestMap {
if (lookup.TryGetValue(item.Key, out var ourNode)) {
ourNode.Value = item.Value;
} else {
ourNode = new Node<Quest>(new List<Node<Quest>>(), item.Key, item.Value);
ourNode = new Node<Quest>([], 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<Quest> PreviousQuests(this Quest quest, IDataManager dataManager) {
internal static IEnumerable<Quest> 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<Quest>()!.GetRow(quest.Unknown12);
if (previous != null)
yield return previous;
}
}
}
}

View File

@ -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<GraphInfo>();
@ -48,7 +45,6 @@ namespace QuestMap {
public void Dispose() {
this.Commands.Dispose();
this.Ui.Dispose();
this.Common.Dispose();
}
internal void SaveConfig() {

View File

@ -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<GraphInfo> GraphChannel { get; }
private CancellationTokenSource? CancellationTokenSource { get; set; }
private HashSet<uint> InfoWindows { get; } = new();
private Dictionary<uint, IDalamudTextureWrap> Icons { get; } = new();
private List<(Quest, bool, string)> FilteredQuests { get; } = new();
private HashSet<uint> 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<QuestData>;
]) as ExcelSheet<QuestData>;
// default to english if reflection failed
sheet ??= this.Plugin.DataManager.Excel.GetSheet<QuestData>(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;

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7-windows</TargetFramework>
<TargetFramework>net8-windows</TargetFramework>
<RootNamespace>QuestMap</RootNamespace>
<Version>1.4.7</Version>
<Version>1.4.8</Version>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -33,6 +33,10 @@
<HintPath>$(DalamudLibPath)\ImGui.NET.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)\FFXIVClientStructs.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)\Lumina.dll</HintPath>
<Private>False</Private>
@ -45,9 +49,8 @@
<ItemGroup>
<PackageReference Include="AutomaticGraphLayout" Version="1.1.12"/>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
<PackageReference Include="System.Threading.Channels" Version="7.0.0"/>
<PackageReference Include="XivCommon" Version="9.0.0"/>
<PackageReference Include="DalamudPackager" Version="2.1.13" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
</ItemGroup>
</Project>

View File

@ -62,7 +62,7 @@ namespace QuestMap {
if (itemRewards.TryGetValue(quest.RowId, out var items)) {
rewards = items;
} else {
rewards = new List<Item>();
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<Item>();
rewards = [];
itemRewards[quest.RowId] = rewards;
}
@ -112,7 +112,7 @@ namespace QuestMap {
this.BeastRewards = beastRewards;
this.JobRewards = jobRewards;
var (_, nodes) = Node<Quest>.BuildTree(allQuests, this.Plugin.DataManager);
var (_, nodes) = Node<Quest>.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<ContentFinderCondition> InstanceUnlocks(Quest quest, ICollection<ContentFinderCondition> others) {
if (quest.IsRepeatable) {
return new HashSet<ContentFinderCondition>();
return [];
}
var unlocks = new HashSet<ContentFinderCondition>();

20
QuestMap/packages.lock.json Normal file → Executable file
View File

@ -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=="
}
}
}