Merge remote-tracking branch 'origin/AddonLifecycleRefactor' into AddonLifecycleRefactor

This commit is contained in:
MidoriKami 2025-12-15 13:13:19 -08:00
commit d7935d6dd4
101 changed files with 2604 additions and 1676 deletions

View file

@ -9,7 +9,6 @@ using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Component.GUI;
namespace Dalamud.Game.Addon.Events;
@ -32,25 +31,21 @@ internal unsafe class AddonEventManager : IInternalDisposableService
private readonly AddonLifecycleEventListener finalizeEventListener;
private readonly AddonEventManagerAddressResolver address;
private readonly Hook<UpdateCursorDelegate> onUpdateCursor;
private readonly Hook<AtkUnitManager.Delegates.UpdateCursor> onUpdateCursor;
private readonly ConcurrentDictionary<Guid, PluginEventController> pluginEventControllers;
private AddonCursorType? cursorOverride;
private AtkCursor.CursorType? cursorOverride;
[ServiceManager.ServiceConstructor]
private AddonEventManager(TargetSigScanner sigScanner)
private AddonEventManager()
{
this.address = new AddonEventManagerAddressResolver();
this.address.Setup(sigScanner);
this.pluginEventControllers = new ConcurrentDictionary<Guid, PluginEventController>();
this.pluginEventControllers.TryAdd(DalamudInternalKey, new PluginEventController());
this.cursorOverride = null;
this.onUpdateCursor = Hook<UpdateCursorDelegate>.FromAddress(this.address.UpdateCursor, this.UpdateCursorDetour);
this.onUpdateCursor = Hook<AtkUnitManager.Delegates.UpdateCursor>.FromAddress(AtkUnitManager.Addresses.UpdateCursor.Value, this.UpdateCursorDetour);
this.finalizeEventListener = new AddonLifecycleEventListener(AddonEvent.PreFinalize, string.Empty, this.OnAddonFinalize);
this.addonLifecycle.RegisterListener(this.finalizeEventListener);
@ -58,8 +53,6 @@ internal unsafe class AddonEventManager : IInternalDisposableService
this.onUpdateCursor.Enable();
}
private delegate nint UpdateCursorDelegate(RaptureAtkModule* module);
/// <inheritdoc/>
void IInternalDisposableService.DisposeService()
{
@ -117,7 +110,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService
/// Force the game cursor to be the specified cursor.
/// </summary>
/// <param name="cursor">Which cursor to use.</param>
internal void SetCursor(AddonCursorType cursor) => this.cursorOverride = cursor;
internal void SetCursor(AddonCursorType cursor) => this.cursorOverride = (AtkCursor.CursorType)cursor;
/// <summary>
/// Un-forces the game cursor.
@ -168,7 +161,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService
}
}
private nint UpdateCursorDetour(RaptureAtkModule* module)
private void UpdateCursorDetour(AtkUnitManager* thisPtr)
{
try
{
@ -176,13 +169,14 @@ internal unsafe class AddonEventManager : IInternalDisposableService
if (this.cursorOverride is not null && atkStage is not null)
{
var cursor = (AddonCursorType)atkStage->AtkCursor.Type;
if (cursor != this.cursorOverride)
ref var atkCursor = ref atkStage->AtkCursor;
if (atkCursor.Type != this.cursorOverride)
{
AtkStage.Instance()->AtkCursor.SetCursorType((AtkCursor.CursorType)this.cursorOverride, 1);
atkCursor.SetCursorType((AtkCursor.CursorType)this.cursorOverride, 1);
}
return nint.Zero;
return;
}
}
catch (Exception e)
@ -190,7 +184,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService
Log.Error(e, "Exception in UpdateCursorDetour.");
}
return this.onUpdateCursor!.Original(module);
this.onUpdateCursor!.Original(thisPtr);
}
}

View file

@ -1,23 +0,0 @@
using Dalamud.Plugin.Services;
namespace Dalamud.Game.Addon.Events;
/// <summary>
/// AddonEventManager memory address resolver.
/// </summary>
internal class AddonEventManagerAddressResolver : BaseAddressResolver
{
/// <summary>
/// Gets the address of the AtkModule UpdateCursor method.
/// </summary>
public nint UpdateCursor { get; private set; }
/// <summary>
/// Scan for and setup any configured address pointers.
/// </summary>
/// <param name="scanner">The signature scanner to facilitate setup.</param>
protected override void Setup64Bit(ISigScanner scanner)
{
this.UpdateCursor = scanner.ScanText("48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 4C 8B F1 E8 ?? ?? ?? ?? 49 8B CE"); // unnamed in CS
}
}

