qstbak/Questionable/Questionable.External/AutoDutyIpc.cs
2026-08-19 13:19:57 +10:00

286 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps;
using Questionable.Data;
using Questionable.Model.Questing;
namespace Questionable.External;
internal sealed class AutoDutyIpc
{
public enum DutyMode
{
Support = 1,
UnsyncRegular
}
private readonly IDalamudPluginInterface _pluginInterface;
private readonly Configuration _configuration;
private readonly TerritoryData _territoryData;
private readonly ILogger<AutoDutyIpc> _logger;
private readonly ICallGateSubscriber<uint, bool> _contentHasPath;
private readonly ICallGateSubscriber<string, string> _getConfig;
private readonly ICallGateSubscriber<string, string, object> _setConfig;
private readonly ICallGateSubscriber<uint, int, bool, object> _run;
private readonly ICallGateSubscriber<bool, object> _start;
private readonly ICallGateSubscriber<bool> _isStopped;
private readonly ICallGateSubscriber<object> _stop;
private bool _loggedContentHasPathQueryWarning;
private bool _loggedLevelingModeWarning;
public const int MinimumLevelForLevelingMode = 15;
public AutoDutyIpc(IDalamudPluginInterface pluginInterface, Configuration configuration, TerritoryData territoryData, ILogger<AutoDutyIpc> logger)
{
_pluginInterface = pluginInterface;
_configuration = configuration;
_territoryData = territoryData;
_logger = logger;
_contentHasPath = pluginInterface.GetIpcSubscriber<uint, bool>("AutoDuty.ContentHasPath");
_getConfig = pluginInterface.GetIpcSubscriber<string, string>("AutoDuty.GetConfig");
_setConfig = pluginInterface.GetIpcSubscriber<string, string, object>("AutoDuty.SetConfig");
_run = pluginInterface.GetIpcSubscriber<uint, int, bool, object>("AutoDuty.Run");
_start = pluginInterface.GetIpcSubscriber<bool, object>("AutoDuty.Start");
_isStopped = pluginInterface.GetIpcSubscriber<bool>("AutoDuty.IsStopped");
_stop = pluginInterface.GetIpcSubscriber<object>("AutoDuty.Stop");
_loggedContentHasPathQueryWarning = false;
_loggedLevelingModeWarning = false;
}
public bool ManagesRotationPluginState()
{
try
{
return string.Equals(_getConfig.InvokeFunc("AutoManageRotationPluginState"), "True", StringComparison.OrdinalIgnoreCase);
}
catch (IpcError)
{
return false;
}
}
public bool ManagesBossModAiSettings()
{
try
{
return string.Equals(_getConfig.InvokeFunc("AutoManageBossModAISettings"), "True", StringComparison.OrdinalIgnoreCase);
}
catch (IpcError)
{
return false;
}
}
public bool IsConfiguredToRunContent(DutyOptions? dutyOptions)
{
if (dutyOptions == null || dutyOptions.ContentFinderConditionId == 0)
{
return false;
}
if (!_configuration.Duties.RunInstancedContentWithAutoDuty)
{
return false;
}
uint contentFinderConditionId = dutyOptions.ContentFinderConditionId;
if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(contentFinderConditionId))
{
return false;
}
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(contentFinderConditionId) && _territoryData.TryGetContentFinderCondition(contentFinderConditionId, out TerritoryData.ContentFinderConditionData _))
{
return true;
}
if (DutyRegistry.Duties.TryGetValue(contentFinderConditionId, out DutyEntry value) && value.Enabled)
{
return HasPath(contentFinderConditionId);
}
return false;
}
public bool IsConfiguredToRunLevelingMode()
{
return _configuration.Duties.RunLevelingModeWhenUnderleveled;
}
public bool IsConfiguredToRunLevelingMode(int currentPlayerLevel)
{
if (!_configuration.Duties.RunLevelingModeWhenUnderleveled)
{
return false;
}
if (currentPlayerLevel < 15)
{
_logger.LogDebug("Leveling mode is enabled but player level {CurrentLevel} is below minimum required level {MinLevel}", currentPlayerLevel, 15);
return false;
}
return true;
}
public bool HasPath(uint cfcId)
{
if (!_territoryData.TryGetContentFinderCondition(cfcId, out TerritoryData.ContentFinderConditionData contentFinderConditionData))
{
return false;
}
try
{
return _contentHasPath.InvokeFunc(contentFinderConditionData.TerritoryId);
}
catch (IpcError ipcError)
{
if (!_loggedContentHasPathQueryWarning)
{
_logger.LogWarning("Unable to query AutoDuty for path in territory {TerritoryType}: {Message}", contentFinderConditionData.TerritoryId, ipcError.Message);
_loggedContentHasPathQueryWarning = true;
}
return false;
}
}
public void StartInstance(uint cfcId, DutyMode dutyMode)
{
if (!_territoryData.TryGetContentFinderCondition(cfcId, out TerritoryData.ContentFinderConditionData contentFinderConditionData))
{
throw new TaskException($"Unknown ContentFinderConditionId {cfcId}");
}
try
{
_logger.LogDebug("Disabling AutoDuty leveling mode before starting specific duty {CfcId}", cfcId);
_setConfig.InvokeAction("leveling", "None");
_setConfig.InvokeAction("Unsynced", $"{dutyMode == DutyMode.UnsyncRegular}");
ICallGateSubscriber<string, string, object> setConfig = _setConfig;
setConfig.InvokeAction("dutyModeEnum", dutyMode switch
{
DutyMode.Support => "Support",
DutyMode.UnsyncRegular => "Regular",
_ => throw new ArgumentOutOfRangeException("dutyMode", dutyMode, null),
});
_run.InvokeAction(contentFinderConditionData.TerritoryId, 1, !_configuration.Advanced.DisableAutoDutyBareMode);
}
catch (IpcError ipcError)
{
throw new TaskException("Unable to run content with AutoDuty: " + ipcError.Message, ipcError);
}
}
public bool StartLevelingMode()
{
try
{
if (!IsStopped())
{
_logger.LogDebug("AutoDuty is already running, not starting leveling mode again");
return true;
}
_logger.LogDebug("Starting AutoDuty Leveling mode (Support) - AutoDuty will select the best dungeon");
_setConfig.InvokeAction("leveling", "Support");
_setConfig.InvokeAction("AutoDutyModeEnum", "Looping");
_start.InvokeAction(arg1: true);
return true;
}
catch (IpcError ipcError)
{
if (!_loggedLevelingModeWarning)
{
_logger.LogWarning("Unable to start AutoDuty Leveling mode: {Message}", ipcError.Message);
_loggedLevelingModeWarning = true;
}
return false;
}
catch (Exception exception)
{
if (!_loggedLevelingModeWarning)
{
_logger.LogWarning(exception, "Unable to start AutoDuty Leveling mode");
_loggedLevelingModeWarning = true;
}
return false;
}
}
public string DescribeInstallation()
{
List<string> list = (from p in _pluginInterface.InstalledPlugins
where p.InternalName.Contains("AutoDuty", StringComparison.OrdinalIgnoreCase) || p.Name.Contains("AutoDuty", StringComparison.OrdinalIgnoreCase)
select $"{p.InternalName} {p.Version} from '{p.Manifest.InstalledFromUrl}' (loaded: {p.IsLoaded}, dev: {p.IsDev})").ToList();
string value = ((list.Count > 0) ? string.Join("; ", list) : "no AutoDuty plugin installed");
string value2 = "IPC Run: " + (_run.HasAction ? "registered" : "missing") + ", IsStopped: " + (_isStopped.HasFunction ? "registered" : "missing");
string value3 = $"GetConfig probe: {ProbeConfig("Questionable.Probe")}, dutyModeEnum: {ProbeConfig("dutyModeEnum")}, LoopTimes: {ProbeConfig("LoopTimes")}, IsStopped: {ProbeIsStopped()}";
return $"{value}; {value2}; {value3}";
}
private string ProbeConfig(string key)
{
try
{
return "'" + _getConfig.InvokeFunc(key) + "'";
}
catch (IpcError ipcError)
{
return $"<{ipcError.GetType().Name}: {ipcError.Message}>";
}
}
private string ProbeIsStopped()
{
try
{
return _isStopped.InvokeFunc().ToString();
}
catch (IpcError ipcError)
{
return $"<{ipcError.GetType().Name}: {ipcError.Message}>";
}
}
public bool IsStopped()
{
try
{
return _isStopped.InvokeFunc();
}
catch (IpcError)
{
return true;
}
}
public bool Stop()
{
try
{
_logger.LogDebug("Calling AutoDuty.Stop");
try
{
_setConfig.InvokeAction("leveling", "None");
}
catch (IpcError)
{
}
_stop.InvokeAction();
return true;
}
catch (IpcError ipcError2)
{
_logger.LogWarning("Unable to stop AutoDuty: {Message}", ipcError2.Message);
return false;
}
}
}