diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index c10d160c..23680978 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Text; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Keys; using Dalamud.Game.Gui.Toast; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; +using Lumina.Excel.Sheets; using Microsoft.Extensions.Logging; using Questionable.Controller.Steps; using Questionable.Controller.Steps.Interactions; @@ -819,6 +821,48 @@ internal sealed class QuestController : MiniTaskController return false; } + public void ImportQuestPriority(List questElements) + { + foreach (ElementId elementId in questElements) + { + if (_questRegistry.TryGetQuest(elementId, out Quest? quest) && !ManualPriorityQuests.Contains(quest)) + ManualPriorityQuests.Add(quest); + } + } + + private const char ClipboardSeparator = ';'; + public string ExportQuestPriority() + { + return string.Join(ClipboardSeparator, ManualPriorityQuests.Select(x => x.Id.ToString())); + } + + public void ClearQuestPriority() + { + ManualPriorityQuests.Clear(); + } + + public bool AddQuestPriority(ElementId elementId) + { + if (_questRegistry.TryGetQuest(elementId, out Quest? quest) && !ManualPriorityQuests.Contains(quest)) + ManualPriorityQuests.Add(quest); + return true; + } + + public bool InsertQuestPriority(int index, ElementId elementId) + { + try + { + if (_questRegistry.TryGetQuest(elementId, out Quest? quest) && !ManualPriorityQuests.Contains(quest)) + ManualPriorityQuests.Insert(index, quest); + return true; + } + catch (Exception e) { + _logger.LogError(e, "Failed to insert quest in priority list"); + _chatGui.PrintError("Failed to insert quest in priority list, please check /xllog for details.", CommandHandler.MessageTag, CommandHandler.TagColor); + return false; + } + } + public bool WasLastTaskUpdateWithin(TimeSpan timeSpan) { _logger.LogInformation("Last update: {Update}", _lastTaskUpdate); diff --git a/Questionable/External/QuestionableIpc.cs b/Questionable/External/QuestionableIpc.cs index f1095f1e..835ecbca 100644 --- a/Questionable/External/QuestionableIpc.cs +++ b/Questionable/External/QuestionableIpc.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using Dalamud.Game.ClientState.Objects; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using JetBrains.Annotations; using Questionable.Controller; using Questionable.Functions; using Questionable.Model.Questing; +using Questionable.Windows; using Questionable.Windows.QuestComponents; namespace Questionable.External; @@ -21,10 +23,16 @@ internal sealed class QuestionableIpc : IDisposable private const string IpcStartQuest = "Questionable.StartQuest"; private const string IpcStartSingleQuest = "Questionable.StartSingleQuest"; private const string IpcIsQuestLocked = "Questionable.IsQuestLocked"; + private const string IpcImportQuestPriority = "Questionable.ImportQuestPriority"; + private const string IpcClearQuestPriority = "Questionable.ClearQuestPriority"; + private const string IpcAddQuestPriority = "Questionable.AddQuestPriority"; + private const string IpcInsertQuestPriority = "Questionable.InsertQuestPriority"; + private const string IpcExportQuestPriority = "Questionable.ExportQuestPriority"; private readonly QuestController _questController; private readonly QuestRegistry _questRegistry; private readonly QuestFunctions _questFunctions; + private readonly PriorityWindow _priorityWindow; private readonly ICallGateProvider _isRunning; private readonly ICallGateProvider _getCurrentQuestId; @@ -33,17 +41,24 @@ internal sealed class QuestionableIpc : IDisposable private readonly ICallGateProvider _startQuest; private readonly ICallGateProvider _startSingleQuest; private readonly ICallGateProvider _isQuestLocked; + private readonly ICallGateProvider _importQuestPriority; + private readonly ICallGateProvider _addQuestPriority; + private readonly ICallGateProvider _clearQuestPriority; + private readonly ICallGateProvider _insertQuestPriority; + private readonly ICallGateProvider _exportQuestPriority; public QuestionableIpc( QuestController questController, EventInfoComponent eventInfoComponent, QuestRegistry questRegistry, QuestFunctions questFunctions, + PriorityWindow priorityWindow, IDalamudPluginInterface pluginInterface) { _questController = questController; _questRegistry = questRegistry; _questFunctions = questFunctions; + _priorityWindow = priorityWindow; _isRunning = pluginInterface.GetIpcProvider(IpcIsRunning); _isRunning.RegisterFunc(() => @@ -65,10 +80,24 @@ internal sealed class QuestionableIpc : IDisposable _startSingleQuest = pluginInterface.GetIpcProvider(IpcStartSingleQuest); _startSingleQuest.RegisterFunc(questId => StartQuest(questId, true)); - //_startSingleQuest.RegisterFunc((questId) => StartQuest(questController, questRegistry, questId, true)); _isQuestLocked = pluginInterface.GetIpcProvider(IpcIsQuestLocked); _isQuestLocked.RegisterFunc((questId) => IsQuestLocked(questId)); + + _importQuestPriority = pluginInterface.GetIpcProvider(IpcImportQuestPriority); + _importQuestPriority.RegisterFunc((encodedQuestPriority) => ImportQuestPriority(encodedQuestPriority)); + + _importQuestPriority = pluginInterface.GetIpcProvider(IpcAddQuestPriority); + _importQuestPriority.RegisterFunc((questId) => AddQuestPriority(questId)); + + _clearQuestPriority = pluginInterface.GetIpcProvider(IpcClearQuestPriority); + _clearQuestPriority.RegisterFunc(ClearQuestPriority); + + _insertQuestPriority = pluginInterface.GetIpcProvider(IpcInsertQuestPriority); + _insertQuestPriority.RegisterFunc((index, questId) => InsertQuestPriority(index, questId)); + + _exportQuestPriority = pluginInterface.GetIpcProvider(IpcExportQuestPriority); + _exportQuestPriority.RegisterFunc(_priorityWindow.EncodeQuestPriority); } private bool StartQuest(string questId, bool single) @@ -122,6 +151,39 @@ internal sealed class QuestionableIpc : IDisposable return true; } + private bool ImportQuestPriority(string encodedQuestPriority) + { + List questElements = PriorityWindow.DecodeQuestPriority(encodedQuestPriority); + _questController.ImportQuestPriority(questElements); + return true; + } + + private bool ClearQuestPriority() + { + _questController.ClearQuestPriority(); + return true; + } + + private bool AddQuestPriority(string questId) + { + if (ElementId.TryFromString(questId, out var elementId) && elementId != null && + _questRegistry.TryGetQuest(elementId, out var quest)) + { + return _questController.AddQuestPriority(elementId); + } + return true; + } + + private bool InsertQuestPriority(int index, string questId) + { + if (ElementId.TryFromString(questId, out var elementId) && elementId != null && + _questRegistry.TryGetQuest(elementId, out var quest)) + { + return _questController.InsertQuestPriority(index, elementId); + } + return true; + } + public void Dispose() { _startSingleQuest.UnregisterFunc(); diff --git a/Questionable/Windows/PriorityWindow.cs b/Questionable/Windows/PriorityWindow.cs index 8b4d5202..5cbb6e9d 100644 --- a/Questionable/Windows/PriorityWindow.cs +++ b/Questionable/Windows/PriorityWindow.cs @@ -76,7 +76,7 @@ internal sealed class PriorityWindow : LWindow _questController.ManualPriorityQuests.RemoveAll(q => _questFunctions.IsQuestComplete(q.Id)); ImGui.SameLine(); if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Trash, "Clear")) - _questController.ManualPriorityQuests.Clear(); + _questController.ClearQuestPriority(); ImGui.EndDisabled(); ImGui.Spacing(); @@ -249,11 +249,16 @@ internal sealed class PriorityWindow : LWindow } private List ParseClipboardItems() + { + string? clipboardText = GetClipboardText(); + return DecodeQuestPriority(clipboardText); + } + + public static List DecodeQuestPriority(string? clipboardText) { List clipboardItems = new List(); try { - string? clipboardText = GetClipboardText(); if (clipboardText != null && clipboardText.StartsWith(ClipboardPrefix, StringComparison.InvariantCulture)) { clipboardText = clipboardText.Substring(ClipboardPrefix.Length); @@ -273,22 +278,22 @@ internal sealed class PriorityWindow : LWindow return clipboardItems; } + public string EncodeQuestPriority() + { + return ClipboardPrefix + Convert.ToBase64String(Encoding.UTF8.GetBytes( + string.Join(ClipboardSeparator, _questController.ManualPriorityQuests.Select(x => x.Id.ToString())))); + } + private void ExportToClipboard() { - string clipboardText = ClipboardPrefix + Convert.ToBase64String(Encoding.UTF8.GetBytes( - string.Join(ClipboardSeparator, _questController.ManualPriorityQuests.Select(x => x.Id.ToString())))); + string clipboardText = EncodeQuestPriority(); ImGui.SetClipboardText(clipboardText); _chatGui.Print("Copied quests to clipboard.", CommandHandler.MessageTag, CommandHandler.TagColor); } - private void ImportFromClipboard(List clipboardItems) + private void ImportFromClipboard(List questElements) { - foreach (ElementId elementId in clipboardItems) - { - if (_questRegistry.TryGetQuest(elementId, out Quest? quest) && - !_questController.ManualPriorityQuests.Contains(quest)) - _questController.ManualPriorityQuests.Add(quest); - } + _questController.ImportQuestPriority(questElements); } ///