diff --git a/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs b/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs index ff6108c..aefd4aa 100644 --- a/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs +++ b/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs @@ -5,6 +5,7 @@ using MareSynchronos.Utils; using MareSynchronos.WebAPI; using MareSynchronos.WebAPI.Files; using Microsoft.Extensions.Logging; +using System.Linq; namespace MareSynchronos.PlayerData.Pairs; @@ -47,16 +48,9 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase var playerCharacters = _dalamudUtil.GetPlayerCharacters(); var newVisiblePlayers = new List(); - foreach (var pChar in playerCharacters) - { - var pair = _pairManager.FindPair(pChar); - if (pair == null) continue; - - if (pair.InitializePair(pChar.Name.ToString())) - { - newVisiblePlayers.Add(pair.UserData); - } - } + var chars = _pairManager.FindAllPairs(playerCharacters); + newVisiblePlayers.AddRange(from pChar in chars.Where(p => p.Pair != null && p.Pair.InitializePair(p.Character.Name.ToString())) + select pChar.Pair.UserData); if (newVisiblePlayers.Any()) { diff --git a/MareSynchronos/PlayerData/Pairs/Pair.cs b/MareSynchronos/PlayerData/Pairs/Pair.cs index abce7e2..268d5e3 100644 --- a/MareSynchronos/PlayerData/Pairs/Pair.cs +++ b/MareSynchronos/PlayerData/Pairs/Pair.cs @@ -45,22 +45,10 @@ public class Pair public CharacterData? LastReceivedCharacterData { get; set; } public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty; - public string GetPlayerNameHash() - { - try - { - return CachedPlayer?.PlayerNameHash ?? string.Empty; - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Error accessing PlayerNameHash, recreating CachedPlayer"); - RecreateCachedPlayer(); - } - - return string.Empty; - } public UserData UserData => UserPair?.User ?? GroupPair.First().Value.User; + public UserPairDto? UserPair { get; set; } + private CachedPlayer? CachedPlayer { get; set; } public void AddContextMenu(GameObjectContextMenuOpenArgs args) @@ -118,6 +106,21 @@ public class Pair return _serverConfigurationManager.GetNoteForUid(UserData.UID); } + public string GetPlayerNameHash() + { + try + { + return CachedPlayer?.PlayerNameHash ?? string.Empty; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Error accessing PlayerNameHash, recreating CachedPlayer"); + RecreateCachedPlayer(); + } + + return string.Empty; + } + public bool HasAnyConnection() { return UserPair != null || GroupPair.Any(); @@ -203,14 +206,14 @@ public class Pair if (disableAnimations || disableSounds) { _logger.LogTrace("Data cleaned up: Animations disabled: {disableAnimations}, Sounds disabled: {disableSounds}", disableAnimations, disableSounds); - foreach (var kvp in data.FileReplacements) + foreach (var objectKind in data.FileReplacements.Select(k => k.Key)) { if (disableSounds) - data.FileReplacements[kvp.Key] = data.FileReplacements[kvp.Key] + data.FileReplacements[objectKind] = data.FileReplacements[objectKind] .Where(f => !f.GamePaths.Any(p => p.EndsWith("scd", StringComparison.OrdinalIgnoreCase))) .ToList(); if (disableAnimations) - data.FileReplacements[kvp.Key] = data.FileReplacements[kvp.Key] + data.FileReplacements[objectKind] = data.FileReplacements[objectKind] .Where(f => !f.GamePaths.Any(p => p.EndsWith("tmb", StringComparison.OrdinalIgnoreCase) || p.EndsWith("pap", StringComparison.OrdinalIgnoreCase))) .ToList(); } diff --git a/MareSynchronos/PlayerData/Pairs/PairManager.cs b/MareSynchronos/PlayerData/Pairs/PairManager.cs index ff82f07..c3e581b 100644 --- a/MareSynchronos/PlayerData/Pairs/PairManager.cs +++ b/MareSynchronos/PlayerData/Pairs/PairManager.cs @@ -91,6 +91,11 @@ public sealed class PairManager : DisposableMediatorSubscriberBase RecreateLazy(); } + public List<(PlayerCharacter Character, Pair? Pair)> FindAllPairs(List playerCharacters) + { + return playerCharacters.Select(p => (p, _allClientPairs.Values.FirstOrDefault(f => string.Equals(p.GetHash256(), f.GetPlayerNameHash())))).ToList(); + } + public Pair? FindPair(PlayerCharacter? pChar) { if (pChar == null) return null; diff --git a/MareSynchronos/Utils/Crypto.cs b/MareSynchronos/Utils/Crypto.cs index a0cf4d6..7c9fca2 100644 --- a/MareSynchronos/Utils/Crypto.cs +++ b/MareSynchronos/Utils/Crypto.cs @@ -6,6 +6,9 @@ namespace MareSynchronos.Utils; public static class Crypto { + private static readonly Dictionary _hashListSHA1 = new(StringComparer.Ordinal); + private static readonly Dictionary _hashListSHA256 = new(StringComparer.Ordinal); + #pragma warning disable SYSLIB0021 // Type or member is obsolete public static string GetFileHash(this string filePath) @@ -16,20 +19,40 @@ public static class Crypto public static string GetHash(this string stringToHash) { - using SHA1CryptoServiceProvider cryptoProvider = new(); - return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToHash))).Replace("-", "", StringComparison.Ordinal); + return GetOrComputeHashSHA1(stringToHash); } public static string GetHash256(this string stringToHash) { - using SHA256CryptoServiceProvider cryptoProvider = new(); - return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToHash))).Replace("-", "", StringComparison.Ordinal); + return GetOrComputeHashSHA256(stringToHash); } public static string GetHash256(this PlayerCharacter character) { + var charName = character.Name + character.HomeWorld.Id.ToString(); + return GetOrComputeHashSHA256(charName); + } + + private static string GetOrComputeHashSHA1(string stringToCompute) + { + if (_hashListSHA1.TryGetValue(stringToCompute, out var hash)) + return hash; + + using SHA1CryptoServiceProvider cryptoProvider = new(); + var computedHash = BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal); + _hashListSHA1[stringToCompute] = computedHash; + return computedHash; + } + + private static string GetOrComputeHashSHA256(string stringToCompute) + { + if (_hashListSHA256.TryGetValue(stringToCompute, out var hash)) + return hash; + using SHA256CryptoServiceProvider cryptoProvider = new(); - return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(character.Name + character.HomeWorld.Id.ToString()))).Replace("-", "", StringComparison.Ordinal); + var computedHash = BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToCompute))).Replace("-", "", StringComparison.Ordinal); + _hashListSHA256[stringToCompute] = computedHash; + return computedHash; } #pragma warning restore SYSLIB0021 // Type or member is obsolete