mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge pull request #1415 from MidoriKami/AddonLifecycle_IAddonArgs
This commit is contained in:
commit
c3dd2364bb
12 changed files with 245 additions and 44 deletions
46
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonArgs.cs
Normal file
46
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonArgs.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using Dalamud.Memory;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for AddonLifecycle AddonArgTypes.
|
||||
/// </summary>
|
||||
public abstract unsafe class AddonArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant string representing the name of an addon that is invalid.
|
||||
/// </summary>
|
||||
public const string InvalidAddon = "NullAddon";
|
||||
|
||||
private string? addonName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the addon this args referrers to.
|
||||
/// </summary>
|
||||
public string AddonName => this.GetAddonName();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pointer to the addons AtkUnitBase.
|
||||
/// </summary>
|
||||
public nint Addon { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of these args.
|
||||
/// </summary>
|
||||
public abstract AddonArgsType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for ensuring the name of the addon is valid.
|
||||
/// </summary>
|
||||
/// <returns>The name of the addon for this object. <see cref="InvalidAddon"/> when invalid.</returns>
|
||||
private string GetAddonName()
|
||||
{
|
||||
if (this.Addon == nint.Zero) return InvalidAddon;
|
||||
|
||||
var addonPointer = (AtkUnitBase*)this.Addon;
|
||||
if (addonPointer->Name is null) return InvalidAddon;
|
||||
|
||||
return this.addonName ??= MemoryHelper.ReadString((nint)addonPointer->Name, 0x20);
|
||||
}
|
||||
}
|
||||
10
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonDrawArgs.cs
Normal file
10
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonDrawArgs.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Finalize events.
|
||||
/// </summary>
|
||||
public class AddonDrawArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.Draw;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Finalize events.
|
||||
/// </summary>
|
||||
public class AddonFinalizeArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.Finalize;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Finalize events.
|
||||
/// </summary>
|
||||
public class AddonRefreshArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.Refresh;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of AtkValues.
|
||||
/// </summary>
|
||||
public uint AtkValueCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the AtkValue array.
|
||||
/// </summary>
|
||||
public nint AtkValues { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AtkValues in the form of a span.
|
||||
/// </summary>
|
||||
public unsafe Span<AtkValue> AtkValueSpan => new(this.AtkValues.ToPointer(), (int)this.AtkValueCount);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Finalize events.
|
||||
/// </summary>
|
||||
public class AddonRequestedUpdateArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.RequestedUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the NumberArrayData** for this event.
|
||||
/// </summary>
|
||||
public nint NumberArrayData { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the StringArrayData** for this event.
|
||||
/// </summary>
|
||||
public nint StringArrayData { get; init; }
|
||||
}
|
||||
29
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonSetupArgs.cs
Normal file
29
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonSetupArgs.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Setup events.
|
||||
/// </summary>
|
||||
public class AddonSetupArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.Setup;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of AtkValues.
|
||||
/// </summary>
|
||||
public uint AtkValueCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the AtkValue array.
|
||||
/// </summary>
|
||||
public nint AtkValues { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AtkValues in the form of a span.
|
||||
/// </summary>
|
||||
public unsafe Span<AtkValue> AtkValueSpan => new(this.AtkValues.ToPointer(), (int)this.AtkValueCount);
|
||||
}
|
||||
15
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonUpdateArgs.cs
Normal file
15
Dalamud/Game/AddonLifecycle/AddonArgTypes/AddonUpdateArgs.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for Finalize events.
|
||||
/// </summary>
|
||||
public class AddonUpdateArgs : AddonArgs
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override AddonArgsType Type => AddonArgsType.Update;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time since the last update.
|
||||
/// </summary>
|
||||
public float TimeDelta { get; init; }
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
using Dalamud.Memory;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Addon argument data for use in event subscribers.
|
||||
/// </summary>
|
||||
public unsafe class AddonArgs
|
||||
{
|
||||
private string? addonName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the addon this args referrers to.
|
||||
/// </summary>
|
||||
public string AddonName => this.Addon == nint.Zero ? "NullAddon" : this.addonName ??= MemoryHelper.ReadString((nint)((AtkUnitBase*)this.Addon)->Name, 0x20);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pointer to the addons AtkUnitBase.
|
||||
/// </summary>
|
||||
required public nint Addon { get; init; }
|
||||
}
|
||||
37
Dalamud/Game/AddonLifecycle/AddonArgsType.cs
Normal file
37
Dalamud/Game/AddonLifecycle/AddonArgsType.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
namespace Dalamud.Game.Addon;
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration for available AddonLifecycle arg data.
|
||||
/// </summary>
|
||||
public enum AddonArgsType
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains argument data for Setup.
|
||||
/// </summary>
|
||||
Setup,
|
||||
|
||||
/// <summary>
|
||||
/// Contains argument data for Update.
|
||||
/// </summary>
|
||||
Update,
|
||||
|
||||
/// <summary>
|
||||
/// Contains argument data for Draw.
|
||||
/// </summary>
|
||||
Draw,
|
||||
|
||||
/// <summary>
|
||||
/// Contains argument data for Finalize.
|
||||
/// </summary>
|
||||
Finalize,
|
||||
|
||||
/// <summary>
|
||||
/// Contains argument data for RequestedUpdate.
|
||||
/// </summary>
|
||||
RequestedUpdate,
|
||||
|
||||
/// <summary>
|
||||
/// Contains argument data for Refresh.
|
||||
/// </summary>
|
||||
Refresh,
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
private readonly Framework framework = Service<Framework>.Get();
|
||||
|
||||
private readonly AddonLifecycleAddressResolver address;
|
||||
private readonly Hook<AddonSetupDelegate> onAddonSetupHook;
|
||||
private readonly CallHook<AddonSetupDelegate> onAddonSetupHook;
|
||||
private readonly Hook<AddonFinalizeDelegate> onAddonFinalizeHook;
|
||||
private readonly CallHook<AddonDrawDelegate> onAddonDrawHook;
|
||||
private readonly CallHook<AddonUpdateDelegate> onAddonUpdateHook;
|
||||
|
|
@ -45,7 +45,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
this.framework.Update += this.OnFrameworkUpdate;
|
||||
|
||||
this.onAddonSetupHook = Hook<AddonSetupDelegate>.FromAddress(this.address.AddonSetup, this.OnAddonSetup);
|
||||
this.onAddonSetupHook = new CallHook<AddonSetupDelegate>(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);
|
||||
|
|
@ -53,7 +53,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
this.onAddonRequestedUpdateHook = new CallHook<AddonOnRequestedUpdateDelegate>(this.address.AddonOnRequestedUpdate, this.OnRequestedUpdate);
|
||||
}
|
||||
|
||||
private delegate nint AddonSetupDelegate(AtkUnitBase* addon);
|
||||
private delegate void AddonSetupDelegate(AtkUnitBase* addon, uint valueCount, AtkValue* values);
|
||||
|
||||
private delegate void AddonFinalizeDelegate(AtkUnitManager* unitManager, AtkUnitBase** atkUnitBase);
|
||||
|
||||
|
|
@ -136,36 +136,44 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
}
|
||||
}
|
||||
|
||||
private nint OnAddonSetup(AtkUnitBase* addon)
|
||||
private void OnAddonSetup(AtkUnitBase* addon, uint valueCount, AtkValue* values)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreSetup, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PreSetup, new AddonSetupArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
AtkValueCount = valueCount,
|
||||
AtkValues = (nint)values,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonSetup pre-setup invoke.");
|
||||
}
|
||||
|
||||
var result = this.onAddonSetupHook.Original(addon);
|
||||
addon->OnSetup(valueCount, values);
|
||||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostSetup, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PostSetup, new AddonSetupArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
AtkValueCount = valueCount,
|
||||
AtkValues = (nint)values,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception in OnAddonSetup post-setup invoke.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void OnAddonFinalize(AtkUnitManager* unitManager, AtkUnitBase** atkUnitBase)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreFinalize, new AddonArgs { Addon = (nint)atkUnitBase[0] });
|
||||
this.InvokeListeners(AddonEvent.PreFinalize, new AddonFinalizeArgs { Addon = (nint)atkUnitBase[0] });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -179,7 +187,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreDraw, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PreDraw, new AddonDrawArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -190,7 +198,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostDraw, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PostDraw, new AddonDrawArgs { Addon = (nint)addon });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -202,7 +210,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreUpdate, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PreUpdate, new AddonUpdateArgs { Addon = (nint)addon, TimeDelta = delta });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -213,7 +221,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostUpdate, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PostUpdate, new AddonUpdateArgs { Addon = (nint)addon, TimeDelta = delta });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -225,7 +233,12 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreRefresh, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PreRefresh, new AddonRefreshArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
AtkValueCount = valueCount,
|
||||
AtkValues = (nint)values,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -236,7 +249,12 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostRefresh, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PostRefresh, new AddonRefreshArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
AtkValueCount = valueCount,
|
||||
AtkValues = (nint)values,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -250,7 +268,12 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
{
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PreRequestedUpdate, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PreRequestedUpdate, new AddonRequestedUpdateArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
NumberArrayData = (nint)numberArrayData,
|
||||
StringArrayData = (nint)stringArrayData,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -261,7 +284,12 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
|
|||
|
||||
try
|
||||
{
|
||||
this.InvokeListeners(AddonEvent.PostRequestedUpdate, new AddonArgs { Addon = (nint)addon });
|
||||
this.InvokeListeners(AddonEvent.PostRequestedUpdate, new AddonRequestedUpdateArgs
|
||||
{
|
||||
Addon = (nint)addon,
|
||||
NumberArrayData = (nint)numberArrayData,
|
||||
StringArrayData = (nint)stringArrayData,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ internal class AddonLifecycleAddressResolver : BaseAddressResolver
|
|||
/// <param name="sig">The signature scanner to facilitate setup.</param>
|
||||
protected override void Setup64Bit(SigScanner sig)
|
||||
{
|
||||
this.AddonSetup = sig.ScanText("E8 ?? ?? ?? ?? 8B 83 ?? ?? ?? ?? C1 E8 14");
|
||||
this.AddonSetup = sig.ScanText("FF 90 ?? ?? ?? ?? 48 8B 93 ?? ?? ?? ?? 80 8B");
|
||||
this.AddonFinalize = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 7C 24 ?? 41 8B C6");
|
||||
this.AddonDraw = sig.ScanText("FF 90 ?? ?? ?? ?? 83 EB 01 79 C1");
|
||||
this.AddonUpdate = sig.ScanText("FF 90 ?? ?? ?? ?? 40 88 AF");
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ public interface IAddonLifecycle
|
|||
/// <summary>
|
||||
/// Delegate for receiving addon lifecycle event messages.
|
||||
/// </summary>
|
||||
/// <param name="eventType">The event type that triggered the message.</param>
|
||||
/// <param name="addonInfo">Information about what addon triggered the message.</param>
|
||||
public delegate void AddonEventDelegate(AddonEvent eventType, AddonArgs addonInfo);
|
||||
/// <param name="type">The event type that triggered the message.</param>
|
||||
/// <param name="args">Information about what addon triggered the message.</param>
|
||||
public delegate void AddonEventDelegate(AddonEvent type, AddonArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Register a listener that will trigger on the specified event and any of the specified addons.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue