diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs
index 1af976b1c..760a4e492 100644
--- a/Dalamud/Game/ClientState/Actors/ActorTable.cs
+++ b/Dalamud/Game/ClientState/Actors/ActorTable.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Actors.Types;
@@ -11,9 +12,10 @@ namespace Dalamud.Game.ClientState.Actors {
///
/// This collection represents the currently spawned FFXIV actors.
///
- public class ActorTable : ICollection, IDisposable {
+ public class ActorTable : IReadOnlyCollection, ICollection, IDisposable {
#region temporary imports for crash workaround
+
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
@@ -21,6 +23,7 @@ namespace Dalamud.Game.ClientState.Actors {
IntPtr lpBuffer,
int dwSize,
out IntPtr lpNumberOfBytesRead);
+
#endregion
private ClientStateAddressResolver Address { get; }
@@ -42,7 +45,8 @@ namespace Dalamud.Game.ClientState.Actors {
Address = addressResolver;
this.dalamud = dalamud;
- this.someActorTableAccessHook = new Hook(Address.SomeActorTableAccess, new SomeActorTableAccessDelegate(SomeActorTableAccessDetour), this);
+ this.someActorTableAccessHook = new Hook(
+ Address.SomeActorTableAccess, new SomeActorTableAccessDelegate(SomeActorTableAccessDetour), this);
Log.Verbose("Actor table address {ActorTable}", Address.ViewportActorTable);
}
@@ -74,15 +78,14 @@ namespace Dalamud.Game.ClientState.Actors {
if (!this.isReady)
return null;
- if (this.someActorTableAccessHook != null)
- {
+ if (this.someActorTableAccessHook != null) {
this.someActorTableAccessHook.Dispose();
this.someActorTableAccessHook = null;
}
if (index >= Length)
return null;
-
+
var tblIndex = this.realActorTablePtr + 8 + index * 8;
var offset = Marshal.ReadIntPtr(tblIndex);
@@ -94,9 +97,8 @@ namespace Dalamud.Game.ClientState.Actors {
// FIXME: hack workaround for trying to access the player on logout, after the main object has been deleted
var sz = Marshal.SizeOf(typeof(Structs.Actor));
- var actorMem = Marshal.AllocHGlobal(sz); // we arguably could just reuse this
- if (!ReadProcessMemory(Process.GetCurrentProcess().Handle, offset, actorMem, sz, out _))
- {
+ var actorMem = Marshal.AllocHGlobal(sz); // we arguably could just reuse this
+ if (!ReadProcessMemory(Process.GetCurrentProcess().Handle, offset, actorMem, sz, out _)) {
Log.Debug("ActorTable - ReadProcessMemory failed: likely player deletion during logout");
return null;
}
@@ -106,9 +108,8 @@ namespace Dalamud.Game.ClientState.Actors {
//Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"),
// actorStruct.ObjectKind.ToString());
-
- switch (actorStruct.ObjectKind)
- {
+
+ switch (actorStruct.ObjectKind) {
case ObjectKind.Player: return new PlayerCharacter(offset, actorStruct, this.dalamud);
case ObjectKind.BattleNpc: return new BattleNpc(offset, actorStruct, this.dalamud);
default: return new Actor(offset, actorStruct, this.dalamud);
@@ -116,7 +117,7 @@ namespace Dalamud.Game.ClientState.Actors {
}
}
- private class ActorTableEnumerator : IEnumerator {
+ private class ActorTableEnumerator : IEnumerator {
private readonly ActorTable table;
private int currentIndex;
@@ -134,18 +135,29 @@ namespace Dalamud.Game.ClientState.Actors {
this.currentIndex = 0;
}
- public object Current => this.table[this.currentIndex];
+ public Actor Current => this.table[this.currentIndex];
+
+ object IEnumerator.Current => Current;
+
+ // Required by IEnumerator even though we have nothing we want to dispose here.
+ public void Dispose() {}
}
- public IEnumerator GetEnumerator() {
+ public IEnumerator GetEnumerator() {
return new ActorTableEnumerator(this);
}
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
///
/// The amount of currently spawned actors.
///
public int Length => !this.isReady ? 0 : Marshal.ReadInt32(this.realActorTablePtr);
+ int IReadOnlyCollection.Count => Length;
+
int ICollection.Count => Length;
bool ICollection.IsSynchronized => false;