mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Add IInternal/PublicDisposableService (#1696)
* Add IInternal/PublicDisposableService Plugins are exposed interfaces that are not inherited from `IDisposable`, but services implementing plugin interfaces often implement `IDisposable`. Some plugins may try to call `IDisposable.Dispose` on everything provided, and it also is possible to use `using` clause too eagerly while working on Dalamud itself, such as writing `using var smth = await Service<SomeService>.GetAsync();`. Such behaviors often lead to a difficult-to-debug errors, and making those services either not an `IDisposable` or making `IDisposable.Dispose` do nothing if the object has been loaded would prevent such errors. As `ServiceManager` must be the only class dealing with construction and disposal of services, `IInternalDisposableService` has been added to limit who can dispose the object. `IPublicDisposableService` also has been added to classes that can be constructed and accessed directly by plugins; for those, `Dispose` will be ignored if the instance is a service instance, and only `DisposeService` will respond. In addition, `DalamudPluginInterface` and `UiBuilder` also have been changed so that their `IDisposable.Dispose` no longer respond, and instead, internal functions have been added to only allow disposal from Dalamud. * Cleanup * Postmerge fixes * More explanation on RunOnFrameworkThread(ClearHooks) * Mark ReliableFileStorage public ctor obsolete --------- Co-authored-by: goat <16760685+goaaats@users.noreply.github.com>
This commit is contained in:
parent
dcec076ca7
commit
87b9edb448
62 changed files with 441 additions and 381 deletions
|
|
@ -97,8 +97,6 @@ namespace Dalamud.CorePlugin
|
||||||
this.Interface.UiBuilder.Draw -= this.OnDraw;
|
this.Interface.UiBuilder.Draw -= this.OnDraw;
|
||||||
|
|
||||||
this.windowSystem.RemoveAllWindows();
|
this.windowSystem.RemoveAllWindows();
|
||||||
|
|
||||||
this.Interface.ExplicitDispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Dalamud.Configuration.Internal;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[InherentDependency<ReliableFileStorage>] // We must still have this when unloading
|
[InherentDependency<ReliableFileStorage>] // We must still have this when unloading
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal sealed class DalamudConfiguration : IServiceType, IDisposable
|
internal sealed class DalamudConfiguration : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly JsonSerializerSettings SerializerSettings = new()
|
private static readonly JsonSerializerSettings SerializerSettings = new()
|
||||||
{
|
{
|
||||||
|
|
@ -502,7 +502,7 @@ internal sealed class DalamudConfiguration : IServiceType, IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
// Make sure that we save, if a save is queued while we are shutting down
|
// Make sure that we save, if a save is queued while we are shutting down
|
||||||
this.Update();
|
this.Update();
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
||||||
using Dalamud.Common;
|
using Dalamud.Common;
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Interface.Internal;
|
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Storage;
|
using Dalamud.Storage;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
@ -187,27 +186,6 @@ internal sealed class Dalamud : IServiceType
|
||||||
this.unloadSignal.WaitOne();
|
this.unloadSignal.WaitOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose subsystems related to plugin handling.
|
|
||||||
/// </summary>
|
|
||||||
public void DisposePlugins()
|
|
||||||
{
|
|
||||||
// this must be done before unloading interface manager, in order to do rebuild
|
|
||||||
// the correct cascaded WndProc (IME -> RawDX11Scene -> Game). Otherwise the game
|
|
||||||
// will not receive any windows messages
|
|
||||||
Service<DalamudIme>.GetNullable()?.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
|
|
||||||
Service<InterfaceManager>.GetNullable()?.Dispose();
|
|
||||||
|
|
||||||
Service<DalamudInterface>.GetNullable()?.Dispose();
|
|
||||||
|
|
||||||
Service<PluginManager>.GetNullable()?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replace the current exception handler with the default one.
|
/// Replace the current exception handler with the default one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Data;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IDataManager>]
|
[ResolveVia<IDataManager>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal sealed class DataManager : IDisposable, IServiceType, IDataManager
|
internal sealed class DataManager : IInternalDisposableService, IDataManager
|
||||||
{
|
{
|
||||||
private readonly Thread luminaResourceThread;
|
private readonly Thread luminaResourceThread;
|
||||||
private readonly CancellationTokenSource luminaCancellationTokenSource;
|
private readonly CancellationTokenSource luminaCancellationTokenSource;
|
||||||
|
|
@ -158,7 +158,7 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.luminaCancellationTokenSource.Cancel();
|
this.luminaCancellationTokenSource.Cancel();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,9 @@ public sealed class EntryPoint
|
||||||
SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
|
SerilogEventSink.Instance.LogLine += SerilogOnLogLine;
|
||||||
|
|
||||||
// Load configuration first to get some early persistent state, like log level
|
// Load configuration first to get some early persistent state, like log level
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
var fs = new ReliableFileStorage(Path.GetDirectoryName(info.ConfigurationPath)!);
|
var fs = new ReliableFileStorage(Path.GetDirectoryName(info.ConfigurationPath)!);
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
var configuration = DalamudConfiguration.Load(info.ConfigurationPath!, fs);
|
var configuration = DalamudConfiguration.Load(info.ConfigurationPath!, fs);
|
||||||
|
|
||||||
// Set the appropriate logging level from the configuration
|
// Set the appropriate logging level from the configuration
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Game.Addon.Events;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal unsafe class AddonEventManager : IDisposable, IServiceType
|
internal unsafe class AddonEventManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PluginName for Dalamud Internal use.
|
/// PluginName for Dalamud Internal use.
|
||||||
|
|
@ -62,7 +62,7 @@ internal unsafe class AddonEventManager : IDisposable, IServiceType
|
||||||
private delegate nint UpdateCursorDelegate(RaptureAtkModule* module);
|
private delegate nint UpdateCursorDelegate(RaptureAtkModule* module);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.onUpdateCursor.Dispose();
|
this.onUpdateCursor.Dispose();
|
||||||
|
|
||||||
|
|
@ -204,7 +204,7 @@ internal unsafe class AddonEventManager : IDisposable, IServiceType
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IAddonEventManager>]
|
[ResolveVia<IAddonEventManager>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class AddonEventManagerPluginScoped : IDisposable, IServiceType, IAddonEventManager
|
internal class AddonEventManagerPluginScoped : IInternalDisposableService, IAddonEventManager
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly AddonEventManager eventManagerService = Service<AddonEventManager>.Get();
|
private readonly AddonEventManager eventManagerService = Service<AddonEventManager>.Get();
|
||||||
|
|
@ -225,7 +225,7 @@ internal class AddonEventManagerPluginScoped : IDisposable, IServiceType, IAddon
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
// if multiple plugins force cursors and dispose without un-forcing them then all forces will be cleared.
|
// if multiple plugins force cursors and dispose without un-forcing them then all forces will be cleared.
|
||||||
if (this.isForcingCursor)
|
if (this.isForcingCursor)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Game.Addon.Lifecycle;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
internal unsafe class AddonLifecycle : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("AddonLifecycle");
|
private static readonly ModuleLog Log = new("AddonLifecycle");
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
||||||
internal List<AddonLifecycleEventListener> EventListeners { get; } = new();
|
internal List<AddonLifecycleEventListener> EventListeners { get; } = new();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.onAddonSetupHook.Dispose();
|
this.onAddonSetupHook.Dispose();
|
||||||
this.onAddonSetup2Hook.Dispose();
|
this.onAddonSetup2Hook.Dispose();
|
||||||
|
|
@ -383,7 +383,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IAddonLifecycle>]
|
[ResolveVia<IAddonLifecycle>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLifecycle
|
internal class AddonLifecyclePluginScoped : IInternalDisposableService, IAddonLifecycle
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly AddonLifecycle addonLifecycleService = Service<AddonLifecycle>.Get();
|
private readonly AddonLifecycle addonLifecycleService = Service<AddonLifecycle>.Get();
|
||||||
|
|
@ -391,7 +391,7 @@ internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLif
|
||||||
private readonly List<AddonLifecycleEventListener> eventListeners = new();
|
private readonly List<AddonLifecycleEventListener> eventListeners = new();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
foreach (var listener in this.eventListeners)
|
foreach (var listener in this.eventListeners)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Dalamud.Game.ClientState;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class ClientState : IDisposable, IServiceType, IClientState
|
internal sealed class ClientState : IInternalDisposableService, IClientState
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("ClientState");
|
private static readonly ModuleLog Log = new("ClientState");
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose of managed and unmanaged resources.
|
/// Dispose of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.setupTerritoryTypeHook.Dispose();
|
this.setupTerritoryTypeHook.Dispose();
|
||||||
this.framework.Update -= this.FrameworkOnOnUpdateEvent;
|
this.framework.Update -= this.FrameworkOnOnUpdateEvent;
|
||||||
|
|
@ -196,7 +196,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IClientState>]
|
[ResolveVia<IClientState>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ClientStatePluginScoped : IDisposable, IServiceType, IClientState
|
internal class ClientStatePluginScoped : IInternalDisposableService, IClientState
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ClientState clientStateService = Service<ClientState>.Get();
|
private readonly ClientState clientStateService = Service<ClientState>.Get();
|
||||||
|
|
@ -257,7 +257,7 @@ internal class ClientStatePluginScoped : IDisposable, IServiceType, IClientState
|
||||||
public bool IsGPosing => this.clientStateService.IsGPosing;
|
public bool IsGPosing => this.clientStateService.IsGPosing;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.clientStateService.TerritoryChanged -= this.TerritoryChangedForward;
|
this.clientStateService.TerritoryChanged -= this.TerritoryChangedForward;
|
||||||
this.clientStateService.Login -= this.LoginForward;
|
this.clientStateService.Login -= this.LoginForward;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Dalamud.Game.ClientState.Conditions;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed partial class Condition : IServiceType, ICondition
|
internal sealed partial class Condition : IInternalDisposableService, ICondition
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has.
|
/// Gets the current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has.
|
||||||
|
|
@ -22,6 +22,8 @@ internal sealed partial class Condition : IServiceType, ICondition
|
||||||
|
|
||||||
private readonly bool[] cache = new bool[MaxConditionEntries];
|
private readonly bool[] cache = new bool[MaxConditionEntries];
|
||||||
|
|
||||||
|
private bool isDisposed;
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private Condition(ClientState clientState)
|
private Condition(ClientState clientState)
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +37,9 @@ internal sealed partial class Condition : IServiceType, ICondition
|
||||||
this.framework.Update += this.FrameworkUpdate;
|
this.framework.Update += this.FrameworkUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Finalizes an instance of the <see cref="Condition" /> class.</summary>
|
||||||
|
~Condition() => this.Dispose(false);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public event ICondition.ConditionChangeDelegate? ConditionChange;
|
public event ICondition.ConditionChangeDelegate? ConditionChange;
|
||||||
|
|
||||||
|
|
@ -60,6 +65,9 @@ internal sealed partial class Condition : IServiceType, ICondition
|
||||||
public bool this[ConditionFlag flag]
|
public bool this[ConditionFlag flag]
|
||||||
=> this[(int)flag];
|
=> this[(int)flag];
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IInternalDisposableService.DisposeService() => this.Dispose(true);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool Any()
|
public bool Any()
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +97,19 @@ internal sealed partial class Condition : IServiceType, ICondition
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (this.isDisposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
this.framework.Update -= this.FrameworkUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isDisposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void FrameworkUpdate(IFramework unused)
|
private void FrameworkUpdate(IFramework unused)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < MaxConditionEntries; i++)
|
for (var i = 0; i < MaxConditionEntries; i++)
|
||||||
|
|
@ -112,44 +133,6 @@ internal sealed partial class Condition : IServiceType, ICondition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed partial class Condition : IDisposable
|
|
||||||
{
|
|
||||||
private bool isDisposed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the <see cref="Condition" /> class.
|
|
||||||
/// </summary>
|
|
||||||
~Condition()
|
|
||||||
{
|
|
||||||
this.Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes this instance, alongside its hooks.
|
|
||||||
/// </summary>
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
this.Dispose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (this.isDisposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
this.framework.Update -= this.FrameworkUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plugin-scoped version of a Condition service.
|
/// Plugin-scoped version of a Condition service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -159,7 +142,7 @@ internal sealed partial class Condition : IDisposable
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<ICondition>]
|
[ResolveVia<ICondition>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ConditionPluginScoped : IDisposable, IServiceType, ICondition
|
internal class ConditionPluginScoped : IInternalDisposableService, ICondition
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly Condition conditionService = Service<Condition>.Get();
|
private readonly Condition conditionService = Service<Condition>.Get();
|
||||||
|
|
@ -185,7 +168,7 @@ internal class ConditionPluginScoped : IDisposable, IServiceType, ICondition
|
||||||
public bool this[int flag] => this.conditionService[flag];
|
public bool this[int flag] => this.conditionService[flag];
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.conditionService.ConditionChange -= this.ConditionChangedForward;
|
this.conditionService.ConditionChange -= this.ConditionChangedForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Dalamud.Game.ClientState.GamePad;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGamepadState>]
|
[ResolveVia<IGamepadState>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal unsafe class GamepadState : IDisposable, IServiceType, IGamepadState
|
internal unsafe class GamepadState : IInternalDisposableService, IGamepadState
|
||||||
{
|
{
|
||||||
private readonly Hook<ControllerPoll>? gamepadPoll;
|
private readonly Hook<ControllerPoll>? gamepadPoll;
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ internal unsafe class GamepadState : IDisposable, IServiceType, IGamepadState
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes this instance, alongside its hooks.
|
/// Disposes this instance, alongside its hooks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.Dispose(true);
|
this.Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Game.Command;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class CommandManager : IServiceType, IDisposable, ICommandManager
|
internal sealed class CommandManager : IInternalDisposableService, ICommandManager
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("Command");
|
private static readonly ModuleLog Log = new("Command");
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.chatGui.CheckMessageHandled -= this.OnCheckMessageHandled;
|
this.chatGui.CheckMessageHandled -= this.OnCheckMessageHandled;
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +170,7 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<ICommandManager>]
|
[ResolveVia<ICommandManager>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandManager
|
internal class CommandManagerPluginScoped : IInternalDisposableService, ICommandManager
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("Command");
|
private static readonly ModuleLog Log = new("Command");
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ internal class CommandManagerPluginScoped : IDisposable, IServiceType, ICommandM
|
||||||
public ReadOnlyDictionary<string, CommandInfo> Commands => this.commandManagerService.Commands;
|
public ReadOnlyDictionary<string, CommandInfo> Commands => this.commandManagerService.Commands;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
foreach (var command in this.pluginRegisteredCommands)
|
foreach (var command in this.pluginRegisteredCommands)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Dalamud.Game.Config;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable
|
internal sealed class GameConfig : IInternalDisposableService, IGameConfig
|
||||||
{
|
{
|
||||||
private readonly TaskCompletionSource tcsInitialization = new();
|
private readonly TaskCompletionSource tcsInitialization = new();
|
||||||
private readonly TaskCompletionSource<GameConfigSection> tcsSystem = new();
|
private readonly TaskCompletionSource<GameConfigSection> tcsSystem = new();
|
||||||
|
|
@ -195,7 +195,7 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable
|
||||||
public void Set(UiControlOption option, string value) => this.UiControl.Set(option.GetName(), value);
|
public void Set(UiControlOption option, string value) => this.UiControl.Set(option.GetName(), value);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
var ode = new ObjectDisposedException(nameof(GameConfig));
|
var ode = new ObjectDisposedException(nameof(GameConfig));
|
||||||
this.tcsInitialization.SetExceptionIfIncomplete(ode);
|
this.tcsInitialization.SetExceptionIfIncomplete(ode);
|
||||||
|
|
@ -248,7 +248,7 @@ internal sealed class GameConfig : IServiceType, IGameConfig, IDisposable
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGameConfig>]
|
[ResolveVia<IGameConfig>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class GameConfigPluginScoped : IDisposable, IServiceType, IGameConfig
|
internal class GameConfigPluginScoped : IInternalDisposableService, IGameConfig
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly GameConfig gameConfigService = Service<GameConfig>.Get();
|
private readonly GameConfig gameConfigService = Service<GameConfig>.Get();
|
||||||
|
|
@ -295,7 +295,7 @@ internal class GameConfigPluginScoped : IDisposable, IServiceType, IGameConfig
|
||||||
public GameConfigSection UiControl => this.gameConfigService.UiControl;
|
public GameConfigSection UiControl => this.gameConfigService.UiControl;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.gameConfigService.Changed -= this.ConfigChangedForward;
|
this.gameConfigService.Changed -= this.ConfigChangedForward;
|
||||||
this.initializationTask.ContinueWith(
|
this.initializationTask.ContinueWith(
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Dalamud.Game.DutyState;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal unsafe class DutyState : IDisposable, IServiceType, IDutyState
|
internal unsafe class DutyState : IInternalDisposableService, IDutyState
|
||||||
{
|
{
|
||||||
private readonly DutyStateAddressResolver address;
|
private readonly DutyStateAddressResolver address;
|
||||||
private readonly Hook<SetupContentDirectNetworkMessageDelegate> contentDirectorNetworkMessageHook;
|
private readonly Hook<SetupContentDirectNetworkMessageDelegate> contentDirectorNetworkMessageHook;
|
||||||
|
|
@ -62,7 +62,7 @@ internal unsafe class DutyState : IDisposable, IServiceType, IDutyState
|
||||||
private bool CompletedThisTerritory { get; set; }
|
private bool CompletedThisTerritory { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.contentDirectorNetworkMessageHook.Dispose();
|
this.contentDirectorNetworkMessageHook.Dispose();
|
||||||
this.framework.Update -= this.FrameworkOnUpdateEvent;
|
this.framework.Update -= this.FrameworkOnUpdateEvent;
|
||||||
|
|
@ -168,7 +168,7 @@ internal unsafe class DutyState : IDisposable, IServiceType, IDutyState
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IDutyState>]
|
[ResolveVia<IDutyState>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class DutyStatePluginScoped : IDisposable, IServiceType, IDutyState
|
internal class DutyStatePluginScoped : IInternalDisposableService, IDutyState
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly DutyState dutyStateService = Service<DutyState>.Get();
|
private readonly DutyState dutyStateService = Service<DutyState>.Get();
|
||||||
|
|
@ -200,7 +200,7 @@ internal class DutyStatePluginScoped : IDisposable, IServiceType, IDutyState
|
||||||
public bool IsDutyStarted => this.dutyStateService.IsDutyStarted;
|
public bool IsDutyStarted => this.dutyStateService.IsDutyStarted;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.dutyStateService.DutyStarted -= this.DutyStartedForward;
|
this.dutyStateService.DutyStarted -= this.DutyStartedForward;
|
||||||
this.dutyStateService.DutyWiped -= this.DutyWipedForward;
|
this.dutyStateService.DutyWiped -= this.DutyWipedForward;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Dalamud.Game;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class Framework : IDisposable, IServiceType, IFramework
|
internal sealed class Framework : IInternalDisposableService, IFramework
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("Framework");
|
private static readonly ModuleLog Log = new("Framework");
|
||||||
|
|
||||||
|
|
@ -274,7 +274,7 @@ internal sealed class Framework : IDisposable, IServiceType, IFramework
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose of managed and unmanaged resources.
|
/// Dispose of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.RunOnFrameworkThread(() =>
|
this.RunOnFrameworkThread(() =>
|
||||||
{
|
{
|
||||||
|
|
@ -469,7 +469,7 @@ internal sealed class Framework : IDisposable, IServiceType, IFramework
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IFramework>]
|
[ResolveVia<IFramework>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class FrameworkPluginScoped : IDisposable, IServiceType, IFramework
|
internal class FrameworkPluginScoped : IInternalDisposableService, IFramework
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly Framework frameworkService = Service<Framework>.Get();
|
private readonly Framework frameworkService = Service<Framework>.Get();
|
||||||
|
|
@ -504,7 +504,7 @@ internal class FrameworkPluginScoped : IDisposable, IServiceType, IFramework
|
||||||
public bool IsFrameworkUnloading => this.frameworkService.IsFrameworkUnloading;
|
public bool IsFrameworkUnloading => this.frameworkService.IsFrameworkUnloading;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.frameworkService.Update -= this.OnUpdateForward;
|
this.frameworkService.Update -= this.OnUpdateForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Dalamud.Game.Gui;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed unsafe class ChatGui : IDisposable, IServiceType, IChatGui
|
internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("ChatGui");
|
private static readonly ModuleLog Log = new("ChatGui");
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ internal sealed unsafe class ChatGui : IDisposable, IServiceType, IChatGui
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose of managed and unmanaged resources.
|
/// Dispose of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.printMessageHook.Dispose();
|
this.printMessageHook.Dispose();
|
||||||
this.populateItemLinkHook.Dispose();
|
this.populateItemLinkHook.Dispose();
|
||||||
|
|
@ -409,7 +409,7 @@ internal sealed unsafe class ChatGui : IDisposable, IServiceType, IChatGui
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IChatGui>]
|
[ResolveVia<IChatGui>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ChatGuiPluginScoped : IDisposable, IServiceType, IChatGui
|
internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ChatGui chatGuiService = Service<ChatGui>.Get();
|
private readonly ChatGui chatGuiService = Service<ChatGui>.Get();
|
||||||
|
|
@ -447,7 +447,7 @@ internal class ChatGuiPluginScoped : IDisposable, IServiceType, IChatGui
|
||||||
public IReadOnlyDictionary<(string PluginName, uint CommandId), Action<uint, SeString>> RegisteredLinkHandlers => this.chatGuiService.RegisteredLinkHandlers;
|
public IReadOnlyDictionary<(string PluginName, uint CommandId), Action<uint, SeString>> RegisteredLinkHandlers => this.chatGuiService.RegisteredLinkHandlers;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.chatGuiService.ChatMessage -= this.OnMessageForward;
|
this.chatGuiService.ChatMessage -= this.OnMessageForward;
|
||||||
this.chatGuiService.CheckMessageHandled -= this.OnCheckMessageForward;
|
this.chatGuiService.CheckMessageHandled -= this.OnCheckMessageForward;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Dalamud.Game.Gui.ContextMenu;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed unsafe class ContextMenu : IDisposable, IServiceType, IContextMenu
|
internal sealed unsafe class ContextMenu : IInternalDisposableService, IContextMenu
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("ContextMenu");
|
private static readonly ModuleLog Log = new("ContextMenu");
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ internal sealed unsafe class ContextMenu : IDisposable, IServiceType, IContextMe
|
||||||
private IReadOnlyList<MenuItem>? SubmenuItems { get; set; }
|
private IReadOnlyList<MenuItem>? SubmenuItems { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
var manager = RaptureAtkUnitManager.Instance();
|
var manager = RaptureAtkUnitManager.Instance();
|
||||||
var menu = manager->GetAddonByName("ContextMenu");
|
var menu = manager->GetAddonByName("ContextMenu");
|
||||||
|
|
@ -496,7 +496,7 @@ original:
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IContextMenu>]
|
[ResolveVia<IContextMenu>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ContextMenuPluginScoped : IDisposable, IServiceType, IContextMenu
|
internal class ContextMenuPluginScoped : IInternalDisposableService, IContextMenu
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ContextMenu parentService = Service<ContextMenu>.Get();
|
private readonly ContextMenu parentService = Service<ContextMenu>.Get();
|
||||||
|
|
@ -514,7 +514,7 @@ internal class ContextMenuPluginScoped : IDisposable, IServiceType, IContextMenu
|
||||||
private object MenuItemsLock { get; } = new();
|
private object MenuItemsLock { get; } = new();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.parentService.OnMenuOpened -= this.OnMenuOpenedForward;
|
this.parentService.OnMenuOpened -= this.OnMenuOpenedForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Dalamud.Game.Gui.Dtr;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
|
internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar
|
||||||
{
|
{
|
||||||
private const uint BaseNodeId = 1000;
|
private const uint BaseNodeId = 1000;
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.addonLifecycle.UnregisterListener(this.dtrPostDrawListener);
|
this.addonLifecycle.UnregisterListener(this.dtrPostDrawListener);
|
||||||
this.addonLifecycle.UnregisterListener(this.dtrPostRequestedUpdateListener);
|
this.addonLifecycle.UnregisterListener(this.dtrPostRequestedUpdateListener);
|
||||||
|
|
@ -493,7 +493,7 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IDtrBar>]
|
[ResolveVia<IDtrBar>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class DtrBarPluginScoped : IDisposable, IServiceType, IDtrBar
|
internal class DtrBarPluginScoped : IInternalDisposableService, IDtrBar
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly DtrBar dtrBarService = Service<DtrBar>.Get();
|
private readonly DtrBar dtrBarService = Service<DtrBar>.Get();
|
||||||
|
|
@ -501,7 +501,7 @@ internal class DtrBarPluginScoped : IDisposable, IServiceType, IDtrBar
|
||||||
private readonly Dictionary<string, DtrBarEntry> pluginEntries = new();
|
private readonly Dictionary<string, DtrBarEntry> pluginEntries = new();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
foreach (var entry in this.pluginEntries)
|
foreach (var entry in this.pluginEntries)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Dalamud.Game.Gui.FlyText;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class FlyTextGui : IDisposable, IServiceType, IFlyTextGui
|
internal sealed class FlyTextGui : IInternalDisposableService, IFlyTextGui
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The native function responsible for adding fly text to the UI. See <see cref="FlyTextGuiAddressResolver.AddFlyText"/>.
|
/// The native function responsible for adding fly text to the UI. See <see cref="FlyTextGuiAddressResolver.AddFlyText"/>.
|
||||||
|
|
@ -78,7 +78,7 @@ internal sealed class FlyTextGui : IDisposable, IServiceType, IFlyTextGui
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes of managed and unmanaged resources.
|
/// Disposes of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.createFlyTextHook.Dispose();
|
this.createFlyTextHook.Dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,7 @@ internal sealed class FlyTextGui : IDisposable, IServiceType, IFlyTextGui
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IFlyTextGui>]
|
[ResolveVia<IFlyTextGui>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class FlyTextGuiPluginScoped : IDisposable, IServiceType, IFlyTextGui
|
internal class FlyTextGuiPluginScoped : IInternalDisposableService, IFlyTextGui
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly FlyTextGui flyTextGuiService = Service<FlyTextGui>.Get();
|
private readonly FlyTextGui flyTextGuiService = Service<FlyTextGui>.Get();
|
||||||
|
|
@ -294,7 +294,7 @@ internal class FlyTextGuiPluginScoped : IDisposable, IServiceType, IFlyTextGui
|
||||||
public event IFlyTextGui.OnFlyTextCreatedDelegate? FlyTextCreated;
|
public event IFlyTextGui.OnFlyTextCreatedDelegate? FlyTextCreated;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.flyTextGuiService.FlyTextCreated -= this.FlyTextCreatedForward;
|
this.flyTextGuiService.FlyTextCreated -= this.FlyTextCreatedForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Game.Gui;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui
|
internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("GameGui");
|
private static readonly ModuleLog Log = new("GameGui");
|
||||||
|
|
||||||
|
|
@ -344,7 +344,7 @@ internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disables the hooks and submodules of this module.
|
/// Disables the hooks and submodules of this module.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.setGlobalBgmHook.Dispose();
|
this.setGlobalBgmHook.Dispose();
|
||||||
this.handleItemHoverHook.Dispose();
|
this.handleItemHoverHook.Dispose();
|
||||||
|
|
@ -520,7 +520,7 @@ internal sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGameGui>]
|
[ResolveVia<IGameGui>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class GameGuiPluginScoped : IDisposable, IServiceType, IGameGui
|
internal class GameGuiPluginScoped : IInternalDisposableService, IGameGui
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly GameGui gameGuiService = Service<GameGui>.Get();
|
private readonly GameGui gameGuiService = Service<GameGui>.Get();
|
||||||
|
|
@ -558,7 +558,7 @@ internal class GameGuiPluginScoped : IDisposable, IServiceType, IGameGui
|
||||||
public HoveredAction HoveredAction => this.gameGuiService.HoveredAction;
|
public HoveredAction HoveredAction => this.gameGuiService.HoveredAction;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.gameGuiService.UiHideToggled -= this.UiHideToggledForward;
|
this.gameGuiService.UiHideToggled -= this.UiHideToggledForward;
|
||||||
this.gameGuiService.HoveredItemChanged -= this.HoveredItemForward;
|
this.gameGuiService.HoveredItemChanged -= this.HoveredItemForward;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Dalamud.Game.Gui.PartyFinder;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGui
|
internal sealed class PartyFinderGui : IInternalDisposableService, IPartyFinderGui
|
||||||
{
|
{
|
||||||
private readonly PartyFinderAddressResolver address;
|
private readonly PartyFinderAddressResolver address;
|
||||||
private readonly IntPtr memory;
|
private readonly IntPtr memory;
|
||||||
|
|
@ -47,7 +47,7 @@ internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGu
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose of managed and unmanaged resources.
|
/// Dispose of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.receiveListingHook.Dispose();
|
this.receiveListingHook.Dispose();
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ internal sealed class PartyFinderGui : IDisposable, IServiceType, IPartyFinderGu
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IPartyFinderGui>]
|
[ResolveVia<IPartyFinderGui>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class PartyFinderGuiPluginScoped : IDisposable, IServiceType, IPartyFinderGui
|
internal class PartyFinderGuiPluginScoped : IInternalDisposableService, IPartyFinderGui
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly PartyFinderGui partyFinderGuiService = Service<PartyFinderGui>.Get();
|
private readonly PartyFinderGui partyFinderGuiService = Service<PartyFinderGui>.Get();
|
||||||
|
|
@ -148,7 +148,7 @@ internal class PartyFinderGuiPluginScoped : IDisposable, IServiceType, IPartyFin
|
||||||
public event IPartyFinderGui.PartyFinderListingEventDelegate? ReceiveListing;
|
public event IPartyFinderGui.PartyFinderListingEventDelegate? ReceiveListing;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.partyFinderGuiService.ReceiveListing -= this.ReceiveListingForward;
|
this.partyFinderGuiService.ReceiveListing -= this.ReceiveListingForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Dalamud.Game.Gui.Toast;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed partial class ToastGui : IDisposable, IServiceType, IToastGui
|
internal sealed partial class ToastGui : IInternalDisposableService, IToastGui
|
||||||
{
|
{
|
||||||
private const uint QuestToastCheckmarkMagic = 60081;
|
private const uint QuestToastCheckmarkMagic = 60081;
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ internal sealed partial class ToastGui : IDisposable, IServiceType, IToastGui
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes of managed and unmanaged resources.
|
/// Disposes of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.showNormalToastHook.Dispose();
|
this.showNormalToastHook.Dispose();
|
||||||
this.showQuestToastHook.Dispose();
|
this.showQuestToastHook.Dispose();
|
||||||
|
|
@ -383,7 +383,7 @@ internal sealed partial class ToastGui
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IToastGui>]
|
[ResolveVia<IToastGui>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ToastGuiPluginScoped : IDisposable, IServiceType, IToastGui
|
internal class ToastGuiPluginScoped : IInternalDisposableService, IToastGui
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly ToastGui toastGuiService = Service<ToastGui>.Get();
|
private readonly ToastGui toastGuiService = Service<ToastGui>.Get();
|
||||||
|
|
@ -408,7 +408,7 @@ internal class ToastGuiPluginScoped : IDisposable, IServiceType, IToastGui
|
||||||
public event IToastGui.OnErrorToastDelegate? ErrorToast;
|
public event IToastGui.OnErrorToastDelegate? ErrorToast;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.toastGuiService.Toast -= this.ToastForward;
|
this.toastGuiService.Toast -= this.ToastForward;
|
||||||
this.toastGuiService.QuestToast -= this.QuestToastForward;
|
this.toastGuiService.QuestToast -= this.QuestToastForward;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace Dalamud.Game.Internal;
|
||||||
/// This class disables anti-debug functionality in the game client.
|
/// This class disables anti-debug functionality in the game client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed partial class AntiDebug : IServiceType
|
internal sealed class AntiDebug : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly byte[] nop = new byte[] { 0x31, 0xC0, 0x90, 0x90, 0x90, 0x90 };
|
private readonly byte[] nop = new byte[] { 0x31, 0xC0, 0x90, 0x90, 0x90, 0x90 };
|
||||||
private byte[] original;
|
private byte[] original;
|
||||||
|
|
@ -43,16 +43,25 @@ internal sealed partial class AntiDebug : IServiceType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Finalizes an instance of the <see cref="AntiDebug"/> class.</summary>
|
||||||
|
~AntiDebug() => this.Disable();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether the anti-debugging is enabled.
|
/// Gets a value indicating whether the anti-debugging is enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsEnabled { get; private set; } = false;
|
public bool IsEnabled { get; private set; } = false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
void IInternalDisposableService.DisposeService() => this.Disable();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables the anti-debugging by overwriting code in memory.
|
/// Enables the anti-debugging by overwriting code in memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Enable()
|
public void Enable()
|
||||||
{
|
{
|
||||||
|
if (this.IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
this.original = new byte[this.nop.Length];
|
this.original = new byte[this.nop.Length];
|
||||||
if (this.debugCheckAddress != IntPtr.Zero && !this.IsEnabled)
|
if (this.debugCheckAddress != IntPtr.Zero && !this.IsEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -73,6 +82,9 @@ internal sealed partial class AntiDebug : IServiceType
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disable()
|
public void Disable()
|
||||||
{
|
{
|
||||||
|
if (!this.IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (this.debugCheckAddress != IntPtr.Zero && this.original != null)
|
if (this.debugCheckAddress != IntPtr.Zero && this.original != null)
|
||||||
{
|
{
|
||||||
Log.Information($"Reverting debug check at 0x{this.debugCheckAddress.ToInt64():X}");
|
Log.Information($"Reverting debug check at 0x{this.debugCheckAddress.ToInt64():X}");
|
||||||
|
|
@ -86,45 +98,3 @@ internal sealed partial class AntiDebug : IServiceType
|
||||||
this.IsEnabled = false;
|
this.IsEnabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementing IDisposable.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed partial class AntiDebug : IDisposable
|
|
||||||
{
|
|
||||||
private bool disposed = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the <see cref="AntiDebug"/> class.
|
|
||||||
/// </summary>
|
|
||||||
~AntiDebug() => this.Dispose(false);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of managed and unmanaged resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
this.Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of managed and unmanaged resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">If this was disposed through calling Dispose() or from being finalized.</param>
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (this.disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// If anti-debug is enabled and is being disposed, odds are either the game is exiting, or Dalamud is being reloaded.
|
|
||||||
// If it is the latter, there's half a chance a debugger is currently attached. There's no real need to disable the
|
|
||||||
// check in either situation anyways. However if Dalamud is being reloaded, the sig may fail so may as well undo it.
|
|
||||||
this.Disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Dalamud.Game.Internal;
|
||||||
/// This class implements in-game Dalamud options in the in-game System menu.
|
/// This class implements in-game Dalamud options in the in-game System menu.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed unsafe partial class DalamudAtkTweaks : IServiceType
|
internal sealed unsafe class DalamudAtkTweaks : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly AtkValueChangeType atkValueChangeType;
|
private readonly AtkValueChangeType atkValueChangeType;
|
||||||
private readonly AtkValueSetString atkValueSetString;
|
private readonly AtkValueSetString atkValueSetString;
|
||||||
|
|
@ -40,6 +40,8 @@ internal sealed unsafe partial class DalamudAtkTweaks : IServiceType
|
||||||
private readonly string locDalamudPlugins;
|
private readonly string locDalamudPlugins;
|
||||||
private readonly string locDalamudSettings;
|
private readonly string locDalamudSettings;
|
||||||
|
|
||||||
|
private bool disposed = false;
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private DalamudAtkTweaks(TargetSigScanner sigScanner)
|
private DalamudAtkTweaks(TargetSigScanner sigScanner)
|
||||||
{
|
{
|
||||||
|
|
@ -69,6 +71,9 @@ internal sealed unsafe partial class DalamudAtkTweaks : IServiceType
|
||||||
this.hookAtkUnitBaseReceiveGlobalEvent.Enable();
|
this.hookAtkUnitBaseReceiveGlobalEvent.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Finalizes an instance of the <see cref="DalamudAtkTweaks"/> class.</summary>
|
||||||
|
~DalamudAtkTweaks() => this.Dispose(false);
|
||||||
|
|
||||||
private delegate void AgentHudOpenSystemMenuPrototype(void* thisPtr, AtkValue* atkValueArgs, uint menuSize);
|
private delegate void AgentHudOpenSystemMenuPrototype(void* thisPtr, AtkValue* atkValueArgs, uint menuSize);
|
||||||
|
|
||||||
private delegate void AtkValueChangeType(AtkValue* thisPtr, ValueType type);
|
private delegate void AtkValueChangeType(AtkValue* thisPtr, ValueType type);
|
||||||
|
|
@ -79,6 +84,26 @@ internal sealed unsafe partial class DalamudAtkTweaks : IServiceType
|
||||||
|
|
||||||
private delegate IntPtr AtkUnitBaseReceiveGlobalEvent(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5);
|
private delegate IntPtr AtkUnitBaseReceiveGlobalEvent(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IInternalDisposableService.DisposeService() => this.Dispose(true);
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (this.disposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
this.hookAgentHudOpenSystemMenu.Dispose();
|
||||||
|
this.hookUiModuleRequestMainCommand.Dispose();
|
||||||
|
this.hookAtkUnitBaseReceiveGlobalEvent.Dispose();
|
||||||
|
|
||||||
|
// this.contextMenu.ContextMenuOpened -= this.ContextMenuOnContextMenuOpened;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
private void ContextMenuOnContextMenuOpened(ContextMenuOpenedArgs args)
|
private void ContextMenuOnContextMenuOpened(ContextMenuOpenedArgs args)
|
||||||
{
|
{
|
||||||
|
|
@ -229,45 +254,3 @@ internal sealed unsafe partial class DalamudAtkTweaks : IServiceType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implements IDisposable.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed partial class DalamudAtkTweaks : IDisposable
|
|
||||||
{
|
|
||||||
private bool disposed = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the <see cref="DalamudAtkTweaks"/> class.
|
|
||||||
/// </summary>
|
|
||||||
~DalamudAtkTweaks() => this.Dispose(false);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose of managed and unmanaged resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
this.Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose of managed and unmanaged resources.
|
|
||||||
/// </summary>
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (this.disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
this.hookAgentHudOpenSystemMenu.Dispose();
|
|
||||||
this.hookUiModuleRequestMainCommand.Dispose();
|
|
||||||
this.hookAtkUnitBaseReceiveGlobalEvent.Dispose();
|
|
||||||
|
|
||||||
// this.contextMenu.ContextMenuOpened -= this.ContextMenuOnContextMenuOpened;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Game.Inventory;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal class GameInventory : IDisposable, IServiceType
|
internal class GameInventory : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly List<GameInventoryPluginScoped> subscribersPendingChange = new();
|
private readonly List<GameInventoryPluginScoped> subscribersPendingChange = new();
|
||||||
private readonly List<GameInventoryPluginScoped> subscribers = new();
|
private readonly List<GameInventoryPluginScoped> subscribers = new();
|
||||||
|
|
@ -61,7 +61,7 @@ internal class GameInventory : IDisposable, IServiceType
|
||||||
private unsafe delegate void RaptureAtkModuleUpdateDelegate(RaptureAtkModule* ram, float f1);
|
private unsafe delegate void RaptureAtkModuleUpdateDelegate(RaptureAtkModule* ram, float f1);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
lock (this.subscribersPendingChange)
|
lock (this.subscribersPendingChange)
|
||||||
{
|
{
|
||||||
|
|
@ -351,7 +351,7 @@ internal class GameInventory : IDisposable, IServiceType
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGameInventory>]
|
[ResolveVia<IGameInventory>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInventory
|
internal class GameInventoryPluginScoped : IInternalDisposableService, IGameInventory
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new(nameof(GameInventoryPluginScoped));
|
private static readonly ModuleLog Log = new(nameof(GameInventoryPluginScoped));
|
||||||
|
|
||||||
|
|
@ -406,7 +406,7 @@ internal class GameInventoryPluginScoped : IDisposable, IServiceType, IGameInven
|
||||||
public event IGameInventory.InventoryChangedDelegate<InventoryItemMergedArgs>? ItemMergedExplicit;
|
public event IGameInventory.InventoryChangedDelegate<InventoryItemMergedArgs>? ItemMergedExplicit;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.gameInventoryService.Unsubscribe(this);
|
this.gameInventoryService.Unsubscribe(this);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Dalamud.Game.Network;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
|
internal sealed class GameNetwork : IInternalDisposableService, IGameNetwork
|
||||||
{
|
{
|
||||||
private readonly GameNetworkAddressResolver address;
|
private readonly GameNetworkAddressResolver address;
|
||||||
private readonly Hook<ProcessZonePacketDownDelegate> processZonePacketDownHook;
|
private readonly Hook<ProcessZonePacketDownDelegate> processZonePacketDownHook;
|
||||||
|
|
@ -59,7 +59,7 @@ internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
|
||||||
public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
|
public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.processZonePacketDownHook.Dispose();
|
this.processZonePacketDownHook.Dispose();
|
||||||
this.processZonePacketUpHook.Dispose();
|
this.processZonePacketUpHook.Dispose();
|
||||||
|
|
@ -145,7 +145,7 @@ internal sealed class GameNetwork : IDisposable, IServiceType, IGameNetwork
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGameNetwork>]
|
[ResolveVia<IGameNetwork>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class GameNetworkPluginScoped : IDisposable, IServiceType, IGameNetwork
|
internal class GameNetworkPluginScoped : IInternalDisposableService, IGameNetwork
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly GameNetwork gameNetworkService = Service<GameNetwork>.Get();
|
private readonly GameNetwork gameNetworkService = Service<GameNetwork>.Get();
|
||||||
|
|
@ -162,7 +162,7 @@ internal class GameNetworkPluginScoped : IDisposable, IServiceType, IGameNetwork
|
||||||
public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
|
public event IGameNetwork.OnNetworkMessageDelegate? NetworkMessage;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.gameNetworkService.NetworkMessage -= this.NetworkMessageForward;
|
this.gameNetworkService.NetworkMessage -= this.NetworkMessageForward;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Dalamud.Game.Network.Internal;
|
||||||
/// This class handles network notifications and uploading market board data.
|
/// This class handles network notifications and uploading market board data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal unsafe class NetworkHandlers : IDisposable, IServiceType
|
internal unsafe class NetworkHandlers : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly IMarketBoardUploader uploader;
|
private readonly IMarketBoardUploader uploader;
|
||||||
|
|
||||||
|
|
@ -213,7 +213,7 @@ internal unsafe class NetworkHandlers : IDisposable, IServiceType
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes of managed and unmanaged resources.
|
/// Disposes of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.disposing = true;
|
this.disposing = true;
|
||||||
this.Dispose(this.disposing);
|
this.Dispose(this.disposing);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Dalamud.Game.Network.Internal;
|
||||||
/// This class enables TCP optimizations in the game socket for better performance.
|
/// This class enables TCP optimizations in the game socket for better performance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed class WinSockHandlers : IDisposable, IServiceType
|
internal sealed class WinSockHandlers : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private Hook<SocketDelegate> ws2SocketHook;
|
private Hook<SocketDelegate> ws2SocketHook;
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ internal sealed class WinSockHandlers : IDisposable, IServiceType
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes of managed and unmanaged resources.
|
/// Disposes of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.ws2SocketHook?.Dispose();
|
this.ws2SocketHook?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,10 @@ public class SigScanner : IDisposable, ISigScanner
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ProcessModule Module { get; }
|
public ProcessModule Module { get; }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether this instance of <see cref="SigScanner"/> is meant to be a
|
||||||
|
/// Dalamud service.</summary>
|
||||||
|
private protected bool IsService { get; set; }
|
||||||
|
|
||||||
private IntPtr TextSectionTop => this.TextSectionBase + this.TextSectionSize;
|
private IntPtr TextSectionTop => this.TextSectionBase + this.TextSectionSize;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -309,13 +313,11 @@ public class SigScanner : IDisposable, ISigScanner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Free the memory of the copied module search area on object disposal, if applicable.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.Save();
|
if (!this.IsService)
|
||||||
Marshal.FreeHGlobal(this.moduleCopyPtr);
|
this.DisposeCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -337,6 +339,15 @@ public class SigScanner : IDisposable, ISigScanner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Free the memory of the copied module search area on object disposal, if applicable.
|
||||||
|
/// </summary>
|
||||||
|
private protected void DisposeCore()
|
||||||
|
{
|
||||||
|
this.Save();
|
||||||
|
Marshal.FreeHGlobal(this.moduleCopyPtr);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
|
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Dalamud.Game;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<ISigScanner>]
|
[ResolveVia<ISigScanner>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class TargetSigScanner : SigScanner, IServiceType
|
internal class TargetSigScanner : SigScanner, IPublicDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TargetSigScanner"/> class.
|
/// Initializes a new instance of the <see cref="TargetSigScanner"/> class.
|
||||||
|
|
@ -26,4 +26,14 @@ internal class TargetSigScanner : SigScanner, IServiceType
|
||||||
: base(Process.GetCurrentProcess().MainModule!, doCopy, cacheFile)
|
: base(Process.GetCurrentProcess().MainModule!, doCopy, cacheFile)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IInternalDisposableService.DisposeService()
|
||||||
|
{
|
||||||
|
if (this.IsService)
|
||||||
|
this.DisposeCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IPublicDisposableService.MarkDisposeOnlyFromService() => this.IsService = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Dalamud.Hooking.Internal;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IGameInteropProvider>]
|
[ResolveVia<IGameInteropProvider>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceType, IDisposable
|
internal class GameInteropProviderPluginScoped : IGameInteropProvider, IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly LocalPlugin plugin;
|
private readonly LocalPlugin plugin;
|
||||||
private readonly SigScanner scanner;
|
private readonly SigScanner scanner;
|
||||||
|
|
@ -83,7 +83,7 @@ internal class GameInteropProviderPluginScoped : IGameInteropProvider, IServiceT
|
||||||
=> this.HookFromAddress(this.scanner.ScanText(signature), detour, backend);
|
=> this.HookFromAddress(this.scanner.ScanText(signature), detour, backend);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
var notDisposed = this.trackedHooks.Where(x => !x.IsDisposed).ToArray();
|
var notDisposed = this.trackedHooks.Where(x => !x.IsDisposed).ToArray();
|
||||||
if (notDisposed.Length != 0)
|
if (notDisposed.Length != 0)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Dalamud.Hooking.Internal;
|
||||||
/// This class manages the final disposition of hooks, cleaning up any that have not reverted their changes.
|
/// This class manages the final disposition of hooks, cleaning up any that have not reverted their changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal class HookManager : IDisposable, IServiceType
|
internal class HookManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logger shared with <see cref="Unhooker"/>.
|
/// Logger shared with <see cref="Unhooker"/>.
|
||||||
|
|
@ -74,7 +74,7 @@ internal class HookManager : IDisposable, IServiceType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
RevertHooks();
|
RevertHooks();
|
||||||
TrackedHooks.Clear();
|
TrackedHooks.Clear();
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Dalamud.Hooking.WndProcHook;
|
||||||
/// Manages WndProc hooks for game main window and extra ImGui viewport windows.
|
/// Manages WndProc hooks for game main window and extra ImGui viewport windows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed class WndProcHookManager : IServiceType, IDisposable
|
internal sealed class WndProcHookManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new(nameof(WndProcHookManager));
|
private static readonly ModuleLog Log = new(nameof(WndProcHookManager));
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ internal sealed class WndProcHookManager : IServiceType, IDisposable
|
||||||
public event WndProcEventDelegate? PostWndProc;
|
public event WndProcEventDelegate? PostWndProc;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
if (this.dispatchMessageWHook.IsDisposed)
|
if (this.dispatchMessageWHook.IsDisposed)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,20 @@
|
||||||
public interface IServiceType
|
public interface IServiceType
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary><see cref="IDisposable"/>, but for <see cref="IServiceType"/>.</summary>
|
||||||
|
/// <remarks>Use this to prevent services from accidentally being disposed by plugins or <c>using</c> clauses.</remarks>
|
||||||
|
internal interface IInternalDisposableService : IServiceType
|
||||||
|
{
|
||||||
|
/// <summary>Disposes the service.</summary>
|
||||||
|
void DisposeService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>An <see cref="IInternalDisposableService"/> which happens to be public and needs to expose
|
||||||
|
/// <see cref="IDisposable.Dispose"/>.</summary>
|
||||||
|
internal interface IPublicDisposableService : IInternalDisposableService, IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>Marks that only <see cref="IInternalDisposableService.DisposeService"/> should respond,
|
||||||
|
/// while suppressing <see cref="IDisposable.Dispose"/>.</summary>
|
||||||
|
void MarkDisposeOnlyFromService();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Dalamud.Interface.DragDrop;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IDragDropManager>]
|
[ResolveVia<IDragDropManager>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal partial class DragDropManager : IDisposable, IDragDropManager, IServiceType
|
internal partial class DragDropManager : IInternalDisposableService, IDragDropManager
|
||||||
{
|
{
|
||||||
private nint windowHandlePtr = nint.Zero;
|
private nint windowHandlePtr = nint.Zero;
|
||||||
|
|
||||||
|
|
@ -56,6 +56,9 @@ internal partial class DragDropManager : IDisposable, IDragDropManager, IService
|
||||||
/// <summary> Gets the list of directory paths currently being dragged from an external application over any FFXIV-related viewport or stored from the last drop. </summary>
|
/// <summary> Gets the list of directory paths currently being dragged from an external application over any FFXIV-related viewport or stored from the last drop. </summary>
|
||||||
public IReadOnlyList<string> Directories { get; private set; } = Array.Empty<string>();
|
public IReadOnlyList<string> Directories { get; private set; } = Array.Empty<string>();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IInternalDisposableService.DisposeService() => this.Disable();
|
||||||
|
|
||||||
/// <summary> Enable external drag and drop. </summary>
|
/// <summary> Enable external drag and drop. </summary>
|
||||||
public void Enable()
|
public void Enable()
|
||||||
{
|
{
|
||||||
|
|
@ -99,10 +102,6 @@ internal partial class DragDropManager : IDisposable, IDragDropManager, IService
|
||||||
this.ServiceAvailable = false;
|
this.ServiceAvailable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Disable"/>
|
|
||||||
public void Dispose()
|
|
||||||
=> this.Disable();
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IDragDropManager.CreateImGuiSource(string, Func{IDragDropManager, bool}, Func{IDragDropManager, bool})"/>
|
/// <inheritdoc cref="IDragDropManager.CreateImGuiSource(string, Func{IDragDropManager, bool}, Func{IDragDropManager, bool})"/>
|
||||||
public void CreateImGuiSource(string label, Func<IDragDropManager, bool> validityCheck, Func<IDragDropManager, bool> tooltipBuilder)
|
public void CreateImGuiSource(string label, Func<IDragDropManager, bool> validityCheck, Func<IDragDropManager, bool> tooltipBuilder)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ public sealed class SingleFontChooserDialog : IDisposable
|
||||||
/// <summary>Initializes a new instance of the <see cref="SingleFontChooserDialog"/> class.</summary>
|
/// <summary>Initializes a new instance of the <see cref="SingleFontChooserDialog"/> class.</summary>
|
||||||
/// <param name="newAsyncAtlas">A new instance of <see cref="IFontAtlas"/> created using
|
/// <param name="newAsyncAtlas">A new instance of <see cref="IFontAtlas"/> created using
|
||||||
/// <see cref="FontAtlasAutoRebuildMode.Async"/> as its auto-rebuild mode.</param>
|
/// <see cref="FontAtlasAutoRebuildMode.Async"/> as its auto-rebuild mode.</param>
|
||||||
/// <remarks>The passed instance of <see cref="newAsyncAtlas"/> will be disposed after use. If you pass an atlas
|
/// <remarks>The passed instance of <paramref see="newAsyncAtlas"/> will be disposed after use. If you pass an atlas
|
||||||
/// that is already being used, then all the font handles under the passed atlas will be invalidated upon disposing
|
/// that is already being used, then all the font handles under the passed atlas will be invalidated upon disposing
|
||||||
/// this font chooser. Consider using <see cref="SingleFontChooserDialog(UiBuilder, bool, string?)"/> for automatic
|
/// this font chooser. Consider using <see cref="SingleFontChooserDialog(UiBuilder, bool, string?)"/> for automatic
|
||||||
/// handling of font atlas derived from a <see cref="UiBuilder"/>, or even <see cref="CreateAuto"/> for automatic
|
/// handling of font atlas derived from a <see cref="UiBuilder"/>, or even <see cref="CreateAuto"/> for automatic
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// This class handles CJK IME.
|
/// This class handles CJK IME.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed unsafe class DalamudIme : IDisposable, IServiceType
|
internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private const int CImGuiStbTextCreateUndoOffset = 0xB57A0;
|
private const int CImGuiStbTextCreateUndoOffset = 0xB57A0;
|
||||||
private const int CImGuiStbTextUndoOffset = 0xB59C0;
|
private const int CImGuiStbTextUndoOffset = 0xB59C0;
|
||||||
|
|
@ -200,7 +200,7 @@ internal sealed unsafe class DalamudIme : IDisposable, IServiceType
|
||||||
this.candidateStrings.Count != 0 || this.ShowPartialConversion || this.inputModeIcon != default;
|
this.candidateStrings.Count != 0 || this.ShowPartialConversion || this.inputModeIcon != default;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.interfaceManager.Draw -= this.Draw;
|
this.interfaceManager.Draw -= this.Draw;
|
||||||
this.ReleaseUnmanagedResources();
|
this.ReleaseUnmanagedResources();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// This plugin implements all of the Dalamud interface separately, to allow for reloading of the interface and rapid prototyping.
|
/// This plugin implements all of the Dalamud interface separately, to allow for reloading of the interface and rapid prototyping.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal class DalamudInterface : IDisposable, IServiceType
|
internal class DalamudInterface : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private const float CreditsDarkeningMaxAlpha = 0.8f;
|
private const float CreditsDarkeningMaxAlpha = 0.8f;
|
||||||
|
|
||||||
|
|
@ -209,7 +209,7 @@ internal class DalamudInterface : IDisposable, IServiceType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.interfaceManager.Draw -= this.OnDraw;
|
this.interfaceManager.Draw -= this.OnDraw;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed unsafe class ImGuiClipboardFunctionProvider : IServiceType, IDisposable
|
internal sealed unsafe class ImGuiClipboardFunctionProvider : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new(nameof(ImGuiClipboardFunctionProvider));
|
private static readonly ModuleLog Log = new(nameof(ImGuiClipboardFunctionProvider));
|
||||||
private readonly nint clipboardUserDataOriginal;
|
private readonly nint clipboardUserDataOriginal;
|
||||||
|
|
@ -75,7 +75,7 @@ internal sealed unsafe class ImGuiClipboardFunctionProvider : IServiceType, IDis
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
if (!this.clipboardUserData.IsAllocated)
|
if (!this.clipboardUserData.IsAllocated)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// Change push_texture_id to only have one condition.
|
/// Change push_texture_id to only have one condition.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal sealed unsafe class ImGuiDrawListFixProvider : IServiceType, IDisposable
|
internal sealed unsafe class ImGuiDrawListFixProvider : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private const int CImGuiImDrawListAddPolyLineOffset = 0x589B0;
|
private const int CImGuiImDrawListAddPolyLineOffset = 0x589B0;
|
||||||
private const int CImGuiImDrawListAddRectFilled = 0x59FD0;
|
private const int CImGuiImDrawListAddRectFilled = 0x59FD0;
|
||||||
|
|
@ -69,7 +69,7 @@ internal sealed unsafe class ImGuiDrawListFixProvider : IServiceType, IDisposabl
|
||||||
ImDrawFlags flags);
|
ImDrawFlags flags);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.hookImDrawListAddPolyline.Dispose();
|
this.hookImDrawListAddPolyline.Dispose();
|
||||||
this.hookImDrawListAddRectFilled.Dispose();
|
this.hookImDrawListAddRectFilled.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
|
|
@ -51,7 +52,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// This class manages interaction with the ImGui interface.
|
/// This class manages interaction with the ImGui interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal class InterfaceManager : IDisposable, IServiceType
|
internal class InterfaceManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default font size, in points.
|
/// The default font size, in points.
|
||||||
|
|
@ -69,10 +70,13 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly WndProcHookManager wndProcHookManager = Service<WndProcHookManager>.Get();
|
private readonly WndProcHookManager wndProcHookManager = Service<WndProcHookManager>.Get();
|
||||||
|
|
||||||
|
[ServiceManager.ServiceDependency]
|
||||||
|
private readonly Framework framework = Service<Framework>.Get();
|
||||||
|
|
||||||
private readonly SwapChainVtableResolver address = new();
|
private readonly SwapChainVtableResolver address = new();
|
||||||
private readonly Hook<SetCursorDelegate> setCursorHook;
|
|
||||||
private RawDX11Scene? scene;
|
private RawDX11Scene? scene;
|
||||||
|
|
||||||
|
private Hook<SetCursorDelegate>? setCursorHook;
|
||||||
private Hook<PresentDelegate>? presentHook;
|
private Hook<PresentDelegate>? presentHook;
|
||||||
private Hook<ResizeBuffersDelegate>? resizeBuffersHook;
|
private Hook<ResizeBuffersDelegate>? resizeBuffersHook;
|
||||||
|
|
||||||
|
|
@ -87,8 +91,6 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
private InterfaceManager()
|
private InterfaceManager()
|
||||||
{
|
{
|
||||||
this.setCursorHook = Hook<SetCursorDelegate>.FromImport(
|
|
||||||
null, "user32.dll", "SetCursor", 0, this.SetCursorDetour);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||||
|
|
@ -233,25 +235,45 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispose of managed and unmanaged resources.
|
/// Dispose of managed and unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
if (Service<Framework>.GetNullable() is { } framework)
|
// Unload hooks from the framework thread if possible.
|
||||||
framework.RunOnFrameworkThread(Disposer).Wait();
|
// We're currently off the framework thread, as this function can only be called from
|
||||||
else
|
// ServiceManager.UnloadAllServices, which is called from EntryPoint.RunThread.
|
||||||
Disposer();
|
// The functions being unhooked are mostly called from the main thread, so unhooking from the main thread when
|
||||||
|
// possible would avoid any chance of unhooking a function that currently is being called.
|
||||||
|
// If unloading is initiated from "Unload Dalamud" /xldev menu, then the framework would still be running, as
|
||||||
|
// Framework.Destroy has never been called and thus Framework.IsFrameworkUnloading cannot be true, and this
|
||||||
|
// function will actually run the destroy from the framework thread.
|
||||||
|
// Otherwise, as Framework.IsFrameworkUnloading should have been set, this code should run immediately.
|
||||||
|
this.framework.RunOnFrameworkThread(ClearHooks).Wait();
|
||||||
|
|
||||||
|
// Below this point, hooks are guaranteed to be no longer called.
|
||||||
|
|
||||||
|
// A font resource lock outlives the parent handle and the owner atlas. It should be disposed.
|
||||||
|
Interlocked.Exchange(ref this.defaultFontResourceLock, null)?.Dispose();
|
||||||
|
|
||||||
|
// Font handles become invalid after disposing the atlas, but just to be safe.
|
||||||
|
this.DefaultFontHandle?.Dispose();
|
||||||
|
this.DefaultFontHandle = null;
|
||||||
|
|
||||||
|
this.MonoFontHandle?.Dispose();
|
||||||
|
this.MonoFontHandle = null;
|
||||||
|
|
||||||
|
this.IconFontHandle?.Dispose();
|
||||||
|
this.IconFontHandle = null;
|
||||||
|
|
||||||
|
Interlocked.Exchange(ref this.dalamudAtlas, null)?.Dispose();
|
||||||
|
Interlocked.Exchange(ref this.scene, null)?.Dispose();
|
||||||
|
|
||||||
this.wndProcHookManager.PreWndProc -= this.WndProcHookManagerOnPreWndProc;
|
|
||||||
this.defaultFontResourceLock?.Dispose(); // lock outlives handle and atlas
|
|
||||||
this.defaultFontResourceLock = null;
|
|
||||||
this.dalamudAtlas?.Dispose();
|
|
||||||
this.scene?.Dispose();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void Disposer()
|
void ClearHooks()
|
||||||
{
|
{
|
||||||
this.setCursorHook.Dispose();
|
this.wndProcHookManager.PreWndProc -= this.WndProcHookManagerOnPreWndProc;
|
||||||
this.presentHook?.Dispose();
|
Interlocked.Exchange(ref this.setCursorHook, null)?.Dispose();
|
||||||
this.resizeBuffersHook?.Dispose();
|
Interlocked.Exchange(ref this.presentHook, null)?.Dispose();
|
||||||
|
Interlocked.Exchange(ref this.resizeBuffersHook, null)?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,7 +715,6 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
"InterfaceManager accepts event registration and stuff even when the game window is not ready.")]
|
"InterfaceManager accepts event registration and stuff even when the game window is not ready.")]
|
||||||
private void ContinueConstruction(
|
private void ContinueConstruction(
|
||||||
TargetSigScanner sigScanner,
|
TargetSigScanner sigScanner,
|
||||||
Framework framework,
|
|
||||||
FontAtlasFactory fontAtlasFactory)
|
FontAtlasFactory fontAtlasFactory)
|
||||||
{
|
{
|
||||||
this.dalamudAtlas = fontAtlasFactory
|
this.dalamudAtlas = fontAtlasFactory
|
||||||
|
|
@ -731,7 +752,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
this.DefaultFontHandle.ImFontChanged += (_, font) =>
|
this.DefaultFontHandle.ImFontChanged += (_, font) =>
|
||||||
{
|
{
|
||||||
var fontLocked = font.NewRef();
|
var fontLocked = font.NewRef();
|
||||||
Service<Framework>.Get().RunOnFrameworkThread(
|
this.framework.RunOnFrameworkThread(
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
// Update the ImGui default font.
|
// Update the ImGui default font.
|
||||||
|
|
@ -765,6 +786,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
Log.Error(ex, "Could not enable immersive mode");
|
Log.Error(ex, "Could not enable immersive mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setCursorHook = Hook<SetCursorDelegate>.FromImport(null, "user32.dll", "SetCursor", 0, this.SetCursorDetour);
|
||||||
this.presentHook = Hook<PresentDelegate>.FromAddress(this.address.Present, this.PresentDetour);
|
this.presentHook = Hook<PresentDelegate>.FromAddress(this.address.Present, this.PresentDetour);
|
||||||
this.resizeBuffersHook = Hook<ResizeBuffersDelegate>.FromAddress(this.address.ResizeBuffers, this.ResizeBuffersDetour);
|
this.resizeBuffersHook = Hook<ResizeBuffersDelegate>.FromAddress(this.address.ResizeBuffers, this.ResizeBuffersDetour);
|
||||||
|
|
||||||
|
|
@ -808,7 +830,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
if (this.lastWantCapture && (!this.scene?.IsImGuiCursor(hCursor) ?? false) && this.OverrideGameCursor)
|
if (this.lastWantCapture && (!this.scene?.IsImGuiCursor(hCursor) ?? false) && this.OverrideGameCursor)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
return this.setCursorHook.IsDisposed
|
return this.setCursorHook?.IsDisposed is not false
|
||||||
? User32.SetCursor(new(hCursor, false)).DangerousGetHandle()
|
? User32.SetCursor(new(hCursor, false)).DangerousGetHandle()
|
||||||
: this.setCursorHook.Original(hCursor);
|
: this.setCursorHook.Original(hCursor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
[ResolveVia<ITextureProvider>]
|
[ResolveVia<ITextureProvider>]
|
||||||
[ResolveVia<ITextureSubstitutionProvider>]
|
[ResolveVia<ITextureSubstitutionProvider>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITextureSubstitutionProvider
|
internal class TextureManager : IInternalDisposableService, ITextureProvider, ITextureSubstitutionProvider
|
||||||
{
|
{
|
||||||
private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex";
|
private const string IconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}.tex";
|
||||||
private const string HighResolutionIconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}_hr1.tex";
|
private const string HighResolutionIconFileFormat = "ui/icon/{0:D3}000/{1}{2:D6}_hr1.tex";
|
||||||
|
|
@ -268,7 +268,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.fallbackTextureWrap?.Dispose();
|
this.fallbackTextureWrap?.Dispose();
|
||||||
this.framework.Update -= this.FrameworkOnUpdate;
|
this.framework.Update -= this.FrameworkOnUpdate;
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ internal class GameInventoryTestWidget : IDataWindowWidget
|
||||||
this.standardEnabled = false;
|
this.standardEnabled = false;
|
||||||
if (!this.rawEnabled)
|
if (!this.rawEnabled)
|
||||||
{
|
{
|
||||||
this.scoped.Dispose();
|
((IInternalDisposableService)this.scoped).DisposeService();
|
||||||
this.scoped = null;
|
this.scoped = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ internal class GameInventoryTestWidget : IDataWindowWidget
|
||||||
this.rawEnabled = false;
|
this.rawEnabled = false;
|
||||||
if (!this.standardEnabled)
|
if (!this.standardEnabled)
|
||||||
{
|
{
|
||||||
this.scoped.Dispose();
|
((IInternalDisposableService)this.scoped).DisposeService();
|
||||||
this.scoped = null;
|
this.scoped = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +135,7 @@ internal class GameInventoryTestWidget : IDataWindowWidget
|
||||||
{
|
{
|
||||||
if (ImGui.Button("Disable##all-disable"))
|
if (ImGui.Button("Disable##all-disable"))
|
||||||
{
|
{
|
||||||
this.scoped?.Dispose();
|
((IInternalDisposableService)this.scoped)?.DisposeService();
|
||||||
this.scoped = null;
|
this.scoped = null;
|
||||||
this.standardEnabled = this.rawEnabled = false;
|
this.standardEnabled = this.rawEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Dalamud.Interface.Internal.Windows;
|
||||||
/// A cache for plugin icons and images.
|
/// A cache for plugin icons and images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal class PluginImageCache : IDisposable, IServiceType
|
internal class PluginImageCache : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum plugin image width.
|
/// Maximum plugin image width.
|
||||||
|
|
@ -136,7 +136,7 @@ internal class PluginImageCache : IDisposable, IServiceType
|
||||||
this.dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall, this.EmptyTexture);
|
this.dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall, this.EmptyTexture);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.cancelToken.Cancel();
|
this.cancelToken.Cancel();
|
||||||
this.downloadQueue.CompleteAdding();
|
this.downloadQueue.CompleteAdding();
|
||||||
|
|
|
||||||
|
|
@ -204,12 +204,12 @@ internal sealed partial class FontAtlasFactory
|
||||||
{
|
{
|
||||||
while (this.IsBuildInProgress)
|
while (this.IsBuildInProgress)
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
this.Garbage.Dispose();
|
this.Clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Garbage.Dispose();
|
this.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRefCount;
|
return newRefCount;
|
||||||
|
|
@ -227,6 +227,20 @@ internal sealed partial class FontAtlasFactory
|
||||||
var axisSubstance = this.Substances.OfType<GamePrebakedFontHandle.HandleSubstance>().Single();
|
var axisSubstance = this.Substances.OfType<GamePrebakedFontHandle.HandleSubstance>().Single();
|
||||||
return new(factory, this, axisSubstance, isAsync) { BuildStep = FontAtlasBuildStep.PreBuild };
|
return new(factory, this, axisSubstance, isAsync) { BuildStep = FontAtlasBuildStep.PreBuild };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Garbage.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(
|
||||||
|
e,
|
||||||
|
$"Disposing {nameof(FontAtlasBuiltData)} of {this.Owner?.Name ?? "???"}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DalamudFontAtlas : IFontAtlas, DisposeSafety.IDisposeCallback
|
private class DalamudFontAtlas : IFontAtlas, DisposeSafety.IDisposeCallback
|
||||||
|
|
@ -547,13 +561,13 @@ internal sealed partial class FontAtlasFactory
|
||||||
{
|
{
|
||||||
if (this.buildIndex != rebuildIndex)
|
if (this.buildIndex != rebuildIndex)
|
||||||
{
|
{
|
||||||
data.ExplicitDisposeIgnoreExceptions();
|
data.Release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prevBuiltData = this.builtData;
|
var prevBuiltData = this.builtData;
|
||||||
this.builtData = data;
|
this.builtData = data;
|
||||||
prevBuiltData.ExplicitDisposeIgnoreExceptions();
|
prevBuiltData?.Release();
|
||||||
|
|
||||||
this.buildTask = EmptyTask;
|
this.buildTask = EmptyTask;
|
||||||
fontsAndLocks.EnsureCapacity(data.Substances.Sum(x => x.RelevantHandles.Count));
|
fontsAndLocks.EnsureCapacity(data.Substances.Sum(x => x.RelevantHandles.Count));
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal sealed partial class FontAtlasFactory
|
internal sealed partial class FontAtlasFactory
|
||||||
: IServiceType, GamePrebakedFontHandle.IGameFontTextureProvider, IDisposable
|
: IInternalDisposableService, GamePrebakedFontHandle.IGameFontTextureProvider
|
||||||
{
|
{
|
||||||
private readonly DisposeSafety.ScopedFinalizer scopedFinalizer = new();
|
private readonly DisposeSafety.ScopedFinalizer scopedFinalizer = new();
|
||||||
private readonly CancellationTokenSource cancellationTokenSource = new();
|
private readonly CancellationTokenSource cancellationTokenSource = new();
|
||||||
|
|
@ -161,7 +161,7 @@ internal sealed partial class FontAtlasFactory
|
||||||
this.dalamudAssetManager.IsStreamImmediatelyAvailable(DalamudAsset.LodestoneGameSymbol);
|
this.dalamudAssetManager.IsStreamImmediatelyAvailable(DalamudAsset.LodestoneGameSymbol);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.cancellationTokenSource.Cancel();
|
this.cancellationTokenSource.Cancel();
|
||||||
this.scopedFinalizer.Dispose();
|
this.scopedFinalizer.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
|
|
@ -291,11 +292,15 @@ internal abstract class FontHandle : IFontHandle
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
if (Interlocked.Exchange(ref this.manager, null) is not { } managerToDisassociate)
|
||||||
|
return;
|
||||||
|
|
||||||
if (this.pushedFonts.Count > 0)
|
if (this.pushedFonts.Count > 0)
|
||||||
Log.Warning($"{nameof(IFontHandle)}.{nameof(IDisposable.Dispose)}: fonts were still in a stack.");
|
Log.Warning($"{nameof(IFontHandle)}.{nameof(IDisposable.Dispose)}: fonts were still in a stack.");
|
||||||
this.Manager.FreeFontHandle(this);
|
|
||||||
this.manager = null;
|
managerToDisassociate.FreeFontHandle(this);
|
||||||
this.Disposed?.InvokeSafely();
|
this.Disposed?.InvokeSafely();
|
||||||
|
this.Disposed = null;
|
||||||
this.ImFontChanged = null;
|
this.ImFontChanged = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ internal class TitleScreenMenu : IServiceType, ITitleScreenMenu
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<ITitleScreenMenu>]
|
[ResolveVia<ITitleScreenMenu>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class TitleScreenMenuPluginScoped : IDisposable, IServiceType, ITitleScreenMenu
|
internal class TitleScreenMenuPluginScoped : IInternalDisposableService, ITitleScreenMenu
|
||||||
{
|
{
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly TitleScreenMenu titleScreenMenuService = Service<TitleScreenMenu>.Get();
|
private readonly TitleScreenMenu titleScreenMenuService = Service<TitleScreenMenu>.Get();
|
||||||
|
|
@ -204,7 +204,7 @@ internal class TitleScreenMenuPluginScoped : IDisposable, IServiceType, ITitleSc
|
||||||
public IReadOnlyList<TitleScreenMenuEntry>? Entries => this.titleScreenMenuService.Entries;
|
public IReadOnlyList<TitleScreenMenuEntry>? Entries => this.titleScreenMenuService.Entries;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
foreach (var entry in this.pluginEntries)
|
foreach (var entry in this.pluginEntries)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ using Dalamud.Interface.Internal.ManagedAsserts;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using Dalamud.Interface.ManagedFontAtlas;
|
using Dalamud.Interface.ManagedFontAtlas;
|
||||||
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
@ -605,6 +606,10 @@ public sealed class UiBuilder : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Clean up resources allocated by this instance of <see cref="UiBuilder"/>.</summary>
|
||||||
|
/// <remarks>Dalamud internal use only.</remarks>
|
||||||
|
internal void DisposeInternal() => this.scopedFinalizer.Dispose();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open the registered configuration UI, if it exists.
|
/// Open the registered configuration UI, if it exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,17 @@ internal class ServiceScopeImpl : IServiceScope
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (var createdObject in this.scopeCreatedObjects.OfType<IDisposable>()) createdObject.Dispose();
|
foreach (var createdObject in this.scopeCreatedObjects)
|
||||||
|
{
|
||||||
|
switch (createdObject)
|
||||||
|
{
|
||||||
|
case IInternalDisposableService d:
|
||||||
|
d.DisposeService();
|
||||||
|
break;
|
||||||
|
case IDisposable d:
|
||||||
|
d.Dispose();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Dalamud.Logging.Internal;
|
||||||
/// Class responsible for tracking asynchronous tasks.
|
/// Class responsible for tracking asynchronous tasks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal class TaskTracker : IDisposable, IServiceType
|
internal class TaskTracker : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("TT");
|
private static readonly ModuleLog Log = new("TT");
|
||||||
private static readonly List<TaskInfo> TrackedTasksInternal = new();
|
private static readonly List<TaskInfo> TrackedTasksInternal = new();
|
||||||
|
|
@ -119,7 +119,7 @@ internal class TaskTracker : IDisposable, IServiceType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.scheduleAndStartHook?.Dispose();
|
this.scheduleAndStartHook?.Dispose();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Dalamud.Logging;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IPluginLog>]
|
[ResolveVia<IPluginLog>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable
|
internal class ScopedPluginLogService : IServiceType, IPluginLog
|
||||||
{
|
{
|
||||||
private readonly LocalPlugin localPlugin;
|
private readonly LocalPlugin localPlugin;
|
||||||
|
|
||||||
|
|
@ -53,12 +53,6 @@ internal class ScopedPluginLogService : IServiceType, IPluginLog, IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ILogger Logger { get; }
|
public ILogger Logger { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Fatal(string messageTemplate, params object[] values) =>
|
public void Fatal(string messageTemplate, params object[] values) =>
|
||||||
this.Write(LogEventLevel.Fatal, null, messageTemplate, values);
|
this.Write(LogEventLevel.Fatal, null, messageTemplate, values);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace Dalamud.Networking.Http;
|
||||||
/// awareness.
|
/// awareness.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.BlockingEarlyLoadedService]
|
[ServiceManager.BlockingEarlyLoadedService]
|
||||||
internal class HappyHttpClient : IDisposable, IServiceType
|
internal class HappyHttpClient : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HappyHttpClient"/> class.
|
/// Initializes a new instance of the <see cref="HappyHttpClient"/> class.
|
||||||
|
|
@ -58,7 +58,7 @@ internal class HappyHttpClient : IDisposable, IServiceType
|
||||||
public HappyEyeballsCallback SharedHappyEyeballsCallback { get; }
|
public HappyEyeballsCallback SharedHappyEyeballsCallback { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
void IDisposable.Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.SharedHttpClient.Dispose();
|
this.SharedHttpClient.Dispose();
|
||||||
this.SharedHappyEyeballsCallback.Dispose();
|
this.SharedHappyEyeballsCallback.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -452,26 +452,28 @@ public sealed class DalamudPluginInterface : IDisposable
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="Dispose"/>
|
||||||
/// Unregister your plugin and dispose all references.
|
|
||||||
/// </summary>
|
|
||||||
void IDisposable.Dispose()
|
void IDisposable.Dispose()
|
||||||
{
|
{
|
||||||
this.UiBuilder.ExplicitDispose();
|
|
||||||
Service<ChatGui>.Get().RemoveChatLinkHandler(this.plugin.InternalName);
|
|
||||||
Service<Localization>.Get().LocalizationChanged -= this.OnLocalizationChanged;
|
|
||||||
Service<DalamudConfiguration>.Get().DalamudConfigurationSaved -= this.OnDalamudConfigurationSaved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>This function will do nothing. Dalamud will dispose this object on plugin unload.</summary>
|
||||||
/// Obsolete implicit dispose implementation. Should not be used.
|
[Obsolete("This function will do nothing. Dalamud will dispose this object on plugin unload.", true)]
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Do not dispose \"DalamudPluginInterface\".", true)]
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Unregister the plugin and dispose all references.</summary>
|
||||||
|
/// <remarks>Dalamud internal use only.</remarks>
|
||||||
|
internal void DisposeInternal()
|
||||||
|
{
|
||||||
|
Service<ChatGui>.Get().RemoveChatLinkHandler(this.plugin.InternalName);
|
||||||
|
Service<Localization>.Get().LocalizationChanged -= this.OnLocalizationChanged;
|
||||||
|
Service<DalamudConfiguration>.Get().DalamudConfigurationSaved -= this.OnDalamudConfigurationSaved;
|
||||||
|
this.UiBuilder.DisposeInternal();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dispatch the active plugins changed event.
|
/// Dispatch the active plugins changed event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Dalamud.Plugin.Internal;
|
||||||
[InherentDependency<DataShare>]
|
[InherentDependency<DataShare>]
|
||||||
|
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal partial class PluginManager : IDisposable, IServiceType
|
internal partial class PluginManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default time to wait between plugin unload and plugin assembly unload.
|
/// Default time to wait between plugin unload and plugin assembly unload.
|
||||||
|
|
@ -370,7 +370,7 @@ internal partial class PluginManager : IDisposable, IServiceType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
var disposablePlugins =
|
var disposablePlugins =
|
||||||
this.installedPluginsList.Where(plugin => plugin.State is PluginState.Loaded or PluginState.LoadError).ToArray();
|
this.installedPluginsList.Where(plugin => plugin.State is PluginState.Loaded or PluginState.LoadError).ToArray();
|
||||||
|
|
@ -410,7 +410,16 @@ internal partial class PluginManager : IDisposable, IServiceType
|
||||||
// Now that we've waited enough, dispose the whole plugin.
|
// Now that we've waited enough, dispose the whole plugin.
|
||||||
// Since plugins should have been unloaded above, this should be done quickly.
|
// Since plugins should have been unloaded above, this should be done quickly.
|
||||||
foreach (var plugin in disposablePlugins)
|
foreach (var plugin in disposablePlugins)
|
||||||
plugin.ExplicitDisposeIgnoreExceptions($"Error disposing {plugin.Name}", Log);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
plugin.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e, $"Error disposing {plugin.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.assemblyLocationMonoHook?.Dispose();
|
this.assemblyLocationMonoHook?.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Dalamud.Plugin.Internal.Profiles;
|
||||||
/// Service responsible for profile-related chat commands.
|
/// Service responsible for profile-related chat commands.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal class ProfileCommandHandler : IServiceType, IDisposable
|
internal class ProfileCommandHandler : IInternalDisposableService
|
||||||
{
|
{
|
||||||
private readonly CommandManager cmd;
|
private readonly CommandManager cmd;
|
||||||
private readonly ProfileManager profileManager;
|
private readonly ProfileManager profileManager;
|
||||||
|
|
@ -69,7 +69,7 @@ internal class ProfileCommandHandler : IServiceType, IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
this.cmd.RemoveHandler("/xlenablecollection");
|
this.cmd.RemoveHandler("/xlenablecollection");
|
||||||
this.cmd.RemoveHandler("/xldisablecollection");
|
this.cmd.RemoveHandler("/xldisablecollection");
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ internal class LocalPlugin : IDisposable
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.DalamudInterface?.ExplicitDispose();
|
this.DalamudInterface?.DisposeInternal();
|
||||||
this.DalamudInterface = null;
|
this.DalamudInterface = null;
|
||||||
|
|
||||||
this.ServiceScope?.Dispose();
|
this.ServiceScope?.Dispose();
|
||||||
|
|
@ -426,7 +426,7 @@ internal class LocalPlugin : IDisposable
|
||||||
if (this.instance == null)
|
if (this.instance == null)
|
||||||
{
|
{
|
||||||
this.State = PluginState.LoadError;
|
this.State = PluginState.LoadError;
|
||||||
this.DalamudInterface.ExplicitDispose();
|
this.DalamudInterface.DisposeInternal();
|
||||||
Log.Error(
|
Log.Error(
|
||||||
$"Error while loading {this.Name}, failed to bind and call the plugin constructor");
|
$"Error while loading {this.Name}, failed to bind and call the plugin constructor");
|
||||||
return;
|
return;
|
||||||
|
|
@ -499,7 +499,7 @@ internal class LocalPlugin : IDisposable
|
||||||
|
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
|
|
||||||
this.DalamudInterface?.ExplicitDispose();
|
this.DalamudInterface?.DisposeInternal();
|
||||||
this.DalamudInterface = null;
|
this.DalamudInterface = null;
|
||||||
|
|
||||||
this.ServiceScope?.Dispose();
|
this.ServiceScope?.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
@ -175,7 +176,8 @@ internal static class ServiceManager
|
||||||
foreach (var serviceType in GetConcreteServiceTypes())
|
foreach (var serviceType in GetConcreteServiceTypes())
|
||||||
{
|
{
|
||||||
var serviceKind = serviceType.GetServiceKind();
|
var serviceKind = serviceType.GetServiceKind();
|
||||||
Debug.Assert(serviceKind != ServiceKind.None, $"Service<{serviceType.FullName}> did not specify a kind");
|
|
||||||
|
CheckServiceTypeContracts(serviceType);
|
||||||
|
|
||||||
// Let IoC know about the interfaces this service implements
|
// Let IoC know about the interfaces this service implements
|
||||||
serviceContainer.RegisterInterfaces(serviceType);
|
serviceContainer.RegisterInterfaces(serviceType);
|
||||||
|
|
@ -514,6 +516,44 @@ internal static class ServiceManager
|
||||||
return ServiceKind.ProvidedService;
|
return ServiceKind.ProvidedService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Validate service type contracts, and throws exceptions accordingly.</summary>
|
||||||
|
/// <param name="serviceType">An instance of <see cref="Type"/> that is supposed to be a service type.</param>
|
||||||
|
/// <remarks>Does nothing on non-debug builds.</remarks>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void CheckServiceTypeContracts(Type serviceType)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!serviceType.IsAssignableTo(typeof(IServiceType)))
|
||||||
|
throw new InvalidOperationException($"Non-{nameof(IServiceType)} passed.");
|
||||||
|
if (serviceType.GetServiceKind() == ServiceKind.None)
|
||||||
|
throw new InvalidOperationException("Service type is not specified.");
|
||||||
|
|
||||||
|
var isServiceDisposable =
|
||||||
|
serviceType.IsAssignableTo(typeof(IInternalDisposableService));
|
||||||
|
var isAnyDisposable =
|
||||||
|
isServiceDisposable
|
||||||
|
|| serviceType.IsAssignableTo(typeof(IDisposable))
|
||||||
|
|| serviceType.IsAssignableTo(typeof(IAsyncDisposable));
|
||||||
|
if (isAnyDisposable && !isServiceDisposable)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"A service must be an {nameof(IInternalDisposableService)} without specifying " +
|
||||||
|
$"{nameof(IDisposable)} nor {nameof(IAsyncDisposable)} if it is purely meant to be a service, " +
|
||||||
|
$"or an {nameof(IPublicDisposableService)} if it also is allowed to be constructed not as a " +
|
||||||
|
$"service to be used elsewhere and has to offer {nameof(IDisposable)} or " +
|
||||||
|
$"{nameof(IAsyncDisposable)}. See {nameof(ReliableFileStorage)} for an example of " +
|
||||||
|
$"{nameof(IPublicDisposableService)}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{serviceType.Name}: {e.Message}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that this constructor will be called for early initialization.
|
/// Indicates that this constructor will be called for early initialization.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,12 @@ internal static class Service<T> where T : IServiceType
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Does nothing.</summary>
|
||||||
|
/// <remarks>Used to invoke the static ctor.</remarks>
|
||||||
|
public static void Nop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the type in the service locator to the given object.
|
/// Sets the type in the service locator to the given object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -72,6 +78,8 @@ internal static class Service<T> where T : IServiceType
|
||||||
public static void Provide(T obj)
|
public static void Provide(T obj)
|
||||||
{
|
{
|
||||||
ServiceManager.Log.Debug("Service<{0}>: Provided", typeof(T).Name);
|
ServiceManager.Log.Debug("Service<{0}>: Provided", typeof(T).Name);
|
||||||
|
if (obj is IPublicDisposableService pds)
|
||||||
|
pds.MarkDisposeOnlyFromService();
|
||||||
instanceTcs.SetResult(obj);
|
instanceTcs.SetResult(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,23 +305,26 @@ internal static class Service<T> where T : IServiceType
|
||||||
if (!instanceTcs.Task.IsCompletedSuccessfully)
|
if (!instanceTcs.Task.IsCompletedSuccessfully)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var instance = instanceTcs.Task.Result;
|
switch (instanceTcs.Task.Result)
|
||||||
if (instance is IDisposable disposable)
|
|
||||||
{
|
{
|
||||||
ServiceManager.Log.Debug("Service<{0}>: Disposing", typeof(T).Name);
|
case IInternalDisposableService d:
|
||||||
try
|
ServiceManager.Log.Debug("Service<{0}>: Disposing", typeof(T).Name);
|
||||||
{
|
try
|
||||||
disposable.Dispose();
|
{
|
||||||
ServiceManager.Log.Debug("Service<{0}>: Disposed", typeof(T).Name);
|
d.DisposeService();
|
||||||
}
|
ServiceManager.Log.Debug("Service<{0}>: Disposed", typeof(T).Name);
|
||||||
catch (Exception e)
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
ServiceManager.Log.Warning(e, "Service<{0}>: Dispose failure", typeof(T).Name);
|
{
|
||||||
}
|
ServiceManager.Log.Warning(e, "Service<{0}>: Dispose failure", typeof(T).Name);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
break;
|
||||||
ServiceManager.Log.Debug("Service<{0}>: Unset", typeof(T).Name);
|
|
||||||
|
default:
|
||||||
|
ServiceManager.CheckServiceTypeContracts(typeof(T));
|
||||||
|
ServiceManager.Log.Debug("Service<{0}>: Unset", typeof(T).Name);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceTcs = new TaskCompletionSource<T>();
|
instanceTcs = new TaskCompletionSource<T>();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Storage.Assets;
|
||||||
#pragma warning disable SA1015
|
#pragma warning disable SA1015
|
||||||
[ResolveVia<IDalamudAssetManager>]
|
[ResolveVia<IDalamudAssetManager>]
|
||||||
#pragma warning restore SA1015
|
#pragma warning restore SA1015
|
||||||
internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudAssetManager
|
internal sealed class DalamudAssetManager : IInternalDisposableService, IDalamudAssetManager
|
||||||
{
|
{
|
||||||
private const int DownloadAttemptCount = 10;
|
private const int DownloadAttemptCount = 10;
|
||||||
private const int RenameAttemptCount = 10;
|
private const int RenameAttemptCount = 10;
|
||||||
|
|
@ -67,7 +67,13 @@ internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudA
|
||||||
.Where(x => x.GetAttribute<DalamudAssetAttribute>()?.Required is true)
|
.Where(x => x.GetAttribute<DalamudAssetAttribute>()?.Required is true)
|
||||||
.Select(this.CreateStreamAsync)
|
.Select(this.CreateStreamAsync)
|
||||||
.Select(x => x.ToContentDisposedTask()))
|
.Select(x => x.ToContentDisposedTask()))
|
||||||
.ContinueWith(_ => loadTimings.Dispose()),
|
.ContinueWith(
|
||||||
|
r =>
|
||||||
|
{
|
||||||
|
loadTimings.Dispose();
|
||||||
|
return r;
|
||||||
|
})
|
||||||
|
.Unwrap(),
|
||||||
"Prevent Dalamud from loading more stuff, until we've ensured that all required assets are available.");
|
"Prevent Dalamud from loading more stuff, until we've ensured that all required assets are available.");
|
||||||
|
|
||||||
Task.WhenAll(
|
Task.WhenAll(
|
||||||
|
|
@ -83,7 +89,7 @@ internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudA
|
||||||
public IDalamudTextureWrap Empty4X4 => this.GetDalamudTextureWrap(DalamudAsset.Empty4X4);
|
public IDalamudTextureWrap Empty4X4 => this.GetDalamudTextureWrap(DalamudAsset.Empty4X4);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
void IInternalDisposableService.DisposeService()
|
||||||
{
|
{
|
||||||
lock (this.syncRoot)
|
lock (this.syncRoot)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,22 @@ namespace Dalamud.Storage;
|
||||||
/// This is not an early-loaded service, as it is needed before they are initialized.
|
/// This is not an early-loaded service, as it is needed before they are initialized.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[ServiceManager.ProvidedService]
|
[ServiceManager.ProvidedService]
|
||||||
public class ReliableFileStorage : IServiceType, IDisposable
|
[Api10ToDo("Make internal and IInternalDisposableService, and remove #pragma guard from the caller.")]
|
||||||
|
public class ReliableFileStorage : IPublicDisposableService
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("VFS");
|
private static readonly ModuleLog Log = new("VFS");
|
||||||
|
|
||||||
private readonly object syncRoot = new();
|
private readonly object syncRoot = new();
|
||||||
|
|
||||||
private SQLiteConnection? db;
|
private SQLiteConnection? db;
|
||||||
|
private bool isService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ReliableFileStorage"/> class.
|
/// Initializes a new instance of the <see cref="ReliableFileStorage"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vfsDbPath">Path to the VFS.</param>
|
/// <param name="vfsDbPath">Path to the VFS.</param>
|
||||||
|
[Obsolete("Dalamud internal use only.", false)]
|
||||||
|
[Api10ToDo("Make internal, and remove #pragma guard from the caller.")]
|
||||||
public ReliableFileStorage(string vfsDbPath)
|
public ReliableFileStorage(string vfsDbPath)
|
||||||
{
|
{
|
||||||
var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db");
|
var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db");
|
||||||
|
|
@ -60,7 +65,7 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a file exists.
|
/// Check if a file exists.
|
||||||
/// This will return true if the file does not exist on the filesystem, but in the transparent backup.
|
/// This will return true if the file does not exist on the filesystem, but in the transparent backup.
|
||||||
|
|
@ -288,9 +293,20 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.db?.Dispose();
|
if (!this.isService)
|
||||||
|
this.DisposeCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IInternalDisposableService.DisposeService()
|
||||||
|
{
|
||||||
|
if (this.isService)
|
||||||
|
this.DisposeCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
void IPublicDisposableService.MarkDisposeOnlyFromService() => this.isService = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replace possible non-portable parts of a path with portable versions.
|
/// Replace possible non-portable parts of a path with portable versions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -312,6 +328,8 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
||||||
this.db.CreateTable<DbFile>();
|
this.db.CreateTable<DbFile>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DisposeCore() => this.db?.Dispose();
|
||||||
|
|
||||||
private class DbFile
|
private class DbFile
|
||||||
{
|
{
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,16 @@ public static class DisposeSafety
|
||||||
r =>
|
r =>
|
||||||
{
|
{
|
||||||
if (!r.IsCompletedSuccessfully)
|
if (!r.IsCompletedSuccessfully)
|
||||||
return ignoreAllExceptions ? Task.CompletedTask : r;
|
{
|
||||||
|
if (ignoreAllExceptions)
|
||||||
|
{
|
||||||
|
_ = r.Exception;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
r.Result.Dispose();
|
r.Result.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Logging.Internal;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
@ -638,42 +637,6 @@ public static class Util
|
||||||
if (!Windows.Win32.PInvoke.MoveFileEx(tempPath, path, MOVE_FILE_FLAGS.MOVEFILE_REPLACE_EXISTING | MOVE_FILE_FLAGS.MOVEFILE_WRITE_THROUGH))
|
if (!Windows.Win32.PInvoke.MoveFileEx(tempPath, path, MOVE_FILE_FLAGS.MOVEFILE_REPLACE_EXISTING | MOVE_FILE_FLAGS.MOVEFILE_WRITE_THROUGH))
|
||||||
throw new Win32Exception();
|
throw new Win32Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to dispose.</param>
|
|
||||||
/// <typeparam name="T">The type of object to dispose.</typeparam>
|
|
||||||
internal static void ExplicitDispose<T>(this T obj) where T : IDisposable
|
|
||||||
{
|
|
||||||
obj.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to dispose.</param>
|
|
||||||
/// <param name="logMessage">Log message to print, if specified and an error occurs.</param>
|
|
||||||
/// <param name="moduleLog">Module logger, if any.</param>
|
|
||||||
/// <typeparam name="T">The type of object to dispose.</typeparam>
|
|
||||||
internal static void ExplicitDisposeIgnoreExceptions<T>(
|
|
||||||
this T obj, string? logMessage = null, ModuleLog? moduleLog = null) where T : IDisposable
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
obj.Dispose();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (logMessage == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (moduleLog != null)
|
|
||||||
moduleLog.Error(e, logMessage);
|
|
||||||
else
|
|
||||||
Log.Error(e, logMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a random, inoffensive, human-friendly string.
|
/// Gets a random, inoffensive, human-friendly string.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue