Hook UpdateRender despite per-frame calls.

This commit is contained in:
Ottermandias 2024-07-17 18:34:03 +02:00
parent 9bba1e2b31
commit 5abbd8b110
3 changed files with 6 additions and 48 deletions

@ -1 +1 @@
Subproject commit 94df458dfb2a704a611fa77d955808284aeb23ac Subproject commit c5ad1f3ae9818baa446327bdcf49fac65088c703

View file

@ -1,37 +0,0 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Services;
using Penumbra.Collections;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
namespace Penumbra.Interop.Hooks.Meta;
public sealed unsafe class GetEqpIndirect : FastHook<GetEqpIndirect.Delegate>
{
private readonly CollectionResolver _collectionResolver;
private readonly MetaState _metaState;
public GetEqpIndirect(HookManager hooks, CollectionResolver collectionResolver, MetaState metaState)
{
_collectionResolver = collectionResolver;
_metaState = metaState;
Task = hooks.CreateHook<Delegate>("Get EQP Indirect", Sigs.GetEqpIndirect, Detour, HookSettings.MetaParentHooks);
}
public delegate void Delegate(DrawObject* drawObject);
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void Detour(DrawObject* drawObject)
{
// Shortcut because this is also called all the time.
// Same thing is checked at the beginning of the original function.
if ((*(byte*)((nint)drawObject + Offsets.GetEqpIndirectSkip1) & 1) == 0 || *(ulong*)((nint)drawObject + Offsets.GetEqpIndirectSkip2) == 0)
return;
Penumbra.Log.Excessive($"[Get EQP Indirect] Invoked on {(nint)drawObject:X}.");
var collection = _collectionResolver.IdentifyCollection(drawObject, true);
_metaState.EqpCollection.Push(collection);
Task.Result.Original(drawObject);
_metaState.EqpCollection.Pop();
}
}

View file

@ -1,20 +1,20 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving; using Penumbra.Interop.PathResolving;
namespace Penumbra.Interop.Hooks.Meta; namespace Penumbra.Interop.Hooks.Meta;
public sealed unsafe class GetEqpIndirect2 : FastHook<GetEqpIndirect2.Delegate> /// <summary> The actual function is inlined, so we need to hook its only callsite: Human.UpdateRender instead. </summary>
public sealed unsafe class UpdateRender : FastHook<UpdateRender.Delegate>
{ {
private readonly CollectionResolver _collectionResolver; private readonly CollectionResolver _collectionResolver;
private readonly MetaState _metaState; private readonly MetaState _metaState;
public GetEqpIndirect2(HookManager hooks, CollectionResolver collectionResolver, MetaState metaState) public UpdateRender(HookManager hooks, CollectionResolver collectionResolver, MetaState metaState, CharacterBaseVTables vTables)
{ {
_collectionResolver = collectionResolver; _collectionResolver = collectionResolver;
_metaState = metaState; _metaState = metaState;
Task = hooks.CreateHook<Delegate>("Get EQP Indirect 2", Sigs.GetEqpIndirect2, Detour, HookSettings.MetaParentHooks); Task = hooks.CreateHook<Delegate>("Human.UpdateRender", vTables.HumanVTable[4], Detour, HookSettings.MetaParentHooks);
} }
public delegate void Delegate(DrawObject* drawObject); public delegate void Delegate(DrawObject* drawObject);
@ -22,12 +22,7 @@ public sealed unsafe class GetEqpIndirect2 : FastHook<GetEqpIndirect2.Delegate>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void Detour(DrawObject* drawObject) private void Detour(DrawObject* drawObject)
{ {
// Shortcut because this is also called all the time. Penumbra.Log.Excessive($"[Human.UpdateRender] Invoked on {(nint)drawObject:X}.");
// Same thing is checked at the beginning of the original function.
if (((*(uint*)((nint)drawObject + Offsets.GetEqpIndirect2Skip) >> 0x12) & 1) == 0)
return;
Penumbra.Log.Excessive($"[Get EQP Indirect 2] Invoked on {(nint)drawObject:X}.");
var collection = _collectionResolver.IdentifyCollection(drawObject, true); var collection = _collectionResolver.IdentifyCollection(drawObject, true);
_metaState.EqpCollection.Push(collection); _metaState.EqpCollection.Push(collection);
Task.Result.Original(drawObject); Task.Result.Original(drawObject);