diff --git a/Dalamud.DrunkenToad/Core/Services/Custom/PlayerEventDispatcher.cs b/Dalamud.DrunkenToad/Core/Services/Custom/PlayerEventDispatcher.cs
index e8aafe3..41e295f 100644
--- a/Dalamud.DrunkenToad/Core/Services/Custom/PlayerEventDispatcher.cs
+++ b/Dalamud.DrunkenToad/Core/Services/Custom/PlayerEventDispatcher.cs
@@ -1,6 +1,8 @@
namespace Dalamud.DrunkenToad.Core.Services;
+using System;
using System.Collections.Generic;
+using System.Threading;
using Extensions;
using Game.ClientState.Objects.SubKinds;
using Models;
@@ -9,11 +11,12 @@
///
/// Manages player character events, including addition, removal, and updates.
///
-public class PlayerEventDispatcher
+public class PlayerEventDispatcher : IDisposable
{
private readonly uint[] existingObjectIds = new uint[100];
private readonly IFramework gameFramework;
private readonly IObjectTable objectCollection;
+ private readonly ReaderWriterLockSlim locker = new ();
///
/// Initializes a new instance of the class.
@@ -66,18 +69,26 @@ public PlayerEventDispatcher(IFramework gameFramework, IObjectTable objectCollec
/// player if exists.
public ToadPlayer? GetPlayerById(uint id)
{
- for (var i = 0; i < this.existingObjectIds.Length; i++)
+ this.locker.EnterReadLock();
+ try
{
- if (this.existingObjectIds[i] == id)
+ for (var i = 0; i < this.existingObjectIds.Length; i++)
{
- if (this.objectCollection[i * 2] is PlayerCharacter playerCharacter)
+ if (this.existingObjectIds[i] == id)
{
- return MapToadPlayer(playerCharacter);
+ if (this.objectCollection[i * 2] is PlayerCharacter playerCharacter)
+ {
+ return MapToadPlayer(playerCharacter);
+ }
}
}
- }
- return null;
+ return null;
+ }
+ finally
+ {
+ this.locker.ExitReadLock();
+ }
}
///
@@ -88,24 +99,37 @@ public PlayerEventDispatcher(IFramework gameFramework, IObjectTable objectCollec
/// player if exists.
public ToadPlayer? GetPlayerByNameAndWorldId(string name, uint worldId)
{
- foreach (var gameObject in this.objectCollection)
+ this.locker.EnterReadLock();
+ try
{
- if (gameObject is PlayerCharacter playerCharacter)
+ foreach (var gameObject in this.objectCollection)
{
- if (playerCharacter.Name.ToString().Equals(name, System.StringComparison.Ordinal) && playerCharacter.HomeWorld.Id == worldId)
+ if (gameObject is PlayerCharacter playerCharacter)
{
- return MapToadPlayer(playerCharacter);
+ if (playerCharacter.Name.ToString().Equals(name, StringComparison.Ordinal) && playerCharacter.HomeWorld.Id == worldId)
+ {
+ return MapToadPlayer(playerCharacter);
+ }
}
}
- }
- return null;
+ return null;
+ }
+ finally
+ {
+ this.locker.ExitReadLock();
+ }
}
///
/// Dispose manager.
///
- public void Dispose() => this.gameFramework.Update -= this.OnFrameworkUpdate;
+ public void Dispose()
+ {
+ GC.SuppressFinalize(this);
+ this.gameFramework.Update -= this.OnFrameworkUpdate;
+ this.locker.Dispose();
+ }
private static ToadPlayer MapToadPlayer(PlayerCharacter character) => new ()
{
@@ -120,67 +144,75 @@ public PlayerEventDispatcher(IFramework gameFramework, IObjectTable objectCollec
IsDead = character.IsDead,
};
- private void OnFrameworkUpdate(IFramework framework1)
+ private void OnFrameworkUpdate(IFramework framework)
{
- var addedPlayers = new List();
- var removedPlayers = new List();
-
- for (var i = 2; i < 200; i += 2)
+ this.locker.EnterWriteLock();
+ try
{
- var index = i / 2;
- var currentObjectId = this.objectCollection[i]?.ObjectId ?? 0;
- var existingId = this.existingObjectIds[index];
+ var addedPlayers = new List();
+ var removedPlayers = new List();
- // check if same
- if (currentObjectId == existingId)
+ for (var i = 2; i < 200; i += 2)
{
- continue;
- }
+ var index = i / 2;
+ var currentObjectId = this.objectCollection[i]?.ObjectId ?? 0;
+ var existingId = this.existingObjectIds[index];
- // check if removed
- if (this.objectCollection[i] == null)
- {
- if (existingId != 0)
+ // check if same
+ if (currentObjectId == existingId)
{
- removedPlayers.Add(existingId);
- this.existingObjectIds[i / 2] = 0;
+ continue;
}
- continue;
- }
+ // check if removed
+ if (this.objectCollection[i] == null)
+ {
+ if (existingId != 0)
+ {
+ removedPlayers.Add(existingId);
+ this.existingObjectIds[i / 2] = 0;
+ }
- PlayerCharacter character;
- if (this.objectCollection[i].IsValidPlayerCharacter())
- {
- character = (this.objectCollection[i] as PlayerCharacter) !;
- }
- else
- {
- continue;
- }
+ continue;
+ }
- // check if new
- if (existingId == 0)
- {
+ PlayerCharacter character;
+ if (this.objectCollection[i].IsValidPlayerCharacter())
+ {
+ character = (this.objectCollection[i] as PlayerCharacter) !;
+ }
+ else
+ {
+ continue;
+ }
+
+ // check if new
+ if (existingId == 0)
+ {
+ addedPlayers.Add(MapToadPlayer(character));
+ this.existingObjectIds[i / 2] = currentObjectId;
+ continue;
+ }
+
+ // otherwise replaced
+ removedPlayers.Add(existingId);
addedPlayers.Add(MapToadPlayer(character));
this.existingObjectIds[i / 2] = currentObjectId;
- continue;
}
- // otherwise replaced
- removedPlayers.Add(existingId);
- addedPlayers.Add(MapToadPlayer(character));
- this.existingObjectIds[i / 2] = currentObjectId;
- }
+ if (removedPlayers.Count > 0)
+ {
+ this.RemovePlayers?.Invoke(removedPlayers);
+ }
- if (removedPlayers.Count > 0)
- {
- this.RemovePlayers?.Invoke(removedPlayers);
+ if (addedPlayers.Count > 0)
+ {
+ this.AddPlayers?.Invoke(addedPlayers);
+ }
}
-
- if (addedPlayers.Count > 0)
+ finally
{
- this.AddPlayers?.Invoke(addedPlayers);
+ this.locker.ExitWriteLock();
}
}
}