mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-02 13:53:40 +01:00
Add AddonDraw, AddonUpdate
This commit is contained in:
parent
4dabd07131
commit
9176342ad5
3 changed files with 106 additions and 51 deletions
|
|
@ -1,7 +1,7 @@
|
|||
namespace Dalamud.Game.AddonLifecycle;
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration for available AddonLifecycle events
|
||||
/// Enumeration for available AddonLifecycle events.
|
||||
/// </summary>
|
||||
public enum AddonEvent
|
||||
{
|
||||
|
|
@ -9,53 +9,32 @@ public enum AddonEvent
|
|||
/// Event that is fired before an addon begins it's setup process.
|
||||
/// </summary>
|
||||
PreSetup,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired after an addon has completed it's setup process.
|
||||
/// </summary>
|
||||
PostSetup,
|
||||
|
||||
// // Events not implemented yet.
|
||||
// /// <summary>
|
||||
// /// Event that is fired right before an addon is set to shown.
|
||||
// /// </summary>
|
||||
// PreShow,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired after an addon has been shown.
|
||||
// /// </summary>
|
||||
// PostShow,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired right before an addon is set to hidden.
|
||||
// /// </summary>
|
||||
// PreHide,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired after an addon has been hidden.
|
||||
// /// </summary>
|
||||
// PostHide,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired before an addon begins update.
|
||||
// /// </summary>
|
||||
// PreUpdate,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired after an addon has completed update.
|
||||
// /// </summary>
|
||||
// PostUpdate,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired before an addon begins draw.
|
||||
// /// </summary>
|
||||
// PreDraw,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Event that is fired after an addon has completed draw.
|
||||
// /// </summary>
|
||||
// PostDraw,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired before an addon begins update.
|
||||
/// </summary>
|
||||
PreUpdate,
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired after an addon has completed update.
|
||||
/// </summary>
|
||||
PostUpdate,
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired before an addon begins draw.
|
||||
/// </summary>
|
||||
PreDraw,
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired after an addon has completed draw.
|
||||
/// </summary>
|
||||
PostDraw,
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired before an addon is finalized.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Hooking.Internal;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging.Internal;
|
||||
|
|
@ -27,6 +28,8 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
private readonly AddonLifecycleAddressResolver address;
|
||||
private readonly Hook<AddonSetupDelegate> onAddonSetupHook;
|
||||
private readonly Hook<AddonFinalizeDelegate> onAddonFinalizeHook;
|
||||
private readonly CallHook<AddonDrawDelegate> onAddonDrawHook;
|
||||
private readonly CallHook<AddonUpdateDelegate> onAddonUpdateHook;
|
||||
|
||||
private readonly ConcurrentBag<AddonLifecycleEventListener> newEventListeners = new();
|
||||
private readonly ConcurrentBag<AddonLifecycleEventListener> removeEventListeners = new();
|
||||
|
|
@ -42,12 +45,18 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
this.onAddonSetupHook = Hook<AddonSetupDelegate>.FromAddress(this.address.AddonSetup, this.OnAddonSetup);
|
||||
this.onAddonFinalizeHook = Hook<AddonFinalizeDelegate>.FromAddress(this.address.AddonFinalize, this.OnAddonFinalize);
|
||||
this.onAddonDrawHook = new CallHook<AddonDrawDelegate>(this.address.AddonDraw, this.OnAddonDraw);
|
||||
this.onAddonUpdateHook = new CallHook<AddonUpdateDelegate>(this.address.AddonUpdate, this.OnAddonUpdate);
|
||||
}
|
||||
|
||||
|
||||
private delegate nint AddonSetupDelegate(AtkUnitBase* addon);
|
||||
|
||||
private delegate void AddonFinalizeDelegate(AtkUnitManager* unitManager, AtkUnitBase** atkUnitBase);
|
||||
|
||||
private delegate void AddonDrawDelegate(AtkUnitBase* addon);
|
||||
|
||||
private delegate void AddonUpdateDelegate(AtkUnitBase* addon);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
@ -55,6 +64,8 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
this.onAddonSetupHook.Dispose();
|
||||
this.onAddonFinalizeHook.Dispose();
|
||||
this.onAddonDrawHook.Dispose();
|
||||
this.onAddonUpdateHook.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -100,6 +111,8 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
{
|
||||
this.onAddonSetupHook.Enable();
|
||||
this.onAddonFinalizeHook.Enable();
|
||||
this.onAddonDrawHook.Enable();
|
||||
this.onAddonUpdateHook.Enable();
|
||||
}
|
||||
|
||||
private void InvokeListeners(AddonEvent eventType, IAddonLifecycle.AddonArgs args)
|
||||
|
|
@ -158,6 +171,56 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
this.onAddonFinalizeHook.Original(unitManager, atkUnitBase);
|
||||
}
|
||||
|
||||
private void OnAddonDraw(AtkUnitBase* addon)
|
||||
{
|
||||
if (addon is null) return;
|
||||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreDraw, new IAddonLifecycle.AddonArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonDraw pre-draw invoke.");
|
||||
}
|
||||
|
||||
((delegate* unmanaged<AtkUnitBase*, void>)addon->AtkEventListener.vfunc[42])(addon);
|
||||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostDraw, new IAddonLifecycle.AddonArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonDraw post-draw invoke.");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAddonUpdate(AtkUnitBase* addon)
|
||||
{
|
||||
if (addon is null) return;
|
||||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreUpdate, new IAddonLifecycle.AddonArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonUpdate pre-update invoke.");
|
||||
}
|
||||
|
||||
((delegate* unmanaged<AtkUnitBase*, void>)addon->AtkEventListener.vfunc[41])(addon);
|
||||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostUpdate, new IAddonLifecycle.AddonArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonUpdate post-update invoke.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -175,7 +238,7 @@ internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLif
|
|||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly AddonLifecycle addonLifecycleService = Service<AddonLifecycle>.Get();
|
||||
|
||||
|
||||
private readonly List<AddonLifecycleEventListener> eventListeners = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -227,7 +290,8 @@ internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLif
|
|||
var targetListeners = this.eventListeners
|
||||
.Where(entry => entry.EventType == eventType)
|
||||
.Where(entry => entry.AddonName == addonName)
|
||||
.Where(entry => handler is null || entry.FunctionDelegate == handler);
|
||||
.Where(entry => handler is null || entry.FunctionDelegate == handler)
|
||||
.ToArray(); // Make a copy so we don't mutate this list while removing entries.
|
||||
|
||||
foreach (var listener in targetListeners)
|
||||
{
|
||||
|
|
@ -245,7 +309,7 @@ internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLif
|
|||
/// <inheritdoc/>
|
||||
public void UnregisterListener(IAddonLifecycle.AddonEventDelegate handler, params IAddonLifecycle.AddonEventDelegate[] handlers)
|
||||
{
|
||||
foreach (var listener in this.eventListeners.Where(entry => entry.FunctionDelegate == handler))
|
||||
foreach (var listener in this.eventListeners.Where(entry => entry.FunctionDelegate == handler).ToArray())
|
||||
{
|
||||
this.addonLifecycleService.UnregisterListener(listener);
|
||||
this.eventListeners.Remove(listener);
|
||||
|
|
@ -253,7 +317,7 @@ internal class AddonLifecyclePluginScoped : IDisposable, IServiceType, IAddonLif
|
|||
|
||||
foreach (var handlerParma in handlers)
|
||||
{
|
||||
foreach (var listener in this.eventListeners.Where(entry => entry.FunctionDelegate == handlerParma))
|
||||
foreach (var listener in this.eventListeners.Where(entry => entry.FunctionDelegate == handlerParma).ToArray())
|
||||
{
|
||||
this.addonLifecycleService.UnregisterListener(listener);
|
||||
this.eventListeners.Remove(listener);
|
||||
|
|
|
|||
|
|
@ -6,14 +6,24 @@
|
|||
internal class AddonLifecycleAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the address of the addon setup hook invoked by the atkunitmanager.
|
||||
/// Gets the address of the addon setup hook invoked by the AtkUnitManager.
|
||||
/// </summary>
|
||||
public nint AddonSetup { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the addon finalize hook invoked by the atkunitmanager.
|
||||
/// Gets the address of the addon finalize hook invoked by the AtkUnitManager.
|
||||
/// </summary>
|
||||
public nint AddonFinalize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the addon draw hook invoked by virtual function call.
|
||||
/// </summary>
|
||||
public nint AddonDraw { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the addon update hook invoked by virtual function call.
|
||||
/// </summary>
|
||||
public nint AddonUpdate { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan for and setup any configured address pointers.
|
||||
|
|
@ -23,5 +33,7 @@ internal class AddonLifecycleAddressResolver : BaseAddressResolver
|
|||
{
|
||||
this.AddonSetup = sig.ScanText("E8 ?? ?? ?? ?? 8B 83 ?? ?? ?? ?? C1 E8 14");
|
||||
this.AddonFinalize = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 7C 24 ?? 41 8B C6");
|
||||
this.AddonDraw = sig.ScanText("48 8B 01 FF 90 ?? ?? ?? ?? 83 EB 01 79 C1");
|
||||
this.AddonUpdate = sig.ScanText("FF 90 ?? ?? ?? ?? 40 88 AF");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue