From 57c91eb83475886418ab8dac2839066a43fe2ba0 Mon Sep 17 00:00:00 2001 From: RisaDev <151885272+RisaDev@users.noreply.github.com> Date: Sun, 3 Mar 2024 02:42:16 +0300 Subject: [PATCH] A bit of work on new IPC --- ...zePlusIpc.cs => CustomizePlusLegacyIpc.cs} | 4 +- CustomizePlus/Api/CustomizePlusIpc.General.cs | 61 +++++++++++++++++++ CustomizePlus/Api/CustomizePlusIpc.Profile.cs | 12 ++++ CustomizePlus/Api/CustomizePlusIpc.cs | 56 +++++++++++++++++ CustomizePlus/Core/ServiceManagerBuilder.cs | 2 + CustomizePlus/Plugin.cs | 2 + .../UI/Windows/Controls/PluginStateBlock.cs | 11 +++- .../MainWindow/Tabs/Debug/IPCTestTab.cs | 8 ++- 8 files changed, 152 insertions(+), 4 deletions(-) rename CustomizePlus/Api/Compatibility/{CustomizePlusIpc.cs => CustomizePlusLegacyIpc.cs} (99%) create mode 100644 CustomizePlus/Api/CustomizePlusIpc.General.cs create mode 100644 CustomizePlus/Api/CustomizePlusIpc.Profile.cs create mode 100644 CustomizePlus/Api/CustomizePlusIpc.cs diff --git a/CustomizePlus/Api/Compatibility/CustomizePlusIpc.cs b/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs similarity index 99% rename from CustomizePlus/Api/Compatibility/CustomizePlusIpc.cs rename to CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs index eef02f9..a86cf4a 100644 --- a/CustomizePlus/Api/Compatibility/CustomizePlusIpc.cs +++ b/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs @@ -24,7 +24,7 @@ using CustomizePlus.GameData.Extensions; namespace CustomizePlus.Api.Compatibility; -public class CustomizePlusIpc : IDisposable +public class CustomizePlusLegacyIpc : IDisposable { private readonly IObjectTable _objectTable; private readonly DalamudPluginInterface _pluginInterface; @@ -52,7 +52,7 @@ public class CustomizePlusIpc : IDisposable internal ICallGateProvider? ProviderGetProfileFromCharacter; internal ICallGateProvider<(int, int)>? ProviderGetApiVersion; - public CustomizePlusIpc( + public CustomizePlusLegacyIpc( IObjectTable objectTable, DalamudPluginInterface pluginInterface, Logger logger, diff --git a/CustomizePlus/Api/CustomizePlusIpc.General.cs b/CustomizePlus/Api/CustomizePlusIpc.General.cs new file mode 100644 index 0000000..230f413 --- /dev/null +++ b/CustomizePlus/Api/CustomizePlusIpc.General.cs @@ -0,0 +1,61 @@ +using Dalamud.Plugin.Ipc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Penumbra.Api.Ipc; + +namespace CustomizePlus.Api; + +//I'm not a big fan of having functions and variables/properties +//grouped up like that but it makes sense here + +public partial class CustomizePlusIpc : IDisposable +{ + /// + /// When there are breaking changes the first number is bumped up and second one is reset. + /// When there are non-breaking changes only second number is bumped up. + /// In general clients should not try to use IPC if they encounter unexpected Breaking version. + /// + private readonly (int Breaking, int Feature) _apiVersion = (4, 0); + private const string _providerGetApiVersionLabel = $"CustomizePlus.General.{nameof(GetApiVersion)}"; + private ICallGateProvider<(int, int)>? _providerGetApiVersion; + + private (int, int) GetApiVersion() + { + return _apiVersion; + } + + /// + /// This indicates if Customize+ is in valid state and can accept IPC requests. + /// This only indicates that no fatal errors occured in Customize+. + /// This will still be true if, for example, user turns off Customize+ in its settings. + /// + private const string _providerIsValidLabel = $"CustomizePlus.General.{nameof(IsValid)}"; + private ICallGateProvider? _providerIsValid; + + private bool IsValid() + { + return !IPCFailed && + !_hookingService.RenderHookFailed && + !_hookingService.MovementHookFailed; + } + + private void InitializeGeneralProviders() + { + _logger.Debug("Initializing General Customize+ IPC providers."); + + _providerGetApiVersion = _pluginInterface.GetIpcProvider<(int, int)>(_providerGetApiVersionLabel); + _providerGetApiVersion.RegisterFunc(GetApiVersion); + + _providerIsValid = _pluginInterface.GetIpcProvider(_providerIsValidLabel); + _providerIsValid.RegisterFunc(IsValid); + } + + private void DisposeGeneralProviders() + { + _logger.Debug("Disposing General Customize+ IPC providers."); + _providerGetApiVersion?.UnregisterFunc(); + } +} diff --git a/CustomizePlus/Api/CustomizePlusIpc.Profile.cs b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs new file mode 100644 index 0000000..fa65609 --- /dev/null +++ b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CustomizePlus.Api; + +public partial class CustomizePlusIpc : IDisposable +{ + +} diff --git a/CustomizePlus/Api/CustomizePlusIpc.cs b/CustomizePlus/Api/CustomizePlusIpc.cs new file mode 100644 index 0000000..9ea050c --- /dev/null +++ b/CustomizePlus/Api/CustomizePlusIpc.cs @@ -0,0 +1,56 @@ +using CustomizePlus.Core.Services; +using Dalamud.Plugin; +using OtterGui.Log; +using System; + +namespace CustomizePlus.Api; + +public partial class CustomizePlusIpc : IDisposable +{ + private readonly DalamudPluginInterface _pluginInterface; + private readonly Logger _logger; + private readonly HookingService _hookingService; + + /// + /// Shows if IPC failed to initialize or any other unrecoverable fatal error occured. + /// + public bool IPCFailed { get; private set; } + + public CustomizePlusIpc( + DalamudPluginInterface pluginInterface, + Logger logger, + HookingService hookingService) + { + _pluginInterface = pluginInterface; + _logger = logger; + _hookingService = hookingService; + + InitializeProviders(); + } + + private void InitializeProviders() + { + try + { + InitializeGeneralProviders(); + } + catch(Exception ex) + { + _logger.Fatal($"Fatal error while initializing Customize+ IPC: {ex}"); + + IPCFailed = true; + + DisposeProviders(); + } + } + + private void DisposeProviders() + { + DisposeGeneralProviders(); + } + + public void Dispose() + { + DisposeProviders(); + } +} diff --git a/CustomizePlus/Core/ServiceManagerBuilder.cs b/CustomizePlus/Core/ServiceManagerBuilder.cs index ae8ee9b..bee548e 100644 --- a/CustomizePlus/Core/ServiceManagerBuilder.cs +++ b/CustomizePlus/Core/ServiceManagerBuilder.cs @@ -33,6 +33,7 @@ using Penumbra.GameData.Actors; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using OtterGui; +using CustomizePlus.Api; namespace CustomizePlus.Core; @@ -147,6 +148,7 @@ public static class ServiceManagerBuilder { services .AddSingleton() + .AddSingleton() .AddSingleton(); return services; diff --git a/CustomizePlus/Plugin.cs b/CustomizePlus/Plugin.cs index ef75de2..4364c6b 100644 --- a/CustomizePlus/Plugin.cs +++ b/CustomizePlus/Plugin.cs @@ -9,6 +9,7 @@ using CustomizePlus.Core; using CustomizePlus.Api.Compatibility; using CustomizePlus.Configuration.Services.Temporary; using OtterGui.Services; +using CustomizePlus.Api; namespace CustomizePlus; @@ -38,6 +39,7 @@ public sealed class Plugin : IDalamudPlugin v3ConfigFixer.FixV3ConfigIfNeeded(); _services.GetService(); + _services.GetService(); _services.GetService(); _services.GetService(); diff --git a/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs b/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs index 889bbed..0e5617b 100644 --- a/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs +++ b/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs @@ -7,6 +7,7 @@ using CustomizePlus.Game.Services; using CustomizePlus.Configuration.Data; using CustomizePlus.UI.Windows.MainWindow.Tabs.Templates; using CustomizePlus.Core.Helpers; +using CustomizePlus.Api; namespace CustomizePlus.UI.Windows.Controls; @@ -17,6 +18,7 @@ public class PluginStateBlock private readonly GameStateService _gameStateService; private readonly FantasiaPlusDetectService _fantasiaPlusDetectService; private readonly HookingService _hookingService; + private readonly CustomizePlusIpc _ipcService; private static Vector4 normalColor = new Vector4(1, 1, 1, 1); private static Vector4 warnColor = new Vector4(1, 0.5f, 0, 1); @@ -27,13 +29,15 @@ public class PluginStateBlock PluginConfiguration configuration, GameStateService gameStateService, FantasiaPlusDetectService fantasiaPlusDetectService, - HookingService hookingService) + HookingService hookingService, + CustomizePlusIpc ipcService) { _boneEditorPanel = boneEditorPanel; _configuration = configuration; _gameStateService = gameStateService; _fantasiaPlusDetectService = fantasiaPlusDetectService; _hookingService = hookingService; + _ipcService = ipcService; } public void Draw(float yPos) @@ -76,6 +80,11 @@ public class PluginStateBlock message = $"Editor is active.{(_boneEditorPanel.HasChanges ? " You have unsaved changes, finish template bone editing to open save/revert dialog." : "")}"; } } + else if (_ipcService.IPCFailed) //this is low priority error + { + severity = PluginStateSeverity.Error; + message = $"Detected failure in IPC. Integrations with other plugins will not function."; + } if (message != null) { diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs index 6d2b2a1..2d95abc 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs @@ -24,6 +24,7 @@ public class IPCTestTab //: IDisposable private readonly ActorManager _actorManager; private readonly ICallGateSubscriber<(int, int)>? _getApiVersion; + private readonly ICallGateSubscriber? _isValid; private readonly ICallGateSubscriber? _setCharacterProfile; private readonly ICallGateSubscriber? _getProfileFromCharacter; private readonly ICallGateSubscriber? _revertCharacter; @@ -51,9 +52,11 @@ public class IPCTestTab //: IDisposable _gameObjectService = gameObjectService; _actorManager = actorManager; - _getApiVersion = pluginInterface.GetIpcSubscriber<(int, int)>("CustomizePlus.GetApiVersion"); + _getApiVersion = pluginInterface.GetIpcSubscriber<(int, int)>("CustomizePlus.General.GetApiVersion"); _apiVersion = _getApiVersion.InvokeFunc(); + _isValid = pluginInterface.GetIpcSubscriber("CustomizePlus.General.IsValid"); + _setCharacterProfile = pluginInterface.GetIpcSubscriber("CustomizePlus.SetProfileToCharacter"); _getProfileFromCharacter = pluginInterface.GetIpcSubscriber("CustomizePlus.GetProfileFromCharacter"); _revertCharacter = pluginInterface.GetIpcSubscriber("CustomizePlus.RevertCharacter"); @@ -79,6 +82,9 @@ public class IPCTestTab //: IDisposable _targetCharacterName = _gameObjectService.GetCurrentPlayerName(); ImGui.Text($"Version: {_apiVersion.Item1}.{_apiVersion.Item2}"); + // + //ImGui.Text($"IsValid: {_isValid?.InvokeFunc()}"); + //ImGui.Text($"Last profile update: {_lastProfileUpdate}, Character: {_lastProfileUpdateName}"); ImGui.Text($"Memory: {(string.IsNullOrWhiteSpace(_rememberedProfileJson) ? "empty" : "has data")}");