using System; 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 Configuration _configuration; private readonly TerritoryData _territoryData; private readonly ILogger _logger; private readonly ICallGateSubscriber _contentHasPath; private readonly ICallGateSubscriber _getConfig; private readonly ICallGateSubscriber _setConfig; private readonly ICallGateSubscriber _run; private readonly ICallGateSubscriber _start; private readonly ICallGateSubscriber _isStopped; private readonly ICallGateSubscriber _stop; private bool _loggedContentHasPathQueryWarning; private bool _loggedLevelingModeWarning; public const int MinimumLevelForLevelingMode = 15; public AutoDutyIpc(IDalamudPluginInterface pluginInterface, Configuration configuration, TerritoryData territoryData, ILogger logger) { _configuration = configuration; _territoryData = territoryData; _logger = logger; _contentHasPath = pluginInterface.GetIpcSubscriber("AutoDuty.ContentHasPath"); _getConfig = pluginInterface.GetIpcSubscriber("AutoDuty.GetConfig"); _setConfig = pluginInterface.GetIpcSubscriber("AutoDuty.SetConfig"); _run = pluginInterface.GetIpcSubscriber("AutoDuty.Run"); _start = pluginInterface.GetIpcSubscriber("AutoDuty.Start"); _isStopped = pluginInterface.GetIpcSubscriber("AutoDuty.IsStopped"); _stop = pluginInterface.GetIpcSubscriber("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 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 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; } } }