diff --git a/MareSynchronos/Factories/CharacterDataFactory.cs b/MareSynchronos/Factories/CharacterDataFactory.cs index a00df6d..6ea9eae 100644 --- a/MareSynchronos/Factories/CharacterDataFactory.cs +++ b/MareSynchronos/Factories/CharacterDataFactory.cs @@ -292,16 +292,6 @@ public class CharacterDataFactory { transientResourceManager.PersistTransientResources(charaPointer, objectKind, CreateFileReplacement); - /*foreach (var item in transientResourceManager.GetTransientResources(charaPointer)) - { - if (!previousData.FileReplacements[objectKind].Any(f => f.GamePaths.Any(p => p.ToLowerInvariant() == item.ToLowerInvariant()))) - { - Logger.Verbose("Found transient resource: " + item); - AddReplacement(item, objectKind, previousData, 1, true); - } - }*/ - - foreach (var item in transientResourceManager.GetSemiTransientResources(objectKind)) { if (!previousData.FileReplacements.ContainsKey(objectKind)) diff --git a/MareSynchronos/Managers/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs index 689afd2..5d917f1 100644 --- a/MareSynchronos/Managers/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -40,7 +40,7 @@ public class CachedPlayer } } - private bool _isDisposed = false; + private bool _isDisposed = true; private CancellationTokenSource? _downloadCancellationTokenSource = new(); private string _lastGlamourerData = string.Empty; @@ -206,6 +206,7 @@ public class CachedPlayer } else { + Logger.Verbose("Missing file: " + item.Hash); missingFiles.Add(item); } } @@ -397,6 +398,7 @@ public class CachedPlayer public void InitializePlayer(PlayerCharacter character, CharacterCacheDto? cache) { + if (!_isDisposed) return; Logger.Debug("Initializing Player " + this + " has cache: " + (cache != null)); IsVisible = true; PlayerName = character.Name.ToString(); diff --git a/MareSynchronos/Managers/OnlinePlayerManager.cs b/MareSynchronos/Managers/OnlinePlayerManager.cs index 30f0ee9..6c28b2e 100644 --- a/MareSynchronos/Managers/OnlinePlayerManager.cs +++ b/MareSynchronos/Managers/OnlinePlayerManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -8,7 +9,6 @@ using MareSynchronos.API; using MareSynchronos.Utils; using MareSynchronos.WebAPI; using MareSynchronos.WebAPI.Utils; -using Newtonsoft.Json; namespace MareSynchronos.Managers; @@ -19,12 +19,12 @@ public class OnlinePlayerManager : IDisposable private readonly Framework _framework; private readonly IpcManager _ipcManager; private readonly PlayerManager _playerManager; - private readonly List _onlineCachedPlayers = new(); + private readonly ConcurrentDictionary _onlineCachedPlayers = new(); private readonly Dictionary _temporaryStoredCharacterCache = new(); private readonly Dictionary _playerTokenDisposal = new(); - private List OnlineVisiblePlayerHashes => _onlineCachedPlayers.Where(p => p.PlayerCharacter != null) - .Select(p => p.PlayerNameHash).ToList(); + private List OnlineVisiblePlayerHashes => _onlineCachedPlayers.Where(p => p.Value.PlayerCharacter != null) + .Select(p => p.Value.PlayerNameHash).ToList(); private DateTime _lastPlayerObjectCheck = DateTime.Now; public OnlinePlayerManager(Framework framework, ApiController apiController, DalamudUtil dalamudUtil, IpcManager ipcManager, PlayerManager playerManager) @@ -58,7 +58,7 @@ public class OnlinePlayerManager : IDisposable private void ApiControllerOnCharacterReceived(object? sender, CharacterReceivedEventArgs e) { - var visiblePlayer = _onlineCachedPlayers.SingleOrDefault(c => c.IsVisible && c.PlayerNameHash == e.CharacterNameHash); + var visiblePlayer = _onlineCachedPlayers.Select(v => v.Value).SingleOrDefault(c => c.IsVisible && c.PlayerNameHash == e.CharacterNameHash); if (visiblePlayer != null) { Logger.Debug("Received data and applying to " + e.CharacterNameHash); @@ -99,7 +99,15 @@ public class OnlinePlayerManager : IDisposable private void IpcManagerOnPenumbraDisposed() { - _onlineCachedPlayers.ForEach(p => p.DisposePlayer()); + DisposeAllPlayers(); + } + + private void DisposeAllPlayers() + { + foreach (var entry in _onlineCachedPlayers) + { + entry.Value.DisposePlayer(); + } } private void ApiControllerOnDisconnected() @@ -111,7 +119,10 @@ public class OnlinePlayerManager : IDisposable public void AddInitialPairs(List apiTaskResult) { _onlineCachedPlayers.Clear(); - _onlineCachedPlayers.AddRange(apiTaskResult.Select(CreateCachedPlayer)); + foreach (var result in apiTaskResult) + { + _onlineCachedPlayers.TryAdd(result, CreateCachedPlayer(result)); + } Logger.Verbose("Online and paired users: " + string.Join(Environment.NewLine, _onlineCachedPlayers)); } @@ -138,7 +149,7 @@ public class OnlinePlayerManager : IDisposable private void RestoreAllCharacters() { - _onlineCachedPlayers.ForEach(p => p.DisposePlayer()); + DisposeAllPlayers(); _onlineCachedPlayers.Clear(); } @@ -171,19 +182,23 @@ public class OnlinePlayerManager : IDisposable private void AddPlayer(string characterNameHash) { - if (_onlineCachedPlayers.Any(p => p.PlayerNameHash == characterNameHash)) + if (_onlineCachedPlayers.ContainsKey(characterNameHash)) { PushCharacterData(new List() { characterNameHash }); - _playerTokenDisposal.TryGetValue(_onlineCachedPlayers.Single(p => p.PlayerNameHash == characterNameHash), out var cancellationTokenSource); + _playerTokenDisposal.TryGetValue(_onlineCachedPlayers[characterNameHash], out var cancellationTokenSource); cancellationTokenSource?.Cancel(); return; } - _onlineCachedPlayers.Add(CreateCachedPlayer(characterNameHash)); + _onlineCachedPlayers.TryAdd(characterNameHash, CreateCachedPlayer(characterNameHash)); } private void RemovePlayer(string characterHash) { - var cachedPlayer = _onlineCachedPlayers.First(p => p.PlayerNameHash == characterHash); + if (!_onlineCachedPlayers.TryGetValue(characterHash, out var cachedPlayer)) + { + return; + } + if (_dalamudUtil.IsInGpose) { _playerTokenDisposal.TryGetValue(cachedPlayer, out var cancellationTokenSource); @@ -202,14 +217,14 @@ public class OnlinePlayerManager : IDisposable } cachedPlayer.DisposePlayer(); - _onlineCachedPlayers.RemoveAll(c => c.PlayerNameHash == cachedPlayer.PlayerNameHash); + _onlineCachedPlayers.TryRemove(cachedPlayer.PlayerNameHash, out _); }, token); return; } cachedPlayer.DisposePlayer(); - _onlineCachedPlayers.RemoveAll(c => c.PlayerNameHash == cachedPlayer.PlayerNameHash); + _onlineCachedPlayers.TryRemove(characterHash, out _); } private void FrameworkOnUpdate(Framework framework) @@ -222,8 +237,7 @@ public class OnlinePlayerManager : IDisposable foreach (var pChar in playerCharacters) { var hashedName = Crypto.GetHash256(pChar); - var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName && !string.IsNullOrEmpty(p.PlayerName)); - if (existingCachedPlayer != null) + if (_onlineCachedPlayers.TryGetValue(hashedName, out var existingCachedPlayer) && !string.IsNullOrEmpty(existingCachedPlayer.PlayerName)) { existingCachedPlayer.IsVisible = true; continue; @@ -233,10 +247,14 @@ public class OnlinePlayerManager : IDisposable { _temporaryStoredCharacterCache.Remove(hashedName); } - _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pChar, cache); + + if (_onlineCachedPlayers.TryGetValue(hashedName, out var playerToInit)) + { + playerToInit.InitializePlayer(pChar, cache); + } } - var newlyVisiblePlayers = _onlineCachedPlayers + var newlyVisiblePlayers = _onlineCachedPlayers.Values .Where(p => p.PlayerCharacter != null && p.IsVisible && !p.WasVisible).Select(p => p.PlayerNameHash) .ToList(); if (newlyVisiblePlayers.Any())