1
0
Fork 0
forked from aly/qstbak
qstbak/Questionable/Questionable.External/TextAdvanceIpc.cs
2026-08-17 20:29:32 +10:00

189 lines
5.9 KiB
C#

using System;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller;
namespace Questionable.External;
internal sealed class TextAdvanceIpc : IDisposable
{
public sealed class ExternalTerritoryConfig
{
public bool? EnableQuestAccept;
public bool? EnableQuestComplete;
public bool? EnableRewardPick;
public bool? EnableRequestHandin;
public bool? EnableCutsceneEsc;
public bool? EnableCutsceneSkipConfirm;
public bool? EnableTalkSkip;
public bool? EnableRequestFill;
public bool? EnableAutoInteract;
}
private bool _isExternalControlActivated;
private long _ipcRetryAfter;
private bool _lastCinemaModeState;
private bool _lastInCutsceneState;
private bool _lastSuppressRequestState;
private readonly QuestController _questController;
private readonly FateController _fateController;
private readonly SeasonalDutyController _seasonalDutyController;
private readonly AttunementController _attunementController;
private readonly CustomDeliveryController _customDeliveryController;
private readonly Configuration _configuration;
private readonly ICondition _condition;
private readonly IFramework _framework;
private readonly ICallGateSubscriber<bool> _isInExternalControl;
private readonly ICallGateSubscriber<string, ExternalTerritoryConfig, bool> _enableExternalControl;
private readonly ICallGateSubscriber<string, bool> _disableExternalControl;
private readonly string _pluginName;
private readonly ILogger<TextAdvanceIpc> _logger;
public TextAdvanceIpc(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, FateController fateController, SeasonalDutyController seasonalDutyController, AttunementController attunementController, CustomDeliveryController customDeliveryController, Configuration configuration, ICondition condition, ILogger<TextAdvanceIpc> logger)
{
_framework = framework;
_questController = questController;
_fateController = fateController;
_seasonalDutyController = seasonalDutyController;
_attunementController = attunementController;
_customDeliveryController = customDeliveryController;
_configuration = configuration;
_condition = condition;
_logger = logger;
_isInExternalControl = pluginInterface.GetIpcSubscriber<bool>("TextAdvance.IsInExternalControl");
_enableExternalControl = pluginInterface.GetIpcSubscriber<string, ExternalTerritoryConfig, bool>("TextAdvance.EnableExternalControl");
_disableExternalControl = pluginInterface.GetIpcSubscriber<string, bool>("TextAdvance.DisableExternalControl");
_pluginName = pluginInterface.InternalName;
_framework.Update += OnUpdate;
}
public void Dispose()
{
_framework.Update -= OnUpdate;
if (_isExternalControlActivated)
{
try
{
_disableExternalControl.InvokeFunc(_pluginName);
}
catch (IpcError exception)
{
_logger.LogDebug(exception, "Failed to disable TextAdvance external control during dispose");
}
}
}
private void OnUpdate(IFramework framework)
{
if (Environment.TickCount64 < _ipcRetryAfter)
{
return;
}
try
{
OnUpdateInner();
}
catch (IpcError exception)
{
_logger.LogDebug(exception, "TextAdvance IPC call failed");
_ipcRetryAfter = Environment.TickCount64 + 30000;
}
}
private void OnUpdateInner()
{
bool flag = _questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual || _fateController.IsRunning || _seasonalDutyController.IsRunning || _attunementController.IsRunning || _customDeliveryController.IsRunning;
if (!_configuration.General.ConfigureTextAdvance || !flag)
{
if (!_isExternalControlActivated)
{
return;
}
try
{
if (_disableExternalControl.InvokeFunc(_pluginName) || !_isInExternalControl.InvokeFunc())
{
_isExternalControlActivated = false;
}
return;
}
catch (IpcError)
{
_isExternalControlActivated = false;
return;
}
}
bool cinemaMode = _configuration.General.CinemaMode;
bool flag2 = _condition[ConditionFlag.OccupiedInCutSceneEvent] || _condition[ConditionFlag.WatchingCutscene] || _condition[ConditionFlag.WatchingCutscene78];
bool flag3 = _customDeliveryController.IsRunning && !_questController.IsRunning && _questController.AutomationType == QuestController.EAutomationType.Manual && !_fateController.IsRunning && !_seasonalDutyController.IsRunning && !_attunementController.IsRunning;
bool flag4 = cinemaMode != _lastCinemaModeState || (cinemaMode && flag2 != _lastInCutsceneState) || flag3 != _lastSuppressRequestState;
if (!_isExternalControlActivated)
{
if (!_isInExternalControl.InvokeFunc())
{
ExternalTerritoryConfig arg = CreateExternalTerritoryConfig(cinemaMode, flag2, flag3);
if (_enableExternalControl.InvokeFunc(_pluginName, arg))
{
_isExternalControlActivated = true;
_lastCinemaModeState = cinemaMode;
_lastInCutsceneState = flag2;
_lastSuppressRequestState = flag3;
}
}
}
else if (flag4)
{
ExternalTerritoryConfig arg2 = CreateExternalTerritoryConfig(cinemaMode, flag2, flag3);
_enableExternalControl.InvokeFunc(_pluginName, arg2);
_lastCinemaModeState = cinemaMode;
_lastInCutsceneState = flag2;
_lastSuppressRequestState = flag3;
}
}
private static ExternalTerritoryConfig CreateExternalTerritoryConfig(bool cinemaMode, bool inCutscene, bool suppressRequestHandling)
{
bool flag = cinemaMode && inCutscene;
return new ExternalTerritoryConfig
{
EnableQuestAccept = true,
EnableQuestComplete = true,
EnableRewardPick = true,
EnableRequestHandin = !suppressRequestHandling,
EnableCutsceneEsc = !cinemaMode,
EnableCutsceneSkipConfirm = !cinemaMode,
EnableTalkSkip = !flag,
EnableRequestFill = !suppressRequestHandling,
EnableAutoInteract = false
};
}
}