Add very thurough exception handling

This commit is contained in:
MidoriKami 2025-12-07 16:45:59 -08:00
parent 45366efd9f
commit 2dbae05522

View file

@ -135,27 +135,46 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
private AtkEventListener* OnAddonDestructor(AtkUnitBase* thisPtr, byte freeFlags) private AtkEventListener* OnAddonDestructor(AtkUnitBase* thisPtr, byte freeFlags)
{
AtkEventListener* result = null;
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
var result = this.originalVirtualTable->Dtor(thisPtr, freeFlags); try
{
result = this.originalVirtualTable->Dtor(thisPtr, freeFlags);
}
catch (Exception e)
{
Log.Error(e, "Caught exception when calling original Addon Dtor. This may be a bug in the game or another plugin hooking this method.");
}
if ((freeFlags & 1) == 1) if ((freeFlags & 1) == 1)
{ {
IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount); IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount);
AddonLifecycle.AllocatedTables.Remove(this); AddonLifecycle.AllocatedTables.Remove(this);
} }
}
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonDestructor.");
}
return result; return result;
} }
private void OnAddonSetup(AtkUnitBase* addon, uint valueCount, AtkValue* values) private void OnAddonSetup(AtkUnitBase* addon, uint valueCount, AtkValue* values)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.setupArgs.Addon = addon; this.setupArgs.Addon = addon;
this.setupArgs.AtkValueCount = valueCount; this.setupArgs.AtkValueCount = valueCount;
this.setupArgs.AtkValues = (nint)values; this.setupArgs.AtkValues = (nint)values;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreSetup, this.setupArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreSetup, this.setupArgs);
valueCount = this.setupArgs.AtkValueCount; valueCount = this.setupArgs.AtkValueCount;
@ -167,17 +186,25 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonSetup. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnSetup. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostSetup, this.setupArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostSetup, this.setupArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonSetup.");
}
}
private void OnAddonFinalize(AtkUnitBase* thisPtr) private void OnAddonFinalize(AtkUnitBase* thisPtr)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.finalizeArgs.Addon = thisPtr; this.finalizeArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreFinalize, this.finalizeArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreFinalize, this.finalizeArgs);
try try
@ -186,15 +213,23 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonFinalize. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Finalizer. This may be a bug in the game or another plugin hooking this method.");
}
}
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonFinalize.");
} }
} }
private void OnAddonDraw(AtkUnitBase* addon) private void OnAddonDraw(AtkUnitBase* addon)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.drawArgs.Addon = addon; this.drawArgs.Addon = addon;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreDraw, this.drawArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreDraw, this.drawArgs);
try try
@ -203,21 +238,30 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonDraw. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Draw. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostDraw, this.drawArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostDraw, this.drawArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonDraw.");
}
}
private void OnAddonUpdate(AtkUnitBase* addon, float delta) private void OnAddonUpdate(AtkUnitBase* addon, float delta)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.updateArgs.Addon = addon; this.updateArgs.Addon = addon;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreUpdate, this.updateArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreUpdate, this.updateArgs);
// Note: Do not pass or allow manipulation of delta. // Note: Do not pass or allow manipulation of delta.
// It's realistically not something that should be needed. // It's realistically not something that should be needed.
// And even if someone does, they are encouraged to hook Update themselves.
try try
{ {
@ -225,21 +269,29 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonUpdate. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Update. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostUpdate, this.updateArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostUpdate, this.updateArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonUpdate.");
}
}
private bool OnAddonRefresh(AtkUnitBase* addon, uint valueCount, AtkValue* values) private bool OnAddonRefresh(AtkUnitBase* addon, uint valueCount, AtkValue* values)
{ {
this.LogEvent(EnableLogging);
var result = false; var result = false;
try
{
this.LogEvent(EnableLogging);
this.refreshArgs.Addon = addon; this.refreshArgs.Addon = addon;
this.refreshArgs.AtkValueCount = valueCount; this.refreshArgs.AtkValueCount = valueCount;
this.refreshArgs.AtkValues = (nint)values; this.refreshArgs.AtkValues = (nint)values;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreRefresh, this.refreshArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreRefresh, this.refreshArgs);
valueCount = this.refreshArgs.AtkValueCount; valueCount = this.refreshArgs.AtkValueCount;
@ -251,20 +303,29 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonRefresh. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnRefresh. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostRefresh, this.refreshArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostRefresh, this.refreshArgs);
}
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonRefresh.");
}
return result; return result;
} }
private void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData) private void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.requestedUpdateArgs.Addon = addon; this.requestedUpdateArgs.Addon = addon;
this.requestedUpdateArgs.NumberArrayData = (nint)numberArrayData; this.requestedUpdateArgs.NumberArrayData = (nint)numberArrayData;
this.requestedUpdateArgs.StringArrayData = (nint)stringArrayData; this.requestedUpdateArgs.StringArrayData = (nint)stringArrayData;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreRequestedUpdate, this.requestedUpdateArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreRequestedUpdate, this.requestedUpdateArgs);
numberArrayData = (NumberArrayData**)this.requestedUpdateArgs.NumberArrayData; numberArrayData = (NumberArrayData**)this.requestedUpdateArgs.NumberArrayData;
@ -276,13 +337,20 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonRequestedUpdate. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnRequestedUpdate. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostRequestedUpdate, this.requestedUpdateArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostRequestedUpdate, this.requestedUpdateArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnRequestedUpdate.");
}
}
private void OnAddonReceiveEvent(AtkUnitBase* addon, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData) private void OnAddonReceiveEvent(AtkUnitBase* addon, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
@ -291,6 +359,7 @@ internal unsafe class AddonVirtualTable : IDisposable
this.receiveEventArgs.EventParam = eventParam; this.receiveEventArgs.EventParam = eventParam;
this.receiveEventArgs.AtkEvent = (IntPtr)atkEvent; this.receiveEventArgs.AtkEvent = (IntPtr)atkEvent;
this.receiveEventArgs.AtkEventData = (nint)atkEventData; this.receiveEventArgs.AtkEventData = (nint)atkEventData;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreReceiveEvent, this.receiveEventArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreReceiveEvent, this.receiveEventArgs);
eventType = (AtkEventType)this.receiveEventArgs.AtkEventType; eventType = (AtkEventType)this.receiveEventArgs.AtkEventType;
@ -304,19 +373,27 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonReceiveEvent. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon ReceiveEvent. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostReceiveEvent, this.receiveEventArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostReceiveEvent, this.receiveEventArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonReceiveEvent.");
}
}
private bool OnAddonOpen(AtkUnitBase* thisPtr, uint depthLayer) private bool OnAddonOpen(AtkUnitBase* thisPtr, uint depthLayer)
{ {
this.LogEvent(EnableLogging);
var result = false; var result = false;
try
{
this.LogEvent(EnableLogging);
this.openArgs.Addon = thisPtr; this.openArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreOpen, this.openArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreOpen, this.openArgs);
try try
@ -325,22 +402,30 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonOpen. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Open. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostOpen, this.openArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostOpen, this.openArgs);
}
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonOpen.");
}
return result; return result;
} }
private bool OnAddonClose(AtkUnitBase* thisPtr, bool fireCallback) private bool OnAddonClose(AtkUnitBase* thisPtr, bool fireCallback)
{ {
this.LogEvent(EnableLogging);
var result = false; var result = false;
try
{
this.LogEvent(EnableLogging);
this.closeArgs.Addon = thisPtr; this.closeArgs.Addon = thisPtr;
this.closeArgs.FireCallback = fireCallback; this.closeArgs.FireCallback = fireCallback;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreClose, this.closeArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreClose, this.closeArgs);
fireCallback = this.closeArgs.FireCallback; fireCallback = this.closeArgs.FireCallback;
@ -351,21 +436,29 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonClose. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Close. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostClose, this.closeArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostClose, this.closeArgs);
}
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonClose.");
}
return result; return result;
} }
private void OnAddonShow(AtkUnitBase* thisPtr, bool silenceOpenSoundEffect, uint unsetShowHideFlags) private void OnAddonShow(AtkUnitBase* thisPtr, bool silenceOpenSoundEffect, uint unsetShowHideFlags)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.showArgs.Addon = thisPtr; this.showArgs.Addon = thisPtr;
this.showArgs.SilenceOpenSoundEffect = silenceOpenSoundEffect; this.showArgs.SilenceOpenSoundEffect = silenceOpenSoundEffect;
this.showArgs.UnsetShowHideFlags = unsetShowHideFlags; this.showArgs.UnsetShowHideFlags = unsetShowHideFlags;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreShow, this.showArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreShow, this.showArgs);
silenceOpenSoundEffect = this.showArgs.SilenceOpenSoundEffect; silenceOpenSoundEffect = this.showArgs.SilenceOpenSoundEffect;
@ -377,13 +470,20 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonShow. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Show. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostShow, this.showArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostShow, this.showArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonShow.");
}
}
private void OnAddonHide(AtkUnitBase* thisPtr, bool unkBool, bool callHideCallback, uint setShowHideFlags) private void OnAddonHide(AtkUnitBase* thisPtr, bool unkBool, bool callHideCallback, uint setShowHideFlags)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
@ -391,6 +491,7 @@ internal unsafe class AddonVirtualTable : IDisposable
this.hideArgs.UnknownBool = unkBool; this.hideArgs.UnknownBool = unkBool;
this.hideArgs.CallHideCallback = callHideCallback; this.hideArgs.CallHideCallback = callHideCallback;
this.hideArgs.SetShowHideFlags = setShowHideFlags; this.hideArgs.SetShowHideFlags = setShowHideFlags;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreHide, this.hideArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreHide, this.hideArgs);
unkBool = this.hideArgs.UnknownBool; unkBool = this.hideArgs.UnknownBool;
@ -403,17 +504,25 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original AddonHide. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Hide. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostHide, this.hideArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostHide, this.hideArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonHide.");
}
}
private void OnAddonMove(AtkUnitBase* thisPtr) private void OnAddonMove(AtkUnitBase* thisPtr)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.onMoveArgs.Addon = thisPtr; this.onMoveArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMove, this.onMoveArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMove, this.onMoveArgs);
try try
@ -422,17 +531,25 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original OnAddonMove. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnMove. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMove, this.onMoveArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMove, this.onMoveArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonMove.");
}
}
private void OnAddonMouseOver(AtkUnitBase* thisPtr) private void OnAddonMouseOver(AtkUnitBase* thisPtr)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.onMouseOverArgs.Addon = thisPtr; this.onMouseOverArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMouseOver, this.onMouseOverArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMouseOver, this.onMouseOverArgs);
try try
@ -441,17 +558,25 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original OnAddonMouseOver. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnMouseOver. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMouseOver, this.onMouseOverArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMouseOver, this.onMouseOverArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonMouseOver.");
}
}
private void OnAddonMouseOut(AtkUnitBase* thisPtr) private void OnAddonMouseOut(AtkUnitBase* thisPtr)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.onMouseOutArgs.Addon = thisPtr; this.onMouseOutArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMouseOut, this.onMouseOutArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreMouseOut, this.onMouseOutArgs);
try try
@ -460,17 +585,25 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original OnAddonMouseOut. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon OnMouseOut. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMouseOut, this.onMouseOutArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostMouseOut, this.onMouseOutArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonMouseOut.");
}
}
private void OnAddonFocus(AtkUnitBase* thisPtr) private void OnAddonFocus(AtkUnitBase* thisPtr)
{
try
{ {
this.LogEvent(EnableLogging); this.LogEvent(EnableLogging);
this.focusArgs.Addon = thisPtr; this.focusArgs.Addon = thisPtr;
this.lifecycleService.InvokeListenersSafely(AddonEvent.PreFocus, this.focusArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PreFocus, this.focusArgs);
try try
@ -479,11 +612,16 @@ internal unsafe class AddonVirtualTable : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e, "Caught exception when calling original OnAddonFocus. This may be a bug in the game or another plugin hooking this method."); Log.Error(e, "Caught exception when calling original Addon Focus. This may be a bug in the game or another plugin hooking this method.");
} }
this.lifecycleService.InvokeListenersSafely(AddonEvent.PostFocus, this.focusArgs); this.lifecycleService.InvokeListenersSafely(AddonEvent.PostFocus, this.focusArgs);
} }
catch (Exception e)
{
Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonFocus.");
}
}
[Conditional("DEBUG")] [Conditional("DEBUG")]
private void LogEvent(bool loggingEnabled, [CallerMemberName] string caller = "") private void LogEvent(bool loggingEnabled, [CallerMemberName] string caller = "")