Add struct enumerator to StatusList

This commit is contained in:
Haselnussbomber 2025-11-13 19:02:50 +01:00
parent 7f2ed9adb6
commit 778c82fad2
No known key found for this signature in database
GPG key ID: BB905BB49E7295D1

View file

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CSStatus = FFXIVClientStructs.FFXIV.Client.Game.Status;
namespace Dalamud.Game.ClientState.Statuses; namespace Dalamud.Game.ClientState.Statuses;
/// <summary> /// <summary>
@ -14,7 +16,7 @@ public sealed unsafe partial class StatusList
/// Initializes a new instance of the <see cref="StatusList"/> class. /// Initializes a new instance of the <see cref="StatusList"/> class.
/// </summary> /// </summary>
/// <param name="address">Address of the status list.</param> /// <param name="address">Address of the status list.</param>
internal StatusList(IntPtr address) internal StatusList(nint address)
{ {
this.Address = address; this.Address = address;
} }
@ -24,14 +26,14 @@ public sealed unsafe partial class StatusList
/// </summary> /// </summary>
/// <param name="pointer">Pointer to the status list.</param> /// <param name="pointer">Pointer to the status list.</param>
internal unsafe StatusList(void* pointer) internal unsafe StatusList(void* pointer)
: this((IntPtr)pointer) : this((nint)pointer)
{ {
} }
/// <summary> /// <summary>
/// Gets the address of the status list in memory. /// Gets the address of the status list in memory.
/// </summary> /// </summary>
public IntPtr Address { get; } public nint Address { get; }
/// <summary> /// <summary>
/// Gets the amount of status effect slots the actor has. /// Gets the amount of status effect slots the actor has.
@ -47,7 +49,7 @@ public sealed unsafe partial class StatusList
/// </summary> /// </summary>
/// <param name="index">Status Index.</param> /// <param name="index">Status Index.</param>
/// <returns>The status at the specified index.</returns> /// <returns>The status at the specified index.</returns>
public Status? this[int index] public IStatus? this[int index]
{ {
get get
{ {
@ -64,7 +66,7 @@ public sealed unsafe partial class StatusList
/// </summary> /// </summary>
/// <param name="address">The address of the status list in memory.</param> /// <param name="address">The address of the status list in memory.</param>
/// <returns>The status object containing the requested data.</returns> /// <returns>The status object containing the requested data.</returns>
public static StatusList? CreateStatusListReference(IntPtr address) public static StatusList? CreateStatusListReference(nint address)
{ {
// The use case for CreateStatusListReference and CreateStatusReference to be static is so // The use case for CreateStatusListReference and CreateStatusReference to be static is so
// fake status lists can be generated. Since they aren't exposed as services, it's either // fake status lists can be generated. Since they aren't exposed as services, it's either
@ -74,7 +76,7 @@ public sealed unsafe partial class StatusList
if (clientState.LocalContentId == 0) if (clientState.LocalContentId == 0)
return null; return null;
if (address == IntPtr.Zero) if (address == 0)
return null; return null;
return new StatusList(address); return new StatusList(address);
@ -85,17 +87,17 @@ public sealed unsafe partial class StatusList
/// </summary> /// </summary>
/// <param name="address">The address of the status effect in memory.</param> /// <param name="address">The address of the status effect in memory.</param>
/// <returns>The status object containing the requested data.</returns> /// <returns>The status object containing the requested data.</returns>
public static Status? CreateStatusReference(IntPtr address) public static IStatus? CreateStatusReference(nint address)
{ {
var clientState = Service<ClientState>.Get(); var clientState = Service<ClientState>.Get();
if (clientState.LocalContentId == 0) if (clientState.LocalContentId == 0)
return null; return null;
if (address == IntPtr.Zero) if (address == 0)
return null; return null;
return new Status(address); return new Status((CSStatus*)address);
} }
/// <summary> /// <summary>
@ -103,22 +105,22 @@ public sealed unsafe partial class StatusList
/// </summary> /// </summary>
/// <param name="index">The index of the status.</param> /// <param name="index">The index of the status.</param>
/// <returns>The memory address of the status.</returns> /// <returns>The memory address of the status.</returns>
public IntPtr GetStatusAddress(int index) public nint GetStatusAddress(int index)
{ {
if (index < 0 || index >= this.Length) if (index < 0 || index >= this.Length)
return IntPtr.Zero; return 0;
return (IntPtr)Unsafe.AsPointer(ref this.Struct->Status[index]); return (nint)Unsafe.AsPointer(ref this.Struct->Status[index]);
} }
} }
/// <summary> /// <summary>
/// This collection represents the status effects an actor is afflicted by. /// This collection represents the status effects an actor is afflicted by.
/// </summary> /// </summary>
public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollection public sealed partial class StatusList : IReadOnlyCollection<IStatus>, ICollection
{ {
/// <inheritdoc/> /// <inheritdoc/>
int IReadOnlyCollection<Status>.Count => this.Length; int IReadOnlyCollection<IStatus>.Count => this.Length;
/// <inheritdoc/> /// <inheritdoc/>
int ICollection.Count => this.Length; int ICollection.Count => this.Length;
@ -130,17 +132,9 @@ public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollectio
object ICollection.SyncRoot => this; object ICollection.SyncRoot => this;
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerator<Status> GetEnumerator() public IEnumerator<IStatus> GetEnumerator()
{ {
for (var i = 0; i < this.Length; i++) return new Enumerator(this);
{
var status = this[i];
if (status == null || status.StatusId == 0)
continue;
yield return status;
}
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -155,4 +149,39 @@ public sealed partial class StatusList : IReadOnlyCollection<Status>, ICollectio
index++; index++;
} }
} }
private struct Enumerator(StatusList statusList) : IEnumerator<IStatus>
{
private int index = 0;
public IStatus Current { get; private set; }
object IEnumerator.Current => this.Current;
public bool MoveNext()
{
if (this.index == statusList.Length) return false;
for (; this.index < statusList.Length; this.index++)
{
var status = statusList[this.index];
if (status != null && status.StatusId != 0)
{
this.Current = status;
return true;
}
}
return false;
}
public void Reset()
{
this.index = 0;
}
public void Dispose()
{
}
}
} }