Add crash handler stuff.

This commit is contained in:
Ottermandias 2024-03-16 16:20:34 +01:00
parent 9ba6e4d0af
commit e08e9c4d13
35 changed files with 1472 additions and 237 deletions

View file

@ -2,21 +2,25 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Services;
using Penumbra.Collections;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Called for some sound effects caused by animations or VFX. </summary>
public sealed unsafe class ApricotListenerSoundPlay : FastHook<ApricotListenerSoundPlay.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly CrashHandlerService _crashHandler;
public ApricotListenerSoundPlay(HookManager hooks, GameState state, CollectionResolver collectionResolver)
public ApricotListenerSoundPlay(HookManager hooks, GameState state, CollectionResolver collectionResolver, CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Apricot Listener Sound Play", Sigs.ApricotListenerSoundPlay, Detour, true);
}
@ -46,6 +50,7 @@ public sealed unsafe class ApricotListenerSoundPlay : FastHook<ApricotListenerSo
newData = _collectionResolver.IdentifyCollection(drawObject, true);
}
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.ApricotSoundPlay);
var last = _state.SetAnimationData(newData);
var ret = Task.Result.Original(a1, a2, a3, a4, a5, a6);
_state.RestoreAnimationData(last);

View file

@ -1,8 +1,10 @@
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Services;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
@ -12,16 +14,18 @@ namespace Penumbra.Interop.Hooks.Animation;
/// </summary>
public sealed unsafe class CharacterBaseLoadAnimation : FastHook<CharacterBaseLoadAnimation.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly DrawObjectState _drawObjectState;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly DrawObjectState _drawObjectState;
private readonly CrashHandlerService _crashHandler;
public CharacterBaseLoadAnimation(HookManager hooks, GameState state, CollectionResolver collectionResolver,
DrawObjectState drawObjectState)
DrawObjectState drawObjectState, CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_drawObjectState = drawObjectState;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("CharacterBase Load Animation", Sigs.CharacterBaseLoadAnimation, Detour, true);
}
@ -33,7 +37,9 @@ public sealed unsafe class CharacterBaseLoadAnimation : FastHook<CharacterBaseLo
var lastObj = _state.LastGameObject;
if (lastObj == nint.Zero && _drawObjectState.TryGetValue((nint)drawObject, out var p))
lastObj = p.Item1;
var last = _state.SetAnimationData(_collectionResolver.IdentifyCollection((GameObject*)lastObj, true));
var data = _collectionResolver.IdentifyCollection((GameObject*)lastObj, true);
var last = _state.SetAnimationData(data);
_crashHandler.LogAnimation(data.AssociatedGameObject, data.ModCollection, AnimationInvocationType.CharacterBaseLoadAnimation);
Penumbra.Log.Excessive($"[CharacterBase Load Animation] Invoked on {(nint)drawObject:X}");
Task.Result.Original(drawObject);
_state.RestoreAnimationData(last);

View file

@ -1,21 +1,25 @@
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.Collections;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Load a ground-based area VFX. </summary>
public sealed unsafe class LoadAreaVfx : FastHook<LoadAreaVfx.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly CrashHandlerService _crashHandler;
public LoadAreaVfx(HookManager hooks, GameState state, CollectionResolver collectionResolver)
public LoadAreaVfx(HookManager hooks, GameState state, CollectionResolver collectionResolver, CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Load Area VFX", Sigs.LoadAreaVfx, Detour, true);
}
@ -25,10 +29,11 @@ public sealed unsafe class LoadAreaVfx : FastHook<LoadAreaVfx.Delegate>
private nint Detour(uint vfxId, float* pos, GameObject* caster, float unk1, float unk2, byte unk3)
{
var newData = caster != null
? _collectionResolver.IdentifyCollection(caster, true)
: ResolveData.Invalid;
? _collectionResolver.IdentifyCollection(caster, true)
: ResolveData.Invalid;
var last = _state.SetAnimationData(newData);
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.LoadAreaVfx);
var ret = Task.Result.Original(vfxId, pos, caster, unk1, unk2, unk3);
Penumbra.Log.Excessive(
$"[Load Area VFX] Invoked with {vfxId}, [{pos[0]} {pos[1]} {pos[2]}], 0x{(nint)caster:X}, {unk1}, {unk2}, {unk3} -> 0x{ret:X}.");

View file

