qstbak/QuestionableCompanion/QuestionableCompanion.Services/QuestionableIPC.cs
2025-12-04 04:39:08 +10:00

959 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Services;
namespace QuestionableCompanion.Services;
public class QuestionableIPC : IDisposable
{
private readonly IDalamudPluginInterface pluginInterface;
private readonly IPluginLog log;
private ICallGateSubscriber<string, bool>? importQuestPrioritySubscriber;
private ICallGateSubscriber<string?>? getCurrentQuestIdSubscriber;
private ICallGateSubscriber<StepData?>? getCurrentStepDataSubscriber;
private ICallGateSubscriber<bool>? isRunningSubscriber;
private ICallGateSubscriber<object?>? getCurrentTaskSubscriber;
private ICallGateSubscriber<string, bool>? isQuestCompleteSubscriber;
private ICallGateSubscriber<string, bool>? isReadyToAcceptQuestSubscriber;
private ICallGateSubscriber<string, bool>? addQuestPrioritySubscriber;
private ICallGateSubscriber<bool>? clearQuestPrioritySubscriber;
private ICallGateSubscriber<List<string>>? getCurrentlyActiveEventQuestsSubscriber;
private ICallGateSubscriber<int>? getAlliedSocietyRemainingAllowancesSubscriber;
private ICallGateSubscriber<byte, List<string>>? getAlliedSocietyAvailableQuestIdsSubscriber;
private ICallGateSubscriber<Dictionary<byte, int>>? getAlliedSocietyAllAvailableQuestCountsSubscriber;
private ICallGateSubscriber<byte, bool>? getAlliedSocietyIsMaxRankSubscriber;
private ICallGateSubscriber<byte, int>? getAlliedSocietyCurrentRankSubscriber;
private ICallGateSubscriber<List<byte>>? getAlliedSocietiesWithAvailableQuestsSubscriber;
private ICallGateSubscriber<byte, int>? addAlliedSocietyOptimalQuestsSubscriber;
private ICallGateSubscriber<byte, List<string>>? getAlliedSocietyOptimalQuestsSubscriber;
private ICallGateSubscriber<long>? getAlliedSocietyTimeUntilResetSubscriber;
private ICallGateSubscriber<bool>? getStopConditionsEnabledSubscriber;
private ICallGateSubscriber<List<string>>? getStopQuestListSubscriber;
private ICallGateSubscriber<StopConditionData>? getLevelStopConditionSubscriber;
private ICallGateSubscriber<StopConditionData>? getSequenceStopConditionSubscriber;
private ICallGateSubscriber<string, uint, int, object?>? getQuestSequenceStopConditionSubscriber;
private ICallGateSubscriber<string, bool>? removeQuestSequenceStopConditionSubscriber;
private ICallGateSubscriber<Dictionary<string, object>>? getAllQuestSequenceStopConditionsSubscriber;
private ICallGateSubscriber<int>? getDefaultDutyModeSubscriber;
private ICallGateSubscriber<int, bool>? setDefaultDutyModeSubscriber;
private bool subscribersInitialized;
private DateTime lastAvailabilityCheck = DateTime.MinValue;
private const int AvailabilityCheckCooldownSeconds = 5;
public bool IsAvailable { get; private set; }
public QuestionableIPC(IDalamudPluginInterface pluginInterface, IPluginLog log)
{
this.pluginInterface = pluginInterface;
this.log = log;
InitializeIPC();
}
private void InitializeIPC()
{
try
{
getCurrentQuestIdSubscriber = pluginInterface.GetIpcSubscriber<string>("Questionable.GetCurrentQuestId");
getCurrentStepDataSubscriber = pluginInterface.GetIpcSubscriber<StepData>("Questionable.GetCurrentStepData");
isRunningSubscriber = pluginInterface.GetIpcSubscriber<bool>("Questionable.IsRunning");
importQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Questionable.ImportQuestPriority");
getCurrentTaskSubscriber = pluginInterface.GetIpcSubscriber<object>("Questionable.GetCurrentTask");
isQuestCompleteSubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Questionable.IsQuestComplete");
isReadyToAcceptQuestSubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Questionable.IsReadyToAcceptQuest");
addQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Questionable.AddQuestPriority");
clearQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber<bool>("Questionable.ClearQuestPriority");
getCurrentlyActiveEventQuestsSubscriber = pluginInterface.GetIpcSubscriber<List<string>>("Questionable.GetCurrentlyActiveEventQuests");
getAlliedSocietyRemainingAllowancesSubscriber = pluginInterface.GetIpcSubscriber<int>("Questionable.AlliedSociety.GetRemainingAllowances");
getAlliedSocietyAvailableQuestIdsSubscriber = pluginInterface.GetIpcSubscriber<byte, List<string>>("Questionable.AlliedSociety.GetAvailableQuestIds");
getAlliedSocietyAllAvailableQuestCountsSubscriber = pluginInterface.GetIpcSubscriber<Dictionary<byte, int>>("Questionable.AlliedSociety.GetAllAvailableQuestCounts");
getAlliedSocietyIsMaxRankSubscriber = pluginInterface.GetIpcSubscriber<byte, bool>("Questionable.AlliedSociety.IsMaxRank");
getAlliedSocietyCurrentRankSubscriber = pluginInterface.GetIpcSubscriber<byte, int>("Questionable.AlliedSociety.GetCurrentRank");
getAlliedSocietiesWithAvailableQuestsSubscriber = pluginInterface.GetIpcSubscriber<List<byte>>("Questionable.AlliedSociety.GetSocietiesWithAvailableQuests");
addAlliedSocietyOptimalQuestsSubscriber = pluginInterface.GetIpcSubscriber<byte, int>("Questionable.AlliedSociety.AddOptimalQuests");
getAlliedSocietyOptimalQuestsSubscriber = pluginInterface.GetIpcSubscriber<byte, List<string>>("Questionable.AlliedSociety.GetOptimalQuests");
getAlliedSocietyTimeUntilResetSubscriber = pluginInterface.GetIpcSubscriber<long>("Questionable.AlliedSociety.GetTimeUntilReset");
getStopConditionsEnabledSubscriber = pluginInterface.GetIpcSubscriber<bool>("Questionable.GetStopConditionsEnabled");
getStopQuestListSubscriber = pluginInterface.GetIpcSubscriber<List<string>>("Questionable.GetStopQuestList");
getLevelStopConditionSubscriber = pluginInterface.GetIpcSubscriber<StopConditionData>("Questionable.GetLevelStopCondition");
getSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber<StopConditionData>("Questionable.GetSequenceStopCondition");
getQuestSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber<string, uint, int, object>("Questionable.GetQuestSequenceStopCondition");
removeQuestSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Questionable.RemoveQuestSequenceStopCondition");
getAllQuestSequenceStopConditionsSubscriber = pluginInterface.GetIpcSubscriber<Dictionary<string, object>>("Questionable.GetAllQuestSequenceStopConditions");
getDefaultDutyModeSubscriber = pluginInterface.GetIpcSubscriber<int>("Questionable.GetDefaultDutyMode");
setDefaultDutyModeSubscriber = pluginInterface.GetIpcSubscriber<int, bool>("Questionable.SetDefaultDutyMode");
subscribersInitialized = true;
log.Debug("[QuestionableIPC] IPC subscribers initialized (lazy-loading enabled)");
}
catch (Exception ex)
{
IsAvailable = false;
subscribersInitialized = false;
log.Error("[QuestionableIPC] Failed to initialize subscribers: " + ex.Message);
}
}
private bool TryEnsureAvailable()
{
if (IsAvailable)
{
return true;
}
if (!subscribersInitialized)
{
log.Warning("[QuestionableIPC] Subscribers not initialized!");
return false;
}
DateTime now = DateTime.Now;
if ((now - lastAvailabilityCheck).TotalSeconds < 5.0)
{
return false;
}
lastAvailabilityCheck = now;
try
{
if (isRunningSubscriber == null)
{
log.Error("[QuestionableIPC] isRunningSubscriber is NULL!");
return false;
}
isRunningSubscriber.InvokeFunc();
if (!IsAvailable)
{
IsAvailable = true;
}
return true;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] Failed to connect to Questionable:");
log.Error("[QuestionableIPC] Exception Type: " + ex.GetType().Name);
log.Error("[QuestionableIPC] Message: " + ex.Message);
log.Error("[QuestionableIPC] Stack Trace: " + ex.StackTrace);
IsAvailable = false;
return false;
}
}
public bool ForceCheckAvailability()
{
try
{
if (!subscribersInitialized)
{
log.Error("[QuestionableIPC] Subscribers not initialized!");
return false;
}
if (isRunningSubscriber == null)
{
log.Error("[QuestionableIPC] isRunningSubscriber is NULL!");
return false;
}
log.Information("[QuestionableIPC] Force checking Questionable availability...");
log.Information("[QuestionableIPC] Attempting to call Questionable.IsRunning...");
bool testRunning = isRunningSubscriber.InvokeFunc();
log.Information($"[QuestionableIPC] SUCCESS! Questionable.IsRunning returned: {testRunning}");
IsAvailable = true;
lastAvailabilityCheck = DateTime.Now;
return true;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] Failed to connect to Questionable:");
log.Error("[QuestionableIPC] Exception Type: " + ex.GetType().Name);
log.Error("[QuestionableIPC] Message: " + ex.Message);
log.Error("[QuestionableIPC] Stack Trace: " + ex.StackTrace);
IsAvailable = false;
return false;
}
}
public bool TryEnsureAvailableSilent()
{
if (IsAvailable)
{
return true;
}
if (!subscribersInitialized)
{
return false;
}
lastAvailabilityCheck = DateTime.MinValue;
try
{
if (isRunningSubscriber == null)
{
return false;
}
isRunningSubscriber.InvokeFunc();
if (!IsAvailable)
{
IsAvailable = true;
}
return true;
}
catch
{
IsAvailable = false;
return false;
}
}
public string? GetCurrentQuestId()
{
TryEnsureAvailable();
if (!IsAvailable || getCurrentQuestIdSubscriber == null)
{
return null;
}
try
{
return getCurrentQuestIdSubscriber.InvokeFunc();
}
catch (Exception ex)
{
log.Debug("[QuestionableIPC] GetCurrentQuestId failed: " + ex.Message);
return null;
}
}
public StepData? GetCurrentStepData()
{
TryEnsureAvailable();
if (!IsAvailable || getCurrentStepDataSubscriber == null)
{
return null;
}
try
{
return getCurrentStepDataSubscriber.InvokeFunc();
}
catch (Exception ex)
{
log.Debug("[QuestionableIPC] GetCurrentStepData failed: " + ex.Message);
return null;
}
}
public byte? GetCurrentSequence()
{
TryEnsureAvailable();
if (!IsAvailable || getCurrentStepDataSubscriber == null)
{
return null;
}
try
{
return getCurrentStepDataSubscriber.InvokeFunc()?.Sequence;
}
catch (Exception ex)
{
log.Debug("[QuestionableIPC] GetCurrentSequence failed: " + ex.Message);
return null;
}
}
public bool IsRunning()
{
TryEnsureAvailable();
if (isRunningSubscriber == null)
{
return false;
}
try
{
bool result = isRunningSubscriber.InvokeFunc();
if (!IsAvailable)
{
IsAvailable = true;
log.Information("[QuestionableIPC] Questionable is now available");
}
return result;
}
catch (Exception ex)
{
if (IsAvailable)
{
IsAvailable = false;
log.Warning("[QuestionableIPC] Questionable is no longer available: " + ex.Message);
}
log.Debug("[QuestionableIPC] IsRunning failed: " + ex.Message);
return false;
}
}
public object? GetCurrentTask()
{
TryEnsureAvailable();
if (getCurrentTaskSubscriber == null)
{
return null;
}
try
{
object? result = getCurrentTaskSubscriber.InvokeFunc();
if (!IsAvailable)
{
IsAvailable = true;
log.Information("[QuestionableIPC] Questionable is now available");
}
return result;
}
catch (Exception ex)
{
if (IsAvailable)
{
IsAvailable = false;
log.Warning("[QuestionableIPC] Questionable is no longer available: " + ex.Message);
}
log.Debug("[QuestionableIPC] GetCurrentTask failed: " + ex.Message);
return null;
}
}
public bool Start()
{
log.Warning("[QuestionableIPC] Start() called - NOT AVAILABLE VIA IPC!");
log.Warning("[QuestionableIPC] Use /qst start command instead");
return false;
}
public bool Stop()
{
log.Warning("[QuestionableIPC] Stop() called - NOT AVAILABLE VIA IPC!");
log.Warning("[QuestionableIPC] Use /qst stop command instead");
return false;
}
public bool ImportQuestPriority(string base64QuestData)
{
TryEnsureAvailable();
if (!IsAvailable || importQuestPrioritySubscriber == null)
{
return false;
}
try
{
bool result = importQuestPrioritySubscriber.InvokeFunc(base64QuestData);
log.Information($"[QuestionableIPC] Imported priority quest: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] ImportQuestPriority failed: " + ex.Message);
return false;
}
}
public bool AddQuestPriority(string questId)
{
TryEnsureAvailable();
if (!IsAvailable || addQuestPrioritySubscriber == null)
{
return false;
}
try
{
bool result = addQuestPrioritySubscriber.InvokeFunc(questId);
log.Debug($"[QuestionableIPC] Added quest {questId} to priority: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] AddQuestPriority failed: " + ex.Message);
return false;
}
}
public bool ClearQuestPriority()
{
TryEnsureAvailable();
if (!IsAvailable || clearQuestPrioritySubscriber == null)
{
return false;
}
try
{
bool result = clearQuestPrioritySubscriber.InvokeFunc();
log.Debug($"[QuestionableIPC] Cleared quest priority: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] ClearQuestPriority failed: " + ex.Message);
return false;
}
}
public bool IsQuestComplete(string questId)
{
TryEnsureAvailable();
if (!IsAvailable || isQuestCompleteSubscriber == null)
{
return false;
}
try
{
bool result = isQuestCompleteSubscriber.InvokeFunc(questId);
log.Debug($"[QuestionableIPC] Quest {questId} complete: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] IsQuestComplete failed: " + ex.Message);
return false;
}
}
public bool IsReadyToAcceptQuest(string questId)
{
TryEnsureAvailable();
if (!IsAvailable || isReadyToAcceptQuestSubscriber == null)
{
return false;
}
try
{
bool result = isReadyToAcceptQuestSubscriber.InvokeFunc(questId);
log.Debug($"[QuestionableIPC] Quest {questId} ready to accept: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] IsReadyToAcceptQuest failed: " + ex.Message);
return false;
}
}
public bool AddQuestsToQueue(List<string> questIds)
{
TryEnsureAvailable();
if (!IsAvailable)
{
log.Warning("[QuestionableIPC] Cannot add quests to queue - Questionable not available");
return false;
}
if (questIds == null || questIds.Count == 0)
{
return true;
}
try
{
log.Information($"[QuestionableIPC] Adding {questIds.Count} quests to priority queue");
foreach (string questId in questIds)
{
if (!string.IsNullOrEmpty(questId))
{
try
{
bool? result = addQuestPrioritySubscriber?.InvokeFunc(questId);
log.Debug($"[QuestionableIPC] Added quest {questId} to queue: {result}");
}
catch (Exception ex)
{
log.Warning("[QuestionableIPC] Failed to add quest " + questId + " to queue: " + ex.Message);
}
}
}
log.Information("[QuestionableIPC] All quests added to priority queue");
return true;
}
catch (Exception ex2)
{
log.Error("[QuestionableIPC] Error adding quests to queue: " + ex2.Message);
return false;
}
}
public List<string> GetCurrentlyActiveEventQuests()
{
TryEnsureAvailable();
if (!IsAvailable || getCurrentlyActiveEventQuestsSubscriber == null)
{
log.Warning("[QuestionableIPC] Cannot get active event quests - Questionable not available");
return new List<string>();
}
try
{
List<string> eventQuests = getCurrentlyActiveEventQuestsSubscriber.InvokeFunc();
log.Debug($"[QuestionableIPC] Retrieved {eventQuests?.Count ?? 0} active event quests");
return eventQuests ?? new List<string>();
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] Error getting active event quests: " + ex.Message);
return new List<string>();
}
}
public int GetAlliedSocietyRemainingAllowances()
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyRemainingAllowancesSubscriber == null)
{
log.Debug("[AlliedSociety] Cannot get remaining allowances - Questionable not available");
return 12;
}
try
{
int result = getAlliedSocietyRemainingAllowancesSubscriber.InvokeFunc();
log.Debug($"[AlliedSociety] Remaining allowances: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[AlliedSociety] Error getting remaining allowances: " + ex.Message);
return 12;
}
}
public List<string> GetAlliedSocietyAvailableQuestIds(byte societyId)
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyAvailableQuestIdsSubscriber == null)
{
log.Debug($"[AlliedSociety] Cannot get quest IDs for society {societyId} - Questionable not available");
return new List<string>();
}
try
{
List<string> result = getAlliedSocietyAvailableQuestIdsSubscriber.InvokeFunc(societyId);
log.Debug($"[AlliedSociety] Society {societyId} has {result?.Count ?? 0} available quests");
return result ?? new List<string>();
}
catch (Exception ex)
{
log.Error($"[AlliedSociety] Error getting quest IDs for society {societyId}: {ex.Message}");
return new List<string>();
}
}
public Dictionary<byte, int> GetAlliedSocietyAllAvailableQuestCounts()
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyAllAvailableQuestCountsSubscriber == null)
{
log.Debug("[AlliedSociety] Cannot get quest counts - Questionable not available");
return new Dictionary<byte, int>();
}
try
{
Dictionary<byte, int> result = getAlliedSocietyAllAvailableQuestCountsSubscriber.InvokeFunc();
log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} societies with available quests");
return result ?? new Dictionary<byte, int>();
}
catch (Exception ex)
{
log.Error("[AlliedSociety] Error getting quest counts: " + ex.Message);
return new Dictionary<byte, int>();
}
}
public bool GetAlliedSocietyIsMaxRank(byte societyId)
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyIsMaxRankSubscriber == null)
{
log.Debug($"[AlliedSociety] Cannot check max rank for society {societyId} - Questionable not available");
return false;
}
try
{
bool result = getAlliedSocietyIsMaxRankSubscriber.InvokeFunc(societyId);
log.Debug($"[AlliedSociety] Society {societyId} max rank: {result}");
return result;
}
catch (Exception ex)
{
log.Error($"[AlliedSociety] Error checking max rank for society {societyId}: {ex.Message}");
return false;
}
}
public int GetAlliedSocietyCurrentRank(byte societyId)
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyCurrentRankSubscriber == null)
{
log.Debug($"[AlliedSociety] Cannot get rank for society {societyId} - Questionable not available");
return -1;
}
try
{
int result = getAlliedSocietyCurrentRankSubscriber.InvokeFunc(societyId);
log.Debug($"[AlliedSociety] Society {societyId} current rank: {result}");
return result;
}
catch (Exception ex)
{
log.Error($"[AlliedSociety] Error getting rank for society {societyId}: {ex.Message}");
return -1;
}
}
public List<byte> GetAlliedSocietiesWithAvailableQuests()
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietiesWithAvailableQuestsSubscriber == null)
{
log.Debug("[AlliedSociety] Cannot get societies with quests - Questionable not available");
return new List<byte>();
}
try
{
List<byte> result = getAlliedSocietiesWithAvailableQuestsSubscriber.InvokeFunc();
log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} societies with available quests");
return result ?? new List<byte>();
}
catch (Exception ex)
{
log.Error("[AlliedSociety] Error getting societies with quests: " + ex.Message);
return new List<byte>();
}
}
public int AddAlliedSocietyOptimalQuests(byte societyId)
{
TryEnsureAvailable();
if (!IsAvailable || addAlliedSocietyOptimalQuestsSubscriber == null)
{
log.Debug($"[AlliedSociety] Cannot add optimal quests for society {societyId} - Questionable not available");
return 0;
}
try
{
int result = addAlliedSocietyOptimalQuestsSubscriber.InvokeFunc(societyId);
log.Information($"[AlliedSociety] Added {result} optimal quests for society {societyId}");
return result;
}
catch (Exception ex)
{
log.Error($"[AlliedSociety] Error adding optimal quests for society {societyId}: {ex.Message}");
return 0;
}
}
public List<string> GetAlliedSocietyOptimalQuests(byte societyId)
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyOptimalQuestsSubscriber == null)
{
log.Debug($"[AlliedSociety] Cannot get optimal quests for society {societyId} - Questionable not available");
return new List<string>();
}
try
{
List<string> result = getAlliedSocietyOptimalQuestsSubscriber.InvokeFunc(societyId);
log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} optimal quests for society {societyId}");
return result ?? new List<string>();
}
catch (Exception ex)
{
log.Error($"[AlliedSociety] Error getting optimal quests for society {societyId}: {ex.Message}");
return new List<string>();
}
}
public TimeSpan GetAlliedSocietyTimeUntilReset()
{
TryEnsureAvailable();
if (!IsAvailable || getAlliedSocietyTimeUntilResetSubscriber == null)
{
log.Debug("[AlliedSociety] Cannot get time until reset - Questionable not available");
return TimeSpan.Zero;
}
try
{
TimeSpan timeSpan = TimeSpan.FromTicks(getAlliedSocietyTimeUntilResetSubscriber.InvokeFunc());
log.Debug($"[AlliedSociety] Time until reset: {timeSpan}");
return timeSpan;
}
catch (Exception ex)
{
log.Error("[AlliedSociety] Error getting time until reset: " + ex.Message);
return TimeSpan.Zero;
}
}
public bool GetStopConditionsEnabled()
{
TryEnsureAvailable();
if (!IsAvailable || getStopConditionsEnabledSubscriber == null)
{
log.Debug("[StopCondition] Cannot get stop conditions enabled - Questionable not available");
return false;
}
try
{
bool result = getStopConditionsEnabledSubscriber.InvokeFunc();
log.Debug($"[StopCondition] Stop conditions enabled: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting stop conditions enabled: " + ex.Message);
return false;
}
}
public List<string> GetStopQuestList()
{
TryEnsureAvailable();
if (!IsAvailable || getStopQuestListSubscriber == null)
{
return new List<string>();
}
try
{
List<string> result = getStopQuestListSubscriber.InvokeFunc();
log.Debug($"[StopCondition] Found {result?.Count ?? 0} stop quests");
return result ?? new List<string>();
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting stop quest list: " + ex.Message);
return new List<string>();
}
}
public StopConditionData? GetLevelStopCondition()
{
TryEnsureAvailable();
if (!IsAvailable || getLevelStopConditionSubscriber == null)
{
log.Debug("[StopCondition] Cannot get level stop condition - Questionable not available");
return null;
}
try
{
return getLevelStopConditionSubscriber.InvokeFunc();
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting level stop condition: " + ex.Message);
return null;
}
}
public StopConditionData? GetSequenceStopCondition()
{
TryEnsureAvailable();
if (!IsAvailable || getSequenceStopConditionSubscriber == null)
{
log.Debug("[StopCondition] Cannot get sequence stop condition - Questionable not available");
return null;
}
try
{
StopConditionData result = getSequenceStopConditionSubscriber.InvokeFunc();
log.Debug($"[StopCondition] Sequence stop condition - Enabled: {result?.Enabled}, Target: {result?.TargetValue}");
return result;
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting sequence stop condition: " + ex.Message);
return null;
}
}
public object? GetQuestSequenceStopCondition(string questId, uint sequence, int step)
{
TryEnsureAvailable();
if (!IsAvailable || getQuestSequenceStopConditionSubscriber == null)
{
log.Warning("[StopCondition] Cannot get quest sequence stop condition - Questionable not available");
return null;
}
try
{
object result = getQuestSequenceStopConditionSubscriber.InvokeFunc(questId, sequence, step);
if (result == null)
{
log.Information($"[StopCondition] No quest sequence stop condition found for {questId} at {sequence}-{step}");
}
else
{
log.Information($"[StopCondition] Quest sequence stop condition for {questId} at {sequence}-{step}: {result}");
}
return result;
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting quest sequence stop condition: " + ex.Message);
return null;
}
}
public bool RemoveQuestSequenceStopCondition(string questId)
{
TryEnsureAvailable();
if (!IsAvailable || removeQuestSequenceStopConditionSubscriber == null)
{
log.Warning("[StopCondition] Cannot remove quest sequence stop condition - Questionable not available");
return false;
}
try
{
bool num = removeQuestSequenceStopConditionSubscriber.InvokeFunc(questId);
if (num)
{
log.Information("[StopCondition] ✓ Removed quest sequence stop condition for " + questId);
}
else
{
log.Warning("[StopCondition] ✗ No quest sequence stop condition to remove for " + questId + " (or removal failed)");
}
return num;
}
catch (Exception ex)
{
log.Error("[StopCondition] Error removing quest sequence stop condition: " + ex.Message);
return false;
}
}
public Dictionary<string, object> GetAllQuestSequenceStopConditions()
{
TryEnsureAvailable();
if (!IsAvailable || getAllQuestSequenceStopConditionsSubscriber == null)
{
return new Dictionary<string, object>();
}
try
{
Dictionary<string, object> result = getAllQuestSequenceStopConditionsSubscriber.InvokeFunc();
if (result == null || result.Count == 0)
{
log.Information("[StopCondition] No quest sequence stop conditions configured (empty or null result)");
return new Dictionary<string, object>();
}
log.Information($"[StopCondition] Found {result.Count} quest sequence stop condition(s)");
return result;
}
catch (Exception ex)
{
log.Error("[StopCondition] Error getting all quest sequence stop conditions: " + ex.Message);
return new Dictionary<string, object>();
}
}
public int GetDefaultDutyMode()
{
TryEnsureAvailable();
if (!IsAvailable || getDefaultDutyModeSubscriber == null)
{
log.Debug("[QuestionableIPC] Cannot get default duty mode - Questionable not available");
return 0;
}
try
{
int result = getDefaultDutyModeSubscriber.InvokeFunc();
log.Debug($"[QuestionableIPC] Default Duty Mode: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] GetDefaultDutyMode failed: " + ex.Message);
return 0;
}
}
public bool SetDefaultDutyMode(int dutyMode)
{
TryEnsureAvailable();
if (!IsAvailable || setDefaultDutyModeSubscriber == null)
{
log.Debug("[QuestionableIPC] Cannot set default duty mode - Questionable not available");
return false;
}
try
{
bool result = setDefaultDutyModeSubscriber.InvokeFunc(dutyMode);
log.Information($"[QuestionableIPC] Set Default Duty Mode to {dutyMode}: {result}");
return result;
}
catch (Exception ex)
{
log.Error("[QuestionableIPC] SetDefaultDutyMode failed: " + ex.Message);
return false;
}
}
public bool ValidateFeatureCompatibility()
{
if (!IsAvailable)
{
return false;
}
try
{
if (getAllQuestSequenceStopConditionsSubscriber == null)
{
return false;
}
if (getLevelStopConditionSubscriber == null)
{
return false;
}
if (getAlliedSocietyOptimalQuestsSubscriber == null)
{
return false;
}
if (getDefaultDutyModeSubscriber == null)
{
return false;
}
try
{
getAllQuestSequenceStopConditionsSubscriber.InvokeFunc();
}
catch
{
return false;
}
return true;
}
catch
{
return false;
}
}
public void Dispose()
{
IsAvailable = false;
}
}