Convert BuddyMember to readonly struct

This commit is contained in:
Haselnussbomber 2025-11-13 18:42:07 +01:00
parent 8a9b47c7a4
commit 23e7c164d8
No known key found for this signature in database
GPG key ID: BB905BB49E7295D1
2 changed files with 56 additions and 37 deletions

View file

@ -8,6 +8,9 @@ using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Game.UI;
using CSBuddy = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy;
using CSBuddyMember = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember;
namespace Dalamud.Game.ClientState.Buddy; namespace Dalamud.Game.ClientState.Buddy;
/// <summary> /// <summary>
@ -21,7 +24,7 @@ namespace Dalamud.Game.ClientState.Buddy;
#pragma warning restore SA1015 #pragma warning restore SA1015
internal sealed partial class BuddyList : IServiceType, IBuddyList internal sealed partial class BuddyList : IServiceType, IBuddyList
{ {
private const uint InvalidObjectID = 0xE0000000; private const uint InvalidEntityId = 0xE0000000;
[ServiceManager.ServiceDependency] [ServiceManager.ServiceDependency]
private readonly ClientState clientState = Service<ClientState>.Get(); private readonly ClientState clientState = Service<ClientState>.Get();
@ -69,7 +72,7 @@ internal sealed partial class BuddyList : IServiceType, IBuddyList
} }
} }
private unsafe FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy* BuddyListStruct => &UIState.Instance()->Buddy; private unsafe CSBuddy* BuddyListStruct => &UIState.Instance()->Buddy;
/// <inheritdoc/> /// <inheritdoc/>
public IBuddyMember? this[int index] public IBuddyMember? this[int index]
@ -82,37 +85,37 @@ internal sealed partial class BuddyList : IServiceType, IBuddyList
} }
/// <inheritdoc/> /// <inheritdoc/>
public unsafe IntPtr GetCompanionBuddyMemberAddress() public unsafe nint GetCompanionBuddyMemberAddress()
{ {
return (IntPtr)this.BuddyListStruct->CompanionInfo.Companion; return (nint)this.BuddyListStruct->CompanionInfo.Companion;
} }
/// <inheritdoc/> /// <inheritdoc/>
public unsafe IntPtr GetPetBuddyMemberAddress() public unsafe nint GetPetBuddyMemberAddress()
{ {
return (IntPtr)this.BuddyListStruct->PetInfo.Pet; return (nint)this.BuddyListStruct->PetInfo.Pet;
} }
/// <inheritdoc/> /// <inheritdoc/>
public unsafe IntPtr GetBattleBuddyMemberAddress(int index) public unsafe nint GetBattleBuddyMemberAddress(int index)
{ {
if (index < 0 || index >= 3) if (index < 0 || index >= 3)
return IntPtr.Zero; return 0;
return (IntPtr)Unsafe.AsPointer(ref this.BuddyListStruct->BattleBuddies[index]); return (nint)Unsafe.AsPointer(ref this.BuddyListStruct->BattleBuddies[index]);
} }
/// <inheritdoc/> /// <inheritdoc/>
public IBuddyMember? CreateBuddyMemberReference(IntPtr address) public unsafe IBuddyMember? CreateBuddyMemberReference(nint address)
{ {
if (address == 0)
return null;
if (this.clientState.LocalContentId == 0) if (this.clientState.LocalContentId == 0)
return null; return null;
if (address == IntPtr.Zero) var buddy = new BuddyMember((CSBuddyMember*)address);
return null; if (buddy.EntityId == InvalidEntityId)
var buddy = new BuddyMember(address);
if (buddy.ObjectId == InvalidObjectID)
return null; return null;
return buddy; return buddy;

View file

@ -1,20 +1,24 @@
using System.Diagnostics.CodeAnalysis;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Lumina.Excel; using Lumina.Excel;
using CSBuddyMember = FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember;
namespace Dalamud.Game.ClientState.Buddy; namespace Dalamud.Game.ClientState.Buddy;
/// <summary> /// <summary>
/// Interface representing represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties. /// Interface representing represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
/// </summary> /// </summary>
public interface IBuddyMember public interface IBuddyMember : IEquatable<IBuddyMember>
{ {
/// <summary> /// <summary>
/// Gets the address of the buddy in memory. /// Gets the address of the buddy in memory.
/// </summary> /// </summary>
IntPtr Address { get; } nint Address { get; }
/// <summary> /// <summary>
/// Gets the object ID of this buddy. /// Gets the object ID of this buddy.
@ -67,42 +71,34 @@ public interface IBuddyMember
} }
/// <summary> /// <summary>
/// This class represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties. /// This struct represents a buddy such as the chocobo companion, summoned pets, squadron groups and trust parties.
/// </summary> /// </summary>
internal unsafe class BuddyMember : IBuddyMember /// <param name="ptr">A pointer to the BuddyMember.</param>
internal readonly unsafe struct BuddyMember(CSBuddyMember* ptr) : IBuddyMember
{ {
[ServiceManager.ServiceDependency] [ServiceManager.ServiceDependency]
private readonly ObjectTable objectTable = Service<ObjectTable>.Get(); private readonly ObjectTable objectTable = Service<ObjectTable>.Get();
/// <summary> /// <inheritdoc />
/// Initializes a new instance of the <see cref="BuddyMember"/> class. public nint Address => (nint)ptr;
/// </summary>
/// <param name="address">Buddy address.</param>
internal BuddyMember(IntPtr address)
{
this.Address = address;
}
/// <inheritdoc /> /// <inheritdoc />
public IntPtr Address { get; } public uint ObjectId => this.EntityId;
/// <inheritdoc /> /// <inheritdoc />
public uint ObjectId => this.Struct->EntityId; public uint EntityId => ptr->EntityId;
/// <inheritdoc /> /// <inheritdoc />
public uint EntityId => this.Struct->EntityId; public IGameObject? GameObject => this.objectTable.SearchById(this.EntityId);
/// <inheritdoc /> /// <inheritdoc />
public IGameObject? GameObject => this.objectTable.SearchById(this.ObjectId); public uint CurrentHP => ptr->CurrentHealth;
/// <inheritdoc /> /// <inheritdoc />
public uint CurrentHP => this.Struct->CurrentHealth; public uint MaxHP => ptr->MaxHealth;
/// <inheritdoc /> /// <inheritdoc />
public uint MaxHP => this.Struct->MaxHealth; public uint DataID => ptr->DataId;
/// <inheritdoc />
public uint DataID => this.Struct->DataId;
/// <inheritdoc /> /// <inheritdoc />
public RowRef<Lumina.Excel.Sheets.Mount> MountData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Mount>(this.DataID); public RowRef<Lumina.Excel.Sheets.Mount> MountData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Mount>(this.DataID);
@ -113,5 +109,25 @@ internal unsafe class BuddyMember : IBuddyMember
/// <inheritdoc /> /// <inheritdoc />
public RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.DawnGrowMember>(this.DataID); public RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.DawnGrowMember>(this.DataID);
private FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember*)this.Address; public static bool operator ==(BuddyMember x, BuddyMember y) => x.Equals(y);
public static bool operator !=(BuddyMember x, BuddyMember y) => !(x == y);
/// <inheritdoc/>
public bool Equals(IBuddyMember? other)
{
return this.EntityId == other.EntityId;
}
/// <inheritdoc/>
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is BuddyMember fate && this.Equals(fate);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.EntityId.GetHashCode();
}
} }