@ -1,19 +1,23 @@
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.CrashHandler.Buffers;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Characters load some of their voice lines or whatever with this function. </summary>
public sealed unsafe class LoadCharacterSound : FastHook<LoadCharacterSound.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly CrashHandlerService _crashHandler;
public LoadCharacterSound(HookManager hooks, GameState state, CollectionResolver collectionResolver)
public LoadCharacterSound(HookManager hooks, GameState state, CollectionResolver collectionResolver, CrashHandlerService crashHandler)
{
_state = state;
_state = state;
_collectionResolver = collectionResolver;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Load Character Sound",
(nint)FFXIVClientStructs.FFXIV.Client.Game.Character.Character.VfxContainer.MemberFunctionPointers.LoadCharacterSound, Detour,
true);
@ -25,7 +29,9 @@ public sealed unsafe class LoadCharacterSound : FastHook<LoadCharacterSound.Dele
private nint Detour(nint container, int unk1, int unk2, nint unk3, ulong unk4, int unk5, int unk6, ulong unk7)
{
var character = *(GameObject**)(container + 8);
var last = _state.SetSoundData(_collectionResolver.IdentifyCollection(character, true));
var newData = _collectionResolver.IdentifyCollection(character, true);
var last = _state.SetSoundData(newData);
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.LoadCharacterSound);
var ret = Task.Result.Original(container, unk1, unk2, unk3, unk4, unk5, unk6, unk7);
Penumbra.Log.Excessive($"[Load Character Sound] Invoked with {container:X} {unk1} {unk2} {unk3} {unk4} {unk5} {unk6} {unk7} -> {ret}.");
_state.RestoreSoundData(last);

View file

@ -2,9 +2,11 @@ using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.Collections;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Interop.Structs;
using Penumbra.Services;
using Penumbra.String;
namespace Penumbra.Interop.Hooks.Animation;
@ -12,15 +14,18 @@ namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Load a VFX specifically for a character. </summary>
public sealed unsafe class LoadCharacterVfx : FastHook<LoadCharacterVfx.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly CrashHandlerService _crashHandler;
public LoadCharacterVfx(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects)
public LoadCharacterVfx(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects,
CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_objects = objects;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Load Character VFX", Sigs.LoadCharacterVfx, Detour, true);
}
@ -45,6 +50,7 @@ public sealed unsafe class LoadCharacterVfx : FastHook<LoadCharacterVfx.Delegate
}
var last = _state.SetAnimationData(newData);
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.LoadCharacterVfx);
var ret = Task.Result.Original(vfxPath, vfxParams, unk1, unk2, unk3, unk4);
Penumbra.Log.Excessive(
$"[Load Character VFX] Invoked with {new ByteString(vfxPath)}, 0x{vfxParams->GameObjectId:X}, {vfxParams->TargetCount}, {unk1}, {unk2}, {unk3}, {unk4} -> 0x{ret:X}.");

View file

@ -3,8 +3,10 @@ using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.Collections;
using Penumbra.CrashHandler;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
@ -14,19 +16,21 @@ namespace Penumbra.Interop.Hooks.Animation;
/// </summary>
public sealed unsafe class LoadTimelineResources : FastHook<LoadTimelineResources.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly ICondition _conditions;
private readonly IObjectTable _objects;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly ICondition _conditions;
private readonly IObjectTable _objects;
private readonly CrashHandlerService _crashHandler;
public LoadTimelineResources(HookManager hooks, GameState state, CollectionResolver collectionResolver, ICondition conditions,
IObjectTable objects)
IObjectTable objects, CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_conditions = conditions;
_objects = objects;
Task = hooks.CreateHook<Delegate>("Load Timeline Resources", Sigs.LoadTimelineResources, Detour, true);
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Load Timeline Resources", Sigs.LoadTimelineResources, Detour, true);
}
public delegate ulong Delegate(nint timeline);
@ -39,7 +43,13 @@ public sealed unsafe class LoadTimelineResources : FastHook<LoadTimelineResource
if (_conditions[ConditionFlag.OccupiedInCutSceneEvent] || _conditions[ConditionFlag.WatchingCutscene78])
return Task.Result.Original(timeline);
var last = _state.SetAnimationData(GetDataFromTimeline(_objects, _collectionResolver, timeline));
var newData = GetDataFromTimeline(_objects, _collectionResolver, timeline);
var last = _state.SetAnimationData(newData);
#if false
// This is called far too often and spams the log too much.
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.LoadTimelineResources);
#endif
var ret = Task.Result.Original(timeline);
_state.RestoreAnimationData(last);
return ret;

View file

@ -1,23 +1,28 @@
using Dalamud.Plugin.Services;
using OtterGui.Services;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Interop.Structs;
namespace Penumbra.Interop.Hooks.Animation;
using OtterGui.Services;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Interop.Structs;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Called when some action timelines update. </summary>
public sealed unsafe class ScheduleClipUpdate : FastHook<ScheduleClipUpdate.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly CrashHandlerService _crashHandler;
public ScheduleClipUpdate(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects)
public ScheduleClipUpdate(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects,
CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_objects = objects;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Schedule Clip Update", Sigs.ScheduleClipUpdate, Detour, true);
}
@ -27,8 +32,9 @@ public sealed unsafe class ScheduleClipUpdate : FastHook<ScheduleClipUpdate.Dele
private void Detour(ClipScheduler* clipScheduler)
{
Penumbra.Log.Excessive($"[Schedule Clip Update] Invoked on {(nint)clipScheduler:X}.");
var last = _state.SetAnimationData(
LoadTimelineResources.GetDataFromTimeline(_objects, _collectionResolver, clipScheduler->SchedulerTimeline));
var newData = LoadTimelineResources.GetDataFromTimeline(_objects, _collectionResolver, clipScheduler->SchedulerTimeline);
var last = _state.SetAnimationData(newData);
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.ScheduleClipUpdate);
Task.Result.Original(clipScheduler);
_state.RestoreAnimationData(last);
}

View file

@ -1,21 +1,25 @@
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.GameData;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Seems to load character actions when zoning or changing class, maybe. </summary>
public sealed unsafe class SomeActionLoad : FastHook<SomeActionLoad.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly CrashHandlerService _crashHandler;
public SomeActionLoad(HookManager hooks, GameState state, CollectionResolver collectionResolver)
public SomeActionLoad(HookManager hooks, GameState state, CollectionResolver collectionResolver, CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Some Action Load", Sigs.LoadSomeAction, Detour, true);
}
@ -24,8 +28,10 @@ public sealed unsafe class SomeActionLoad : FastHook<SomeActionLoad.Delegate>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void Detour(ActionTimelineManager* timelineManager)
{
var last = _state.SetAnimationData(_collectionResolver.IdentifyCollection((GameObject*)timelineManager->Parent, true));
var newData = _collectionResolver.IdentifyCollection((GameObject*)timelineManager->Parent, true);
var last = _state.SetAnimationData(newData);
Penumbra.Log.Excessive($"[Some Action Load] Invoked on 0x{(nint)timelineManager:X}.");
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.ActionLoad);
Task.Result.Original(timelineManager);
_state.RestoreAnimationData(last);
}

View file

@ -1,23 +1,28 @@
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using OtterGui.Services;
using Penumbra.CrashHandler.Buffers;
using Penumbra.GameData;
using Penumbra.Interop.PathResolving;
using Penumbra.Services;
namespace Penumbra.Interop.Hooks.Animation;
/// <summary> Unknown what exactly this is, but it seems to load a bunch of paps. </summary>
public sealed unsafe class SomePapLoad : FastHook<SomePapLoad.Delegate>
{
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly GameState _state;
private readonly CollectionResolver _collectionResolver;
private readonly IObjectTable _objects;
private readonly CrashHandlerService _crashHandler;
public SomePapLoad(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects)
public SomePapLoad(HookManager hooks, GameState state, CollectionResolver collectionResolver, IObjectTable objects,
CrashHandlerService crashHandler)
{
_state = state;
_collectionResolver = collectionResolver;
_objects = objects;
_crashHandler = crashHandler;
Task = hooks.CreateHook<Delegate>("Some PAP Load", Sigs.LoadSomePap, Detour, true);
}
@ -33,8 +38,9 @@ public sealed unsafe class SomePapLoad : FastHook<SomePapLoad.Delegate>
var actorIdx = (int)(*(*(ulong**)timelinePtr + 1) >> 3);
if (actorIdx >= 0 && actorIdx < _objects.Length)
{
var last = _state.SetAnimationData(_collectionResolver.IdentifyCollection((GameObject*)_objects.GetObjectAddress(actorIdx),
true));
var newData = _collectionResolver.IdentifyCollection((GameObject*)_objects.GetObjectAddress(actorIdx), true);
var last = _state.SetAnimationData(newData);
_crashHandler.LogAnimation(newData.AssociatedGameObject, newData.ModCollection, AnimationInvocationType.PapLoad);
Task.Result.Original(a1, a2, a3, a4);
_state.RestoreAnimationData(last);
return;