using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using Questionable.Controller; using Questionable.Functions; using Questionable.Model; using Questionable.Model.Questing; using Questionable.Windows; using Questionable.Windows.QuestComponents; namespace Questionable.External; internal sealed class QuestionableIpc : IDisposable { public sealed class StepData { public required string QuestId { get; init; } public required byte Sequence { get; init; } public required int Step { get; init; } public required string InteractionType { get; init; } public required Vector3? Position { get; init; } public required ushort TerritoryId { get; init; } } private const string IpcIsRunning = "Questionable.IsRunning"; private const string IpcGetCurrentQuestId = "Questionable.GetCurrentQuestId"; private const string IpcGetCurrentStepData = "Questionable.GetCurrentStepData"; private const string IpcGetCurrentlyActiveEventQuests = "Questionable.GetCurrentlyActiveEventQuests"; private const string IpcStartQuest = "Questionable.StartQuest"; private const string IpcStartSingleQuest = "Questionable.StartSingleQuest"; private const string IpcIsQuestLocked = "Questionable.IsQuestLocked"; private const string IpcIsQuestCompleted = "Questionable.IsQuestCompleted"; private const string IpcIsQuestAvailable = "Questionable.IsQuestAvailable"; private const string IpcIsQuestAccepted = "Questionable.IsQuestAccepted"; private const string IpcIsQuestUnobtainable = "Questionable.IsQuestUnobtainable"; 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 ManualPriorityComponent _manualPriorityComponent; private readonly ICallGateProvider _isRunning; private readonly ICallGateProvider _getCurrentQuestId; private readonly ICallGateProvider _getCurrentStepData; private readonly ICallGateProvider> _getCurrentlyActiveEventQuests; private readonly ICallGateProvider _startQuest; private readonly ICallGateProvider _startSingleQuest; private readonly ICallGateProvider _isQuestLocked; private readonly ICallGateProvider _isQuestCompleted; private readonly ICallGateProvider _isQuestAvailable; private readonly ICallGateProvider _isQuestAccepted; private readonly ICallGateProvider _isQuestUnobtainable; 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, ManualPriorityComponent manualPriorityComponent, IDalamudPluginInterface pluginInterface) { QuestionableIpc questionableIpc = this; _questController = questController; _questRegistry = questRegistry; _questFunctions = questFunctions; _manualPriorityComponent = manualPriorityComponent; _isRunning = pluginInterface.GetIpcProvider("Questionable.IsRunning"); _isRunning.RegisterFunc(() => questController.AutomationType != QuestController.EAutomationType.Manual || questController.IsRunning); _getCurrentQuestId = pluginInterface.GetIpcProvider("Questionable.GetCurrentQuestId"); _getCurrentQuestId.RegisterFunc(() => questController.CurrentQuest?.Quest.Id.ToString()); _getCurrentStepData = pluginInterface.GetIpcProvider("Questionable.GetCurrentStepData"); _getCurrentStepData.RegisterFunc(GetStepData); _getCurrentlyActiveEventQuests = pluginInterface.GetIpcProvider>("Questionable.GetCurrentlyActiveEventQuests"); _getCurrentlyActiveEventQuests.RegisterFunc(() => (from q in eventInfoComponent.GetCurrentlyActiveEventQuests() select q.ToString()).ToList()); _startQuest = pluginInterface.GetIpcProvider("Questionable.StartQuest"); _startQuest.RegisterFunc((string questId) => questionableIpc.StartQuest(questId, single: false)); _startSingleQuest = pluginInterface.GetIpcProvider("Questionable.StartSingleQuest"); _startSingleQuest.RegisterFunc((string questId) => questionableIpc.StartQuest(questId, single: true)); _isQuestLocked = pluginInterface.GetIpcProvider("Questionable.IsQuestLocked"); _isQuestLocked.RegisterFunc(IsQuestLocked); _isQuestCompleted = pluginInterface.GetIpcProvider("Questionable.IsQuestCompleted"); _isQuestCompleted.RegisterFunc(IsQuestCompleted); _isQuestAvailable = pluginInterface.GetIpcProvider("Questionable.IsQuestAvailable"); _isQuestAvailable.RegisterFunc(IsQuestAvailable); _isQuestAccepted = pluginInterface.GetIpcProvider("Questionable.IsQuestAccepted"); _isQuestAccepted.RegisterFunc(IsQuestAccepted); _isQuestUnobtainable = pluginInterface.GetIpcProvider("Questionable.IsQuestUnobtainable"); _isQuestUnobtainable.RegisterFunc(IsQuestUnobtainable); _importQuestPriority = pluginInterface.GetIpcProvider("Questionable.ImportQuestPriority"); _importQuestPriority.RegisterFunc(ImportQuestPriority); _addQuestPriority = pluginInterface.GetIpcProvider("Questionable.AddQuestPriority"); _addQuestPriority.RegisterFunc(AddQuestPriority); _clearQuestPriority = pluginInterface.GetIpcProvider("Questionable.ClearQuestPriority"); _clearQuestPriority.RegisterFunc(ClearQuestPriority); _insertQuestPriority = pluginInterface.GetIpcProvider("Questionable.InsertQuestPriority"); _insertQuestPriority.RegisterFunc(InsertQuestPriority); _exportQuestPriority = pluginInterface.GetIpcProvider("Questionable.ExportQuestPriority"); _exportQuestPriority.RegisterFunc(_manualPriorityComponent.EncodeQuestPriority); } private bool StartQuest(string questId, bool single) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.TryGetQuest(elementId, out Quest quest)) { _questController.SetNextQuest(quest); if (single) { _questController.StartSingleQuest("IPCQuestSelection"); } else { _questController.Start("IPCQuestSelection"); } return true; } return false; } private StepData? GetStepData() { QuestController.QuestProgress currentQuest = _questController.CurrentQuest; if (currentQuest == null) { return null; } string text = currentQuest.Quest.Id.ToString(); if (string.IsNullOrEmpty(text)) { return null; } QuestStep questStep = currentQuest.Quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step); if (questStep == null) { return null; } return new StepData { QuestId = text, Sequence = currentQuest.Sequence, Step = currentQuest.Step, InteractionType = questStep.InteractionType.ToString(), Position = questStep.Position, TerritoryId = questStep.TerritoryId }; } private bool IsQuestLocked(string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.TryGetQuest(elementId, out Quest _)) { return _questFunctions.IsQuestLocked(elementId); } return true; } private bool IsQuestCompleted(string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null) { return _questFunctions.IsQuestComplete(elementId); } return false; } private bool IsQuestAvailable(string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null) { return _questFunctions.IsReadyToAcceptQuest(elementId); } return false; } private bool IsQuestAccepted(string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null) { return _questFunctions.IsQuestAccepted(elementId); } return false; } private bool IsQuestUnobtainable(string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null) { return _questFunctions.IsQuestUnobtainable(elementId); } return false; } 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 ElementId elementId) && elementId != null && _questRegistry.IsKnownQuest(elementId)) { return _questController.AddQuestPriority(elementId); } return true; } private bool InsertQuestPriority(int index, string questId) { if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.IsKnownQuest(elementId)) { return _questController.InsertQuestPriority(index, elementId); } return true; } public void Dispose() { _exportQuestPriority.UnregisterFunc(); _insertQuestPriority.UnregisterFunc(); _clearQuestPriority.UnregisterFunc(); _addQuestPriority.UnregisterFunc(); _importQuestPriority.UnregisterFunc(); _isQuestUnobtainable.UnregisterFunc(); _isQuestAccepted.UnregisterFunc(); _isQuestAvailable.UnregisterFunc(); _isQuestCompleted.UnregisterFunc(); _isQuestLocked.UnregisterFunc(); _startSingleQuest.UnregisterFunc(); _startQuest.UnregisterFunc(); _getCurrentlyActiveEventQuests.UnregisterFunc(); _getCurrentStepData.UnregisterFunc(); _getCurrentQuestId.UnregisterFunc(); _isRunning.UnregisterFunc(); } }