From 5cd4b49fee0c76af5456daee2e3c8906d8b69c59 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Tue, 27 Dec 2022 18:09:59 +0100 Subject: [PATCH] Add a toggle to advanced settings that uses reflection to change the Synchronous Load option in Dalamud. --- Penumbra/Dalamud.cs | 118 ++++++++++++++++++ Penumbra/Penumbra.cs | 1 + .../UI/ConfigWindow.SettingsTab.Advanced.cs | 15 +++ 3 files changed, 134 insertions(+) diff --git a/Penumbra/Dalamud.cs b/Penumbra/Dalamud.cs index ab2b924a..d872e629 100644 --- a/Penumbra/Dalamud.cs +++ b/Penumbra/Dalamud.cs @@ -1,3 +1,4 @@ +using System; using Dalamud.Data; using Dalamud.Game; using Dalamud.Game.ClientState; @@ -9,6 +10,8 @@ using Dalamud.Game.Gui; using Dalamud.Interface; using Dalamud.IoC; using Dalamud.Plugin; +using System.Linq; +using System.Reflection; // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local @@ -33,4 +36,119 @@ public class Dalamud [PluginService][RequiredVersion("1.0")] public static GameGui GameGui { get; private set; } = null!; [PluginService][RequiredVersion("1.0")] public static KeyState KeyState { get; private set; } = null!; // @formatter:on + + private static readonly object? DalamudConfig; + private static readonly object? SettingsWindow; + private static readonly MethodInfo? SaveDalamudConfig; + public const string WaitingForPluginsOption = "IsResumeGameAfterPluginLoad"; + + static Dalamud() + { + try + { + var serviceType = typeof( DalamudPluginInterface ).Assembly.DefinedTypes.FirstOrDefault( t => t.Name == "Service`1" && t.IsGenericType ); + var configType = typeof( DalamudPluginInterface ).Assembly.DefinedTypes.FirstOrDefault( t => t.Name == "DalamudConfiguration" ); + var interfaceType = typeof( DalamudPluginInterface ).Assembly.DefinedTypes.FirstOrDefault( t => t.Name == "DalamudInterface" ); + if( serviceType == null || configType == null || interfaceType == null ) + { + return; + } + + var configService = serviceType.MakeGenericType( configType ); + var interfaceService = serviceType.MakeGenericType( interfaceType ); + var configGetter = configService.GetMethod( "Get", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic ); + var interfaceGetter = interfaceService.GetMethod( "Get", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic ); + if( configGetter == null || interfaceGetter == null ) + { + return; + } + + DalamudConfig = configGetter.Invoke( null, null ); + if( DalamudConfig != null ) + { + SaveDalamudConfig = DalamudConfig.GetType().GetMethod( "Save", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + if( SaveDalamudConfig == null ) + { + DalamudConfig = null; + } + + var inter = interfaceGetter.Invoke( null, null ); + SettingsWindow = inter?.GetType().GetField( "settingsWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic )?.GetValue( inter ); + if( SettingsWindow == null ) + { + DalamudConfig = null; + SaveDalamudConfig = null; + } + } + } + catch + { + DalamudConfig = null; + SaveDalamudConfig = null; + SettingsWindow = null; + } + } + + public static bool GetDalamudConfig< T >( string fieldName, out T? value ) + { + value = default; + try + { + if( DalamudConfig == null ) + { + return false; + } + + var getter = DalamudConfig.GetType().GetProperty( fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + if( getter == null ) + { + return false; + } + + var result = getter.GetValue( DalamudConfig ); + if( result is not T v ) + { + return false; + } + + value = v; + return true; + } + catch( Exception e ) + { + Penumbra.Log.Error( $"Error while fetching Dalamud Config {fieldName}:\n{e}" ); + return false; + } + } + + public static bool SetDalamudConfig< T >( string fieldName, in T? value, string? windowFieldName = null ) + { + try + { + if( DalamudConfig == null ) + { + return false; + } + + var getter = DalamudConfig.GetType().GetProperty( fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + if( getter == null ) + { + return false; + } + + getter.SetValue( DalamudConfig, value ); + if( windowFieldName != null ) + { + SettingsWindow!.GetType().GetField( windowFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic )?.SetValue( SettingsWindow, value ); + } + + SaveDalamudConfig!.Invoke( DalamudConfig, null ); + return true; + } + catch( Exception e ) + { + Penumbra.Log.Error( $"Error while fetching Dalamud Config {fieldName}:\n{e}" ); + return false; + } + } } \ No newline at end of file diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index 25ad785c..32538a81 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -330,6 +330,7 @@ public class Penumbra : IDalamudPlugin sb.Append( $"> **`Free Drive Space: `** {( drive != null ? Functions.HumanReadableSize( drive.AvailableFreeSpace ) : "Unknown" )}\n" ); sb.Append( $"> **`Auto-Deduplication: `** {Config.AutoDeduplicateOnImport}\n" ); sb.Append( $"> **`Debug Mode: `** {Config.DebugMode}\n" ); + sb.Append( $"> **`Synchronous Load (Dalamud): `** {(Dalamud.GetDalamudConfig( Dalamud.WaitingForPluginsOption, out bool v ) ? v.ToString() : "Unknown")}\n" ); sb.Append( $"> **`Logging: `** Full: {Config.EnableFullResourceLogging}, Resource: {Config.EnableResourceLogging}\n" ); sb.Append( $"> **`Use Ownership: `** {Config.UseOwnerNameForCharacterCollection}\n" ); sb.AppendLine( "**Mods**" ); diff --git a/Penumbra/UI/ConfigWindow.SettingsTab.Advanced.cs b/Penumbra/UI/ConfigWindow.SettingsTab.Advanced.cs index d0ed97a7..b4bd7dc8 100644 --- a/Penumbra/UI/ConfigWindow.SettingsTab.Advanced.cs +++ b/Penumbra/UI/ConfigWindow.SettingsTab.Advanced.cs @@ -30,6 +30,7 @@ public partial class ConfigWindow "Normally, metadata changes that equal their default values, which are sometimes exported by TexTools, are discarded. " + "Toggle this to keep them, for example if an option in a mod is supposed to disable a metadata change from a prior option.", Penumbra.Config.KeepDefaultMetaChanges, v => Penumbra.Config.KeepDefaultMetaChanges = v ); + DrawWaitForPluginsReflection(); DrawRequestedResourceLogging(); DrawEnableHttpApiBox(); DrawEnableDebugModeBox(); @@ -158,5 +159,19 @@ public partial class ConfigWindow FontReloader.Reload(); } } + + private static void DrawWaitForPluginsReflection() + { + if( !Dalamud.GetDalamudConfig( Dalamud.WaitingForPluginsOption, out bool value ) ) + { + using var disabled = ImRaii.Disabled(); + Checkbox( "Wait for Plugins on Startup (Disabled, can not access Dalamud Configuration)", string.Empty, false, v => { } ); + } + else + { + Checkbox( "Wait for Plugins on Startup", "This changes a setting in the Dalamud Configuration found at /xlsettings -> General.", value, + v => Dalamud.SetDalamudConfig( Dalamud.WaitingForPluginsOption, v, "doWaitForPluginsOnStartup" ) ); + } + } } } \ No newline at end of file