View file

@ -104,7 +104,7 @@ internal partial class ChatHandlers : IServiceType
if (this.configuration.PrintDalamudWelcomeMsg)
{
chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud {0} loaded."), Util.GetScmVersion())
chatGui.Print(string.Format(Loc.Localize("DalamudWelcome", "Dalamud {0} loaded."), Versioning.GetScmVersion())
+ string.Format(Loc.Localize("PluginsWelcome", " {0} plugin(s) loaded."), pluginManager.InstalledPlugins.Count(x => x.IsLoaded)));
}
@ -116,7 +116,7 @@ internal partial class ChatHandlers : IServiceType
}
}
if (string.IsNullOrEmpty(this.configuration.LastVersion) || !Util.AssemblyVersion.StartsWith(this.configuration.LastVersion))
if (string.IsNullOrEmpty(this.configuration.LastVersion) || !Versioning.GetAssemblyVersion().StartsWith(this.configuration.LastVersion))
{
var linkPayload = chatGui.AddChatLinkHandler(
(_, _) => dalamudInterface.OpenPluginInstallerTo(PluginInstallerOpenKind.Changelogs));
@ -137,7 +137,7 @@ internal partial class ChatHandlers : IServiceType
Type = XivChatType.Notice,
});
this.configuration.LastVersion = Util.AssemblyVersion;
this.configuration.LastVersion = Versioning.GetAssemblyVersion();
this.configuration.QueueSave();
}

View file

@ -305,7 +305,8 @@ internal class GameInventory : IInternalDisposableService
private GameInventoryItem[] CreateItemsArray(int length)
{
var items = new GameInventoryItem[length];
items.Initialize();
foreach (ref var item in items.AsSpan())
item = new();
return items;
}

View file

@ -77,7 +77,7 @@ internal unsafe class PlayerState : IServiceType, IPlayerState
public RowRef<ClassJob> ClassJob => this.IsLoaded ? LuminaUtils.CreateRef<ClassJob>(CSPlayerState.Instance()->CurrentClassJobId) : default;
/// <inheritdoc/>
public short Level => this.IsLoaded ? CSPlayerState.Instance()->CurrentLevel : default;
public short Level => this.IsLoaded && this.ClassJob.IsValid ? this.GetClassJobLevel(this.ClassJob.Value) : this.EffectiveLevel;
/// <inheritdoc/>
public bool IsLevelSynced => this.IsLoaded && CSPlayerState.Instance()->IsLevelSynced;

View file

@ -3,7 +3,6 @@ using System.Globalization;
using Lumina.Text.ReadOnly;
using DSeString = Dalamud.Game.Text.SeStringHandling.SeString;
using LSeString = Lumina.Text.SeString;
namespace Dalamud.Game.Text.Evaluator;
@ -71,9 +70,6 @@ public readonly struct SeStringParameter
public static implicit operator SeStringParameter(ReadOnlySeStringSpan value) => new(new ReadOnlySeString(value));
[Obsolete("Switch to using ReadOnlySeString instead of Lumina's SeString.", true)]
public static implicit operator SeStringParameter(LSeString value) => new(new ReadOnlySeString(value.RawData));
public static implicit operator SeStringParameter(DSeString value) => new(new ReadOnlySeString(value.Encode()));
public static implicit operator SeStringParameter(string value) => new(value);

View file

@ -60,8 +60,8 @@ internal record struct NounParams()
/// </summary>
public readonly int ColumnOffset => this.SheetName switch
{
// See "E8 ?? ?? ?? ?? 44 8B 6B 08"
nameof(LSheets.BeastTribe) => 10,
// See "E8 ?? ?? ?? ?? 44 8B 66 ?? 8B E8"
nameof(LSheets.BeastTribe) => 11,
nameof(LSheets.DeepDungeonItem) => 1,
nameof(LSheets.DeepDungeonEquipment) => 1,
nameof(LSheets.DeepDungeonMagicStone) => 1,

View file

@ -113,14 +113,6 @@ public class SeString
/// <returns>Equivalent SeString.</returns>
public static implicit operator SeString(string str) => new(new TextPayload(str));
/// <summary>
/// Implicitly convert a string into a SeString containing a <see cref="TextPayload"/>.
/// </summary>
/// <param name="str">string to convert.</param>
/// <returns>Equivalent SeString.</returns>
[Obsolete("Switch to using ReadOnlySeString instead of Lumina's SeString.", true)]
public static explicit operator SeString(Lumina.Text.SeString str) => str.ToDalamudString();
/// <summary>
/// Parse a binary game message into an SeString.
/// </summary>