Fix doubled hook.

This commit is contained in:
Ottermandias 2024-06-22 23:04:09 +02:00
parent 045abc787d
commit b07af32dee
3 changed files with 23 additions and 41 deletions

View file

@ -3,6 +3,7 @@ using OtterGui.Classes;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.UI.ResourceWatcher;
namespace Penumbra.Interop.Hooks.Resources; namespace Penumbra.Interop.Hooks.Resources;
@ -15,6 +16,9 @@ public sealed unsafe class ResourceHandleDestructor : EventWrapperPtr<ResourceHa
/// <seealso cref="ShaderReplacementFixer"/> /// <seealso cref="ShaderReplacementFixer"/>
ShaderReplacementFixer, ShaderReplacementFixer,
/// <seealso cref="ResourceWatcher.OnResourceDestroyed"/>
ResourceWatcher,
} }
public ResourceHandleDestructor(HookManager hooks) public ResourceHandleDestructor(HookManager hooks)

View file

@ -26,7 +26,6 @@ public unsafe class ResourceService : IDisposable, IRequiredService
interop.InitializeFromAttributes(this); interop.InitializeFromAttributes(this);
_getResourceSyncHook.Enable(); _getResourceSyncHook.Enable();
_getResourceAsyncHook.Enable(); _getResourceAsyncHook.Enable();
_resourceHandleDestructorHook.Enable();
_incRefHook = interop.HookFromAddress<ResourceHandlePrototype>( _incRefHook = interop.HookFromAddress<ResourceHandlePrototype>(
(nint)CSResourceHandle.MemberFunctionPointers.IncRef, (nint)CSResourceHandle.MemberFunctionPointers.IncRef,
ResourceHandleIncRefDetour); ResourceHandleIncRefDetour);
@ -51,7 +50,6 @@ public unsafe class ResourceService : IDisposable, IRequiredService
{ {
_getResourceSyncHook.Dispose(); _getResourceSyncHook.Dispose();
_getResourceAsyncHook.Dispose(); _getResourceAsyncHook.Dispose();
_resourceHandleDestructorHook.Dispose();
_incRefHook.Dispose(); _incRefHook.Dispose();
_decRefHook.Dispose(); _decRefHook.Dispose();
} }
@ -67,8 +65,7 @@ public unsafe class ResourceService : IDisposable, IRequiredService
/// <param name="sync">Whether to request the resource synchronously or asynchronously.</param> /// <param name="sync">Whether to request the resource synchronously or asynchronously.</param>
/// <param name="returnValue">The returned resource handle. If this is not null, calling original will be skipped. </param> /// <param name="returnValue">The returned resource handle. If this is not null, calling original will be skipped. </param>
public delegate void GetResourcePreDelegate(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path, public delegate void GetResourcePreDelegate(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path,
Utf8GamePath original, Utf8GamePath original, GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue);
GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue);
/// <summary> <inheritdoc cref="GetResourcePreDelegate"/> <para/> /// <summary> <inheritdoc cref="GetResourcePreDelegate"/> <para/>
/// Subscribers should be exception-safe.</summary> /// Subscribers should be exception-safe.</summary>
@ -192,27 +189,4 @@ public unsafe class ResourceService : IDisposable, IRequiredService
} }
#endregion #endregion
#region Destructor
/// <summary> Invoked before a resource handle is destructed. </summary>
/// <param name="handle">The resource handle.</param>
public delegate void ResourceHandleDtorDelegate(ResourceHandle* handle);
/// <summary>
/// <inheritdoc cref="ResourceHandleDtorDelegate"/> <para/>
/// Subscribers should be exception-safe.
/// </summary>
public event ResourceHandleDtorDelegate? ResourceHandleDestructor;
[Signature(Sigs.ResourceHandleDestructor, DetourName = nameof(ResourceHandleDestructorDetour))]
private readonly Hook<ResourceHandlePrototype> _resourceHandleDestructorHook = null!;
private nint ResourceHandleDestructorDetour(ResourceHandle* handle)
{
ResourceHandleDestructor?.Invoke(handle);
return _resourceHandleDestructorHook.OriginalDisposeSafe(handle);
}
#endregion
} }

View file

@ -8,8 +8,10 @@ using Penumbra.Api.Enums;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.Interop.Hooks.Resources;
using Penumbra.Interop.ResourceLoading; using Penumbra.Interop.ResourceLoading;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Services;
using Penumbra.String; using Penumbra.String;
using Penumbra.String.Classes; using Penumbra.String.Classes;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
@ -21,28 +23,30 @@ public sealed class ResourceWatcher : IDisposable, ITab, IUiService
public const int DefaultMaxEntries = 1024; public const int DefaultMaxEntries = 1024;
public const RecordType AllRecords = RecordType.Request | RecordType.ResourceLoad | RecordType.FileLoad | RecordType.Destruction; public const RecordType AllRecords = RecordType.Request | RecordType.ResourceLoad | RecordType.FileLoad | RecordType.Destruction;
private readonly Configuration _config; private readonly Configuration _config;
private readonly EphemeralConfig _ephemeral; private readonly EphemeralConfig _ephemeral;
private readonly ResourceService _resources; private readonly ResourceService _resources;
private readonly ResourceLoader _loader; private readonly ResourceLoader _loader;
private readonly ActorManager _actors; private readonly ResourceHandleDestructor _destructor;
private readonly List<Record> _records = []; private readonly ActorManager _actors;
private readonly ConcurrentQueue<Record> _newRecords = []; private readonly List<Record> _records = [];
private readonly ResourceWatcherTable _table; private readonly ConcurrentQueue<Record> _newRecords = [];
private string _logFilter = string.Empty; private readonly ResourceWatcherTable _table;
private Regex? _logRegex; private string _logFilter = string.Empty;
private int _newMaxEntries; private Regex? _logRegex;
private int _newMaxEntries;
public unsafe ResourceWatcher(ActorManager actors, Configuration config, ResourceService resources, ResourceLoader loader) public unsafe ResourceWatcher(ActorManager actors, Configuration config, ResourceService resources, ResourceLoader loader, ResourceHandleDestructor destructor)
{ {
_actors = actors; _actors = actors;
_config = config; _config = config;
_ephemeral = config.Ephemeral; _ephemeral = config.Ephemeral;
_resources = resources; _resources = resources;
_destructor = destructor;
_loader = loader; _loader = loader;
_table = new ResourceWatcherTable(config.Ephemeral, _records); _table = new ResourceWatcherTable(config.Ephemeral, _records);
_resources.ResourceRequested += OnResourceRequested; _resources.ResourceRequested += OnResourceRequested;
_resources.ResourceHandleDestructor += OnResourceDestroyed; _destructor.Subscribe(OnResourceDestroyed, ResourceHandleDestructor.Priority.ResourceWatcher);
_loader.ResourceLoaded += OnResourceLoaded; _loader.ResourceLoaded += OnResourceLoaded;
_loader.FileLoaded += OnFileLoaded; _loader.FileLoaded += OnFileLoaded;
UpdateFilter(_ephemeral.ResourceLoggingFilter, false); UpdateFilter(_ephemeral.ResourceLoggingFilter, false);
@ -54,7 +58,7 @@ public sealed class ResourceWatcher : IDisposable, ITab, IUiService
Clear(); Clear();
_records.TrimExcess(); _records.TrimExcess();
_resources.ResourceRequested -= OnResourceRequested; _resources.ResourceRequested -= OnResourceRequested;
_resources.ResourceHandleDestructor -= OnResourceDestroyed; _destructor.Unsubscribe(OnResourceDestroyed);
_loader.ResourceLoaded -= OnResourceLoaded; _loader.ResourceLoaded -= OnResourceLoaded;
_loader.FileLoaded -= OnFileLoaded; _loader.FileLoaded -= OnFileLoaded;
} }