From e12ec0ceff8d37dbba5cca06f0455eb5babc8fb2 Mon Sep 17 00:00:00 2001 From: MidoriKami <9083275+MidoriKami@users.noreply.github.com> Date: Sat, 21 Oct 2023 18:06:02 -0700 Subject: [PATCH] Add FrameworkPluginScoped (#1442) Co-authored-by: KazWolfe --- Dalamud/Game/Framework.cs | 102 ++++++++++++++++++++++---- Dalamud/Plugin/Services/IFramework.cs | 5 +- 2 files changed, 88 insertions(+), 19 deletions(-) diff --git a/Dalamud/Game/Framework.cs b/Dalamud/Game/Framework.cs index 22343fd8e..a13f0e209 100644 --- a/Dalamud/Game/Framework.cs +++ b/Dalamud/Game/Framework.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -12,23 +11,21 @@ using Dalamud.Game.Gui.Toast; using Dalamud.Hooking; using Dalamud.IoC; using Dalamud.IoC.Internal; +using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using Dalamud.Utility; -using Serilog; namespace Dalamud.Game; /// /// This class represents the Framework of the native game client and grants access to various subsystems. /// -[PluginInterface] [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] -#pragma warning disable SA1015 -[ResolveVia] -#pragma warning restore SA1015 internal sealed class Framework : IDisposable, IServiceType, IFramework { + private static readonly ModuleLog Log = new("Framework"); + private static readonly Stopwatch StatsStopwatch = new(); private readonly GameLifecycle lifecycle; @@ -70,19 +67,11 @@ internal sealed class Framework : IDisposable, IServiceType, IFramework /// A value indicating if the call was successful. public delegate bool OnRealDestroyDelegate(IntPtr framework); - /// - /// A delegate type used during the native Framework::free. - /// - /// The native Framework address. - public delegate IntPtr OnDestroyDelegate(); - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate bool OnUpdateDetour(IntPtr framework); - private delegate IntPtr OnDestroyDetour(); // OnDestroyDelegate - /// - public event IFramework.OnUpdateDelegate Update; + public event IFramework.OnUpdateDelegate? Update; /// /// Gets or sets a value indicating whether the collection of stats is enabled. @@ -523,3 +512,86 @@ internal sealed class Framework : IDisposable, IServiceType, IFramework } } } + +/// +/// Plugin-scoped version of a Framework service. +/// +[PluginInterface] +[InterfaceVersion("1.0")] +[ServiceManager.ScopedService] +#pragma warning disable SA1015 +[ResolveVia] +#pragma warning restore SA1015 +internal class FrameworkPluginScoped : IDisposable, IServiceType, IFramework +{ + [ServiceManager.ServiceDependency] + private readonly Framework frameworkService = Service.Get(); + + /// + /// Initializes a new instance of the class. + /// + internal FrameworkPluginScoped() + { + this.frameworkService.Update += this.OnUpdateForward; + } + + /// + public event IFramework.OnUpdateDelegate? Update; + + /// + public DateTime LastUpdate => this.frameworkService.LastUpdate; + + /// + public DateTime LastUpdateUTC => this.frameworkService.LastUpdateUTC; + + /// + public TimeSpan UpdateDelta => this.frameworkService.UpdateDelta; + + /// + public bool IsInFrameworkUpdateThread => this.frameworkService.IsInFrameworkUpdateThread; + + /// + public bool IsFrameworkUnloading => this.frameworkService.IsFrameworkUnloading; + + /// + public void Dispose() + { + this.frameworkService.Update -= this.OnUpdateForward; + + this.Update = null; + } + + /// + public Task RunOnFrameworkThread(Func func) + => this.frameworkService.RunOnFrameworkThread(func); + + /// + public Task RunOnFrameworkThread(Action action) + => this.frameworkService.RunOnFrameworkThread(action); + + /// + public Task RunOnFrameworkThread(Func> func) + => this.frameworkService.RunOnFrameworkThread(func); + + /// + public Task RunOnFrameworkThread(Func func) + => this.frameworkService.RunOnFrameworkThread(func); + + /// + public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) + => this.frameworkService.RunOnTick(func, delay, delayTicks, cancellationToken); + + /// + public Task RunOnTick(Action action, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) + => this.frameworkService.RunOnTick(action, delay, delayTicks, cancellationToken); + + /// + public Task RunOnTick(Func> func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) + => this.frameworkService.RunOnTick(func, delay, delayTicks, cancellationToken); + + /// + public Task RunOnTick(Func func, TimeSpan delay = default, int delayTicks = default, CancellationToken cancellationToken = default) + => this.frameworkService.RunOnTick(func, delay, delayTicks, cancellationToken); + + private void OnUpdateForward(IFramework framework) => this.Update?.Invoke(framework); +} diff --git a/Dalamud/Plugin/Services/IFramework.cs b/Dalamud/Plugin/Services/IFramework.cs index 334577b92..ca33c5867 100644 --- a/Dalamud/Plugin/Services/IFramework.cs +++ b/Dalamud/Plugin/Services/IFramework.cs @@ -1,9 +1,6 @@ -using System; -using System.Threading; +using System.Threading; using System.Threading.Tasks; -using Dalamud.Game; - namespace Dalamud.Plugin.Services; ///