From bd5f8cde6af8e5fb8bfd3e3a399130200e7dc95c Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Tue, 30 Mar 2021 22:37:17 +0200 Subject: [PATCH] refactor: adjust Dalamud.cs to new code style --- Dalamud/Dalamud.cs | 475 +++++++++++++++++++++++++-------------------- 1 file changed, 263 insertions(+), 212 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index c97a2bae4..bae06a2f9 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -1,18 +1,10 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; -using System.Net; -using System.Numerics; -using System.Runtime.InteropServices; -using System.Text; using System.Threading; -using System.Threading.Tasks; -using CheapLoc; + using Dalamud.Data; using Dalamud.Game; -using Dalamud.Game.Chat; using Dalamud.Game.Chat.SeStringHandling; using Dalamud.Game.ClientState; using Dalamud.Game.Command; @@ -20,125 +12,16 @@ using Dalamud.Game.Internal; using Dalamud.Game.Network; using Dalamud.Interface; using Dalamud.Plugin; -using ImGuiNET; using Serilog; using Serilog.Core; -using Serilog.Events; - -namespace Dalamud { - public sealed class Dalamud : IDisposable { - - #region Native Game Subsystems - - /// - /// Game framework subsystem - /// - internal Framework Framework { get; private set; } - - /// - /// Anti-Debug detection prevention system - /// - internal AntiDebug AntiDebug { get; private set; } - - /// - /// WinSock optimization subsystem - /// - internal WinSockHandlers WinSock2 { get; private set; } - - /// - /// ImGui Interface subsystem - /// - internal InterfaceManager InterfaceManager { get; private set; } - - /// - /// ClientState subsystem - /// - public ClientState ClientState { get; private set; } - - #endregion - - #region Dalamud Subsystems - - /// - /// Plugin Manager subsystem - /// - internal PluginManager PluginManager { get; private set; } - - /// - /// Plugin Repository subsystem - /// - internal PluginRepository PluginRepository { get; private set; } - - /// - /// Data provider subsystem - /// - internal DataManager Data { get; private set; } - - /// - /// Command Manager subsystem - /// - internal CommandManager CommandManager { get; private set; } - - /// - /// Localization subsystem facilitating localization for Dalamud and plugins - /// - internal Localization LocalizationManager { get; private set; } - - #endregion - - #region Helpers - - /// - /// SeStringManager subsystem facilitating string parsing - /// - internal SeStringManager SeStringManager { get; private set; } - - /// - /// Copy-enabled SigScanner for target module - /// - internal SigScanner SigScanner { get; private set; } - - /// - /// LoggingLevelSwitch for Dalamud and Plugin logs - /// - internal LoggingLevelSwitch LogLevelSwitch { get; private set; } - - /// - /// StartInfo object passed from injector - /// - internal DalamudStartInfo StartInfo { get; private set; } - - /// - /// Configuration object facilitating save and load of Dalamud configuration - /// - internal DalamudConfiguration Configuration { get; private set; } - - #endregion - - #region Dalamud Core functionality - - /// - /// Dalamud base UI - /// - internal DalamudInterface DalamudUi { get; private set; } - - /// - /// Dalamud chat commands - /// - internal DalamudCommands DalamudCommands { get; private set; } - - /// - /// Dalamud chat-based features - /// - internal ChatHandlers ChatHandlers { get; private set; } - - /// - /// Dalamud network-based features - /// - internal NetworkHandlers NetworkHandlers { get; private set; } - - #endregion +namespace Dalamud +{ + /// + /// The main Dalamud class containing all subsystems. + /// + public sealed class Dalamud : IDisposable + { #region Internals private readonly ManualResetEvent unloadSignal; @@ -150,25 +33,15 @@ namespace Dalamud { #endregion /// - /// Injected process module + /// Initializes a new instance of the class. /// - internal ProcessModule TargetModule { get; private set; } - - /// - /// Value indicating if Dalamud was successfully loaded - /// - internal bool IsReady { get; private set; } - - /// - /// Location of stored assets - /// - internal DirectoryInfo AssetDirectory => new DirectoryInfo(this.StartInfo.AssetDirectory); - - internal Fools2021 Fools { get; private set; } - - public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal) { - StartInfo = info; - LogLevelSwitch = loggingLevelSwitch; + /// DalamudStartInfo instance. + /// LoggingLevelSwitch to control Serilog level. + /// Signal signalling shutdown. + public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal) + { + this.StartInfo = info; + this.LogLevelSwitch = loggingLevelSwitch; this.baseDirectory = info.WorkingDirectory; @@ -179,17 +52,153 @@ namespace Dalamud { this.unloadSignal.Reset(); } - public void Start() { - try { - Configuration = DalamudConfiguration.Load(StartInfo.ConfigurationPath); + #region Native Game Subsystems + + /// + /// Gets game framework subsystem. + /// + internal Framework Framework { get; private set; } + + /// + /// Gets Anti-Debug detection prevention subsystem. + /// + internal AntiDebug AntiDebug { get; private set; } + + /// + /// Gets WinSock optimization subsystem. + /// + internal WinSockHandlers WinSock2 { get; private set; } + + /// + /// Gets ImGui Interface subsystem. + /// + internal InterfaceManager InterfaceManager { get; private set; } + + /// + /// Gets ClientState subsystem. + /// + internal ClientState ClientState { get; private set; } + + #endregion + + #region Dalamud Subsystems + + /// + /// Gets Plugin Manager subsystem. + /// + internal PluginManager PluginManager { get; private set; } + + /// + /// Gets Plugin Repository subsystem. + /// + internal PluginRepository PluginRepository { get; private set; } + + /// + /// Gets Data provider subsystem. + /// + internal DataManager Data { get; private set; } + + /// + /// Gets Command Manager subsystem. + /// + internal CommandManager CommandManager { get; private set; } + + /// + /// Gets Localization subsystem facilitating localization for Dalamud and plugins. + /// + internal Localization LocalizationManager { get; private set; } + + #endregion + + #region Helpers + + /// + /// Gets SeStringManager subsystem facilitating string parsing. + /// + internal SeStringManager SeStringManager { get; private set; } + + /// + /// Gets copy-enabled SigScanner for target module. + /// + internal SigScanner SigScanner { get; private set; } + + /// + /// Gets LoggingLevelSwitch for Dalamud and Plugin logs. + /// + internal LoggingLevelSwitch LogLevelSwitch { get; private set; } + + /// + /// Gets StartInfo object passed from injector. + /// + internal DalamudStartInfo StartInfo { get; private set; } + + /// + /// Gets Configuration object facilitating save and load of Dalamud configuration. + /// + internal DalamudConfiguration Configuration { get; private set; } + + #endregion + + #region Dalamud Core functionality + + /// + /// Gets Dalamud base UI. + /// + internal DalamudInterface DalamudUi { get; private set; } + + /// + /// Gets Dalamud chat commands. + /// + internal DalamudCommands DalamudCommands { get; private set; } + + /// + /// Gets Dalamud chat-based features. + /// + internal ChatHandlers ChatHandlers { get; private set; } + + /// + /// Gets Dalamud network-based features. + /// + internal NetworkHandlers NetworkHandlers { get; private set; } + + #endregion + + /// + /// Gets Injected process module. + /// + internal ProcessModule TargetModule { get; private set; } + + /// + /// Gets a value indicating whether Dalamud was successfully loaded. + /// + internal bool IsReady { get; private set; } + + /// + /// Gets location of stored assets. + /// + internal DirectoryInfo AssetDirectory => new DirectoryInfo(this.StartInfo.AssetDirectory); + + /// + /// Gets April Fools system. + /// + internal Fools2021 Fools { get; private set; } + + /// + /// Start and initialize Dalamud subsystems. + /// + public void Start() + { + try + { + this.Configuration = DalamudConfiguration.Load(this.StartInfo.ConfigurationPath); // Initialize the process information. - TargetModule = Process.GetCurrentProcess().MainModule; - SigScanner = new SigScanner(TargetModule, true); + this.TargetModule = Process.GetCurrentProcess().MainModule; + this.SigScanner = new SigScanner(this.TargetModule, true); Log.Verbose("[START] Scanner OK!"); - AntiDebug = new AntiDebug(SigScanner); + this.AntiDebug = new AntiDebug(this.SigScanner); #if DEBUG AntiDebug.Enable(); #endif @@ -197,175 +206,217 @@ namespace Dalamud { Log.Verbose("[START] AntiDebug OK!"); // Initialize game subsystem - Framework = new Framework(SigScanner, this); + this.Framework = new Framework(this.SigScanner, this); Log.Verbose("[START] Framework OK!"); - WinSock2 = new WinSockHandlers(); + this.WinSock2 = new WinSockHandlers(); Log.Verbose("[START] WinSock OK!"); - NetworkHandlers = new NetworkHandlers(this, StartInfo.OptOutMbCollection); + this.NetworkHandlers = new NetworkHandlers(this, this.StartInfo.OptOutMbCollection); Log.Verbose("[START] NH OK!"); - ClientState = new ClientState(this, StartInfo, SigScanner); + this.ClientState = new ClientState(this, this.StartInfo, this.SigScanner); Log.Verbose("[START] CS OK!"); - LocalizationManager = new Localization(AssetDirectory.FullName); - if (!string.IsNullOrEmpty(Configuration.LanguageOverride)) - LocalizationManager.SetupWithLangCode(Configuration.LanguageOverride); + this.LocalizationManager = new Localization(this.AssetDirectory.FullName); + if (!string.IsNullOrEmpty(this.Configuration.LanguageOverride)) + this.LocalizationManager.SetupWithLangCode(this.Configuration.LanguageOverride); else - LocalizationManager.SetupWithUiCulture(); + this.LocalizationManager.SetupWithUiCulture(); Log.Verbose("[START] LOC OK!"); - PluginRepository = new PluginRepository(this, StartInfo.PluginDirectory, StartInfo.GameVersion); + this.PluginRepository = + new PluginRepository(this, this.StartInfo.PluginDirectory, this.StartInfo.GameVersion); Log.Verbose("[START] PREPO OK!"); - DalamudUi = new DalamudInterface(this); + this.DalamudUi = new DalamudInterface(this); Log.Verbose("[START] DUI OK!"); var isInterfaceLoaded = false; - if (!bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_INTERFACE") ?? "false")) { - try { - InterfaceManager = new InterfaceManager(this, SigScanner); - InterfaceManager.OnDraw += DalamudUi.Draw; + if (!bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_INTERFACE") ?? "false")) + { + try + { + this.InterfaceManager = new InterfaceManager(this, this.SigScanner); + this.InterfaceManager.OnDraw += this.DalamudUi.Draw; - InterfaceManager.Enable(); + this.InterfaceManager.Enable(); isInterfaceLoaded = true; Log.Verbose("[START] IM OK!"); - InterfaceManager.WaitForFontRebuild(); - } catch (Exception e) { + this.InterfaceManager.WaitForFontRebuild(); + } + catch (Exception e) + { Log.Information(e, "Could not init interface."); } } var time = DateTime.Now; - if (time.Day == 1 && time.Month == 4 && time.Year == 2021 || true) + if (time.Day == 1 && time.Month == 4 && time.Year == 2021) { - Fools = new Fools2021(this); - InterfaceManager.OnDraw += Fools.Draw; + this.Fools = new Fools2021(this); + this.InterfaceManager.OnDraw += this.Fools.Draw; } - Data = new DataManager(StartInfo.Language); - try { - Data.Initialize(AssetDirectory.FullName); - } catch (Exception e) { + this.Data = new DataManager(this.StartInfo.Language); + try + { + this.Data.Initialize(this.AssetDirectory.FullName); + } + catch (Exception e) + { Log.Error(e, "Could not initialize DataManager."); - Unload(); + this.Unload(); return; } Log.Verbose("[START] Data OK!"); - SeStringManager = new SeStringManager(Data); + this.SeStringManager = new SeStringManager(this.Data); Log.Verbose("[START] SeString OK!"); // Initialize managers. Basically handlers for the logic - CommandManager = new CommandManager(this, StartInfo.Language); - DalamudCommands = new DalamudCommands(this); - DalamudCommands.SetupCommands(); + this.CommandManager = new CommandManager(this, this.StartInfo.Language); + this.DalamudCommands = new DalamudCommands(this); + this.DalamudCommands.SetupCommands(); Log.Verbose("[START] CM OK!"); - ChatHandlers = new ChatHandlers(this); + this.ChatHandlers = new ChatHandlers(this); Log.Verbose("[START] CH OK!"); - if (!bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS") ?? "false")) { - try { - PluginRepository.CleanupPlugins(); + if (!bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS") ?? "false")) + { + try + { + this.PluginRepository.CleanupPlugins(); Log.Verbose("[START] PRC OK!"); - PluginManager = - new PluginManager(this, StartInfo.PluginDirectory, StartInfo.DefaultPluginDirectory); - PluginManager.LoadPlugins(); + this.PluginManager = new PluginManager( + this, + this.StartInfo.PluginDirectory, + this.StartInfo.DefaultPluginDirectory); + this.PluginManager.LoadPlugins(); Log.Verbose("[START] PM OK!"); - } catch (Exception ex) { + } + catch (Exception ex) + { Log.Error(ex, "Plugin load failed."); } } - Framework.Enable(); + this.Framework.Enable(); Log.Verbose("[START] Framework ENABLE!"); - ClientState.Enable(); + this.ClientState.Enable(); Log.Verbose("[START] CS ENABLE!"); - IsReady = true; + this.IsReady = true; Troubleshooting.LogTroubleshooting(this, isInterfaceLoaded); Log.Information("Dalamud is ready."); - } catch (Exception ex) { + } + catch (Exception ex) + { Log.Error(ex, "Dalamud::Start() failed."); - Unload(); + this.Unload(); } } - public void Unload() { + /// + /// Queue an unload of Dalamud when it gets the chance. + /// + public void Unload() + { Log.Information("Trigger unload"); this.unloadSignal.Set(); } - public void WaitForUnload() { + /// + /// Wait for an unload request to start. + /// + public void WaitForUnload() + { this.unloadSignal.WaitOne(); } - public void WaitForUnloadFinish() { + /// + /// Wait for a queued unload to be finalized. + /// + public void WaitForUnloadFinish() + { this.finishUnloadSignal.WaitOne(); } - public void Dispose() { - try { - Fools?.Dispose(); + /// + /// Dispose Dalamud subsystems. + /// + public void Dispose() + { + try + { + this.Fools?.Dispose(); // this must be done before unloading plugins, or it can cause a race condition // due to rendering happening on another thread, where a plugin might receive // a render call after it has been disposed, which can crash if it attempts to // use any resources that it freed in its own Dispose method - InterfaceManager?.Dispose(); + this.InterfaceManager?.Dispose(); - try { - PluginManager.UnloadPlugins(); - } catch (Exception ex) { + try + { + this.PluginManager.UnloadPlugins(); + } + catch (Exception ex) + { Log.Error(ex, "Plugin unload failed."); } - Framework.Dispose(); - ClientState.Dispose(); + this.Framework.Dispose(); + this.ClientState.Dispose(); this.unloadSignal.Dispose(); - WinSock2.Dispose(); + this.WinSock2.Dispose(); - SigScanner.Dispose(); + this.SigScanner.Dispose(); - Data.Dispose(); + this.Data.Dispose(); - AntiDebug.Dispose(); + this.AntiDebug.Dispose(); Log.Debug("Dalamud::Dispose() OK!"); - } catch (Exception ex) { + } + catch (Exception ex) + { Log.Error(ex, "Dalamud::Dispose() failed."); } } - internal void ReplaceExceptionHandler() { - var semd = this.SigScanner.ScanText( + /// + /// Replace the built-in exception handler with a debug one. + /// + internal void ReplaceExceptionHandler() + { + var releaseFilter = this.SigScanner.ScanText( "40 55 53 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ??"); - Log.Debug($"SE debug filter at {semd.ToInt64():X}"); + Log.Debug($"SE debug filter at {releaseFilter.ToInt64():X}"); - var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(semd); + var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter); Log.Debug("Reset ExceptionFilter, old: {0}", oldFilter); } }