diff --git a/MareSynchronos/Interop/Ipc/IpcProvider.cs b/MareSynchronos/Interop/Ipc/IpcProvider.cs index 7c520f7..b6e32ad 100644 --- a/MareSynchronos/Interop/Ipc/IpcProvider.cs +++ b/MareSynchronos/Interop/Ipc/IpcProvider.cs @@ -1,6 +1,7 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; +using MareSynchronos.MareConfiguration; using MareSynchronos.PlayerData.Export; using MareSynchronos.PlayerData.Handlers; using MareSynchronos.Services; @@ -14,6 +15,7 @@ public class IpcProvider : IHostedService, IMediatorSubscriber { private readonly ILogger _logger; private readonly IDalamudPluginInterface _pi; + private readonly MareConfigService _mareConfig; private readonly MareCharaFileManager _mareCharaFileManager; private readonly DalamudUtilService _dalamudUtil; private ICallGateProvider? _loadFileProvider; @@ -21,14 +23,25 @@ public class IpcProvider : IHostedService, IMediatorSubscriber private ICallGateProvider>? _handledGameAddresses; private readonly List _activeGameObjectHandlers = []; + private ICallGateProvider? _loadFileProviderMare; + private ICallGateProvider>? _loadFileAsyncProviderMare; + private ICallGateProvider>? _handledGameAddressesMare; + + private bool _marePluginEnabled = false; + private bool _impersonating = false; + + public bool MarePluginEnabled => _marePluginEnabled; + public bool ImpersonationActive => _impersonating; + public MareMediator Mediator { get; init; } - public IpcProvider(ILogger logger, IDalamudPluginInterface pi, + public IpcProvider(ILogger logger, IDalamudPluginInterface pi, MareConfigService mareConfig, MareCharaFileManager mareCharaFileManager, DalamudUtilService dalamudUtil, MareMediator mareMediator) { _logger = logger; _pi = pi; + _mareConfig = mareConfig; _mareCharaFileManager = mareCharaFileManager; _dalamudUtil = dalamudUtil; Mediator = mareMediator; @@ -43,6 +56,13 @@ public class IpcProvider : IHostedService, IMediatorSubscriber if (msg.OwnedObject) return; _activeGameObjectHandlers.Remove(msg.GameObjectHandler); }); + + _marePluginEnabled = pi.InstalledPlugins.Any(p => p.InternalName == "MareSynchronos" && p.IsLoaded); + Mediator.Subscribe(this, p => { + if (p.InternalName == "MareSynchronos") + _marePluginEnabled = p.IsLoaded; + HandleMareImpersonation(); + }); } public Task StartAsync(CancellationToken cancellationToken) @@ -54,16 +74,63 @@ public class IpcProvider : IHostedService, IMediatorSubscriber _loadFileAsyncProvider.RegisterFunc(LoadMcdfAsync); _handledGameAddresses = _pi.GetIpcProvider>("LoporritSync.GetHandledAddresses"); _handledGameAddresses.RegisterFunc(GetHandledAddresses); + + _loadFileProviderMare = _pi.GetIpcProvider("MareSynchronos.LoadMcdf"); + _loadFileAsyncProviderMare = _pi.GetIpcProvider>("MareSynchronos.LoadMcdfAsync"); + _handledGameAddressesMare = _pi.GetIpcProvider>("MareSynchronos.GetHandledAddresses"); + HandleMareImpersonation(); + _logger.LogInformation("Started IpcProviderService"); return Task.CompletedTask; } + public void HandleMareImpersonation() + { + if (_marePluginEnabled) + { + if (_impersonating) + { + // Do not attempt to unregister the functions at this point, otherwise we risk unregistering Mare's + // This may leave the APIs hanging if Mare did not initialize to the point of registering its API though + _impersonating = false; + _logger.LogDebug("Releasing MareSynchronos API"); + } + } + else + { + if (_mareConfig.Current.MareAPI) + { + _loadFileProviderMare?.RegisterFunc(LoadMcdf); + _loadFileAsyncProviderMare?.RegisterFunc(LoadMcdfAsync); + _handledGameAddressesMare?.RegisterFunc(GetHandledAddresses); + _impersonating = true; + _logger.LogDebug("Registered MareSynchronos API"); + } + else + { + _loadFileProviderMare?.UnregisterFunc(); + _loadFileAsyncProviderMare?.UnregisterFunc(); + _handledGameAddressesMare?.UnregisterFunc(); + _impersonating = false; + _logger.LogDebug("Unregistered MareSynchronos API"); + } + } + } + public Task StopAsync(CancellationToken cancellationToken) { _logger.LogDebug("Stopping IpcProvider Service"); _loadFileProvider?.UnregisterFunc(); _loadFileAsyncProvider?.UnregisterFunc(); _handledGameAddresses?.UnregisterFunc(); + + if (_impersonating) + { + _loadFileProviderMare?.UnregisterFunc(); + _loadFileAsyncProviderMare?.UnregisterFunc(); + _handledGameAddressesMare?.UnregisterFunc(); + } + Mediator.UnsubscribeAll(this); return Task.CompletedTask; } diff --git a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs index 9a22602..74eb5db 100644 --- a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs +++ b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs @@ -69,4 +69,6 @@ public class MareConfig : IMareConfiguration public int ChatLogKind { get; set; } = 1; // XivChatType.Debug public bool ExtraChatAPI { get; set; } = false; public bool ExtraChatTags { get; set; } = false; + + public bool MareAPI { get; set; } = true; } \ No newline at end of file diff --git a/MareSynchronos/UI/SettingsUi.cs b/MareSynchronos/UI/SettingsUi.cs index d307834..0911ab1 100644 --- a/MareSynchronos/UI/SettingsUi.cs +++ b/MareSynchronos/UI/SettingsUi.cs @@ -38,6 +38,7 @@ public class SettingsUi : WindowMediatorSubscriberBase { private readonly ApiController _apiController; private readonly IpcManager _ipcManager; + private readonly IpcProvider _ipcProvider; private readonly CacheMonitor _cacheMonitor; private readonly DalamudUtilService _dalamudUtilService; private readonly MareConfigService _configService; @@ -84,7 +85,7 @@ public class SettingsUi : WindowMediatorSubscriberBase FileTransferOrchestrator fileTransferOrchestrator, FileCacheManager fileCacheManager, FileCompactor fileCompactor, ApiController apiController, - IpcManager ipcManager, CacheMonitor cacheMonitor, + IpcManager ipcManager, IpcProvider ipcProvider, CacheMonitor cacheMonitor, DalamudUtilService dalamudUtilService) : base(logger, mediator, "Loporrit Settings", performanceCollector) { _configService = configService; @@ -101,6 +102,7 @@ public class SettingsUi : WindowMediatorSubscriberBase _fileCacheManager = fileCacheManager; _apiController = apiController; _ipcManager = ipcManager; + _ipcProvider = ipcProvider; _cacheMonitor = cacheMonitor; _dalamudUtilService = dalamudUtilService; _fileCompactor = fileCompactor; @@ -616,10 +618,50 @@ public class SettingsUi : WindowMediatorSubscriberBase } } - private void DrawDebug() + private void DrawAdvanced() { - _lastTab = "Debug"; + _lastTab = "Advanced"; + _uiShared.BigText("Advanced"); + + bool mareApi = _configService.Current.MareAPI; + if (ImGui.Checkbox("Enable Mare Synchronos API", ref mareApi)) + { + _configService.Current.MareAPI = mareApi; + _configService.Save(); + _ipcProvider.HandleMareImpersonation(); + } + _uiShared.DrawHelpText("Enables handling of the Mare Synchronos API. This currently includes:\n\n" + + " - MCDF loading support for other plugins\n" + + " - Blocking Moodles applications to paired users\n\n" + + "If the Mare Synchronos plugin is loaded while this option is enabled, control of its API will be relinquished."); + + using (_ = ImRaii.PushIndent()) + { + ImGui.SameLine(300.0f); + if (_ipcProvider.ImpersonationActive) + { + UiSharedService.ColorTextWrapped("Mare API active!", ImGuiColors.HealerGreen); + } + else + { + if (!mareApi) + UiSharedService.ColorTextWrapped("Mare API inactive: Option is disabled", ImGuiColors.DalamudYellow); + else if (_ipcProvider.MarePluginEnabled) + UiSharedService.ColorTextWrapped("Mare API inactive: Mare plugin is loaded", ImGuiColors.DalamudYellow); + else + UiSharedService.ColorTextWrapped("Mare API inactive: Unknown reason", ImGuiColors.DalamudRed); + } + } + + bool logEvents = _configService.Current.LogEvents; + if (ImGui.Checkbox("Log Event Viewer Data", ref logEvents)) + { + _configService.Current.LogEvents = logEvents; + _configService.Save(); + } + + ImGui.Separator(); _uiShared.BigText("Debug"); #if DEBUG if (LastCreatedCharacterData != null && ImGui.TreeNode("Last created character data")) @@ -672,22 +714,17 @@ public class SettingsUi : WindowMediatorSubscriberBase } } - bool logEvents = _configService.Current.LogEvents; - if (ImGui.Checkbox("Log Event Viewer Data", ref logEvents)) + if (ImGui.TreeNode("Active Character Blocks")) { - _configService.Current.LogEvents = logEvents; - _configService.Save(); - } - - ImGui.Separator(); - _uiShared.BigText("Active Character Blocks"); - foreach (var pair in _pairManager.GetOnlineUserPairs()) - { - if (pair.IsApplicationBlocked) + var onlinePairs = _pairManager.GetOnlineUserPairs(); + foreach (var pair in onlinePairs) { - ImGui.TextUnformatted(pair.PlayerName); - ImGui.SameLine(); - ImGui.TextUnformatted(string.Join(", ", pair.HoldApplicationReasons)); + if (pair.IsApplicationBlocked) + { + ImGui.TextUnformatted(pair.PlayerName); + ImGui.SameLine(); + ImGui.TextUnformatted(string.Join(", ", pair.HoldApplicationReasons)); + } } } } @@ -1932,9 +1969,9 @@ public class SettingsUi : WindowMediatorSubscriberBase ImGui.EndTabItem(); } - if (ImGui.BeginTabItem("Debug")) + if (ImGui.BeginTabItem("Advanced")) { - DrawDebug(); + DrawAdvanced(); ImGui.EndTabItem(); }