Safer AddonEventManager node removal (#2232)

* Remove events on Framework thread

* Make sure the addon is not unloaded

* Cleanup node finding loop

* Wait for PluginEventController to be disposed
This commit is contained in:
Haselnussbomber 2025-04-22 16:34:19 +02:00 committed by GitHub
parent 61a17dac28
commit aea62732e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 14 additions and 10 deletions

View file

@ -1,4 +1,4 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
@ -231,7 +231,10 @@ internal class AddonEventManagerPluginScoped : IInternalDisposableService, IAddo
this.eventManagerService.ResetCursor(); this.eventManagerService.ResetCursor();
} }
this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId); Service<Framework>.Get().RunOnFrameworkThread(() =>
{
this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId);
}).Wait();
} }
/// <inheritdoc/> /// <inheritdoc/>

View file

@ -1,9 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Logging.Internal; using Dalamud.Logging.Internal;
using Dalamud.Memory;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
@ -139,17 +138,19 @@ internal unsafe class PluginEventController : IDisposable
// Is our stored addon pointer the same as the active addon pointer? // Is our stored addon pointer the same as the active addon pointer?
if (currentAddonPointer != eventEntry.Addon) return; if (currentAddonPointer != eventEntry.Addon) return;
// Does this addon contain the node this event is for? (by address) // Make sure the addon is not unloaded
var atkUnitBase = (AtkUnitBase*)currentAddonPointer; var atkUnitBase = (AtkUnitBase*)currentAddonPointer;
var nodeFound = false; if (atkUnitBase->UldManager.LoadedState == AtkLoadState.Unloaded) return;
foreach (var index in Enumerable.Range(0, atkUnitBase->UldManager.NodeListCount))
{
var node = atkUnitBase->UldManager.NodeList[index];
// Does this addon contain the node this event is for? (by address)
var nodeFound = false;
foreach (var node in atkUnitBase->UldManager.Nodes)
{
// If this node matches our node, then we know our node is still valid. // If this node matches our node, then we know our node is still valid.
if (node is not null && (nint)node == eventEntry.Node) if ((nint)node.Value == eventEntry.Node)
{ {
nodeFound = true; nodeFound = true;
break;
} }
} }