diff --git a/MareSynchronos/FileCache/TransientResourceManager.cs b/MareSynchronos/FileCache/TransientResourceManager.cs index c1d19ed..55052bc 100644 --- a/MareSynchronos/FileCache/TransientResourceManager.cs +++ b/MareSynchronos/FileCache/TransientResourceManager.cs @@ -11,11 +11,12 @@ namespace MareSynchronos.FileCache; public sealed class TransientResourceManager : DisposableMediatorSubscriberBase { + private readonly HashSet _cachedHandledPaths = new(StringComparer.Ordinal); private readonly TransientConfigService _configurationService; private readonly DalamudUtilService _dalamudUtil; - private readonly string[] _fileTypesToHandle = new[] { "tmb", "pap", "avfx", "atex", "sklb", "eid", "phyb", "scd", "skp", "shpk" }; private readonly HashSet _playerRelatedPointers = new(); + private HashSet _cachedFrameAddresses = new(); public TransientResourceManager(ILogger logger, TransientConfigService configurationService, DalamudUtilService dalamudUtil, MareMediator mediator) : base(logger, mediator) @@ -60,7 +61,6 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase } private string PlayerPersistentDataKey => _dalamudUtil.PlayerName + "_" + _dalamudUtil.WorldId; - private ConcurrentDictionary> SemiTransientResources { get; } = new(); private ConcurrentDictionary> TransientResources { get; } = new(); @@ -169,6 +169,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase private void DalamudUtil_FrameworkUpdate() { + _cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress).ToHashSet(); + _cachedHandledPaths.Clear(); foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList()) { Logger.LogDebug("Object not present anymore: {addr}", item.ToString("X")); @@ -193,13 +195,35 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase var gamePath = msg.GamePath.ToLowerInvariant(); var gameObject = msg.GameObject; var filePath = msg.FilePath; + + // ignore files already processed this frame + if (_cachedHandledPaths.Contains(gamePath)) return; + + _cachedHandledPaths.Add(gamePath); + + // replace individual mtrl stuff + if (filePath.StartsWith("|", StringComparison.OrdinalIgnoreCase)) + { + filePath = filePath.Split("|")[2]; + } + // replace filepath + filePath = filePath.ToLowerInvariant().Replace("\\", "/", StringComparison.OrdinalIgnoreCase); + + // ignore files that are the same + var replacedGamePath = gamePath.ToLowerInvariant().Replace("\\", "/", StringComparison.OrdinalIgnoreCase); + if (string.Equals(filePath, replacedGamePath, StringComparison.OrdinalIgnoreCase)) return; + + // ignore files to not handle if (!_fileTypesToHandle.Any(type => gamePath.EndsWith(type, StringComparison.OrdinalIgnoreCase))) { + _cachedHandledPaths.Add(gamePath); return; } - if (!_playerRelatedPointers.Select(p => p.CurrentAddress).Contains(gameObject)) + + // ignore files not belonging to anything player related + if (!_cachedFrameAddresses.Contains(gameObject)) { - //_logger.LogDebug("Got resource " + gamePath + " for ptr " + gameObject.ToString("X")); + _cachedHandledPaths.Add(gamePath); return; } @@ -208,18 +232,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase TransientResources[gameObject] = new(StringComparer.OrdinalIgnoreCase); } - if (filePath.StartsWith("|", StringComparison.OrdinalIgnoreCase)) - { - filePath = filePath.Split("|")[2]; - } - - filePath = filePath.ToLowerInvariant().Replace("\\", "/", StringComparison.OrdinalIgnoreCase); - - var replacedGamePath = gamePath.ToLowerInvariant().Replace("\\", "/", StringComparison.OrdinalIgnoreCase); - if (string.Equals(filePath, replacedGamePath, StringComparison.OrdinalIgnoreCase)) return; - if (TransientResources[gameObject].Contains(replacedGamePath) || - SemiTransientResources.Any(r => r.Value.Any(f => string.Equals(f, gamePath, StringComparison.OrdinalIgnoreCase)))) + SemiTransientResources.SelectMany(k => k.Value).Any(f => string.Equals(f, gamePath, StringComparison.OrdinalIgnoreCase))) { Logger.LogTrace("Not adding {replacedPath} : {filePath}", replacedGamePath, filePath); } diff --git a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs index fd57438..baa10ae 100644 --- a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs +++ b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs @@ -119,7 +119,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase public async Task Initialize(string name) { PlayerName = name; - _charaHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName)?.Address ?? IntPtr.Zero, false); + _charaHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName), false); _originalGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false); _lastGlamourerData = _originalGlamourerData; @@ -541,7 +541,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase private async Task RevertCustomizationData(ObjectKind objectKind, string name, Guid applicationId) { - nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(name)?.Address ?? IntPtr.Zero; + nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(name); if (address == IntPtr.Zero) return; var cancelToken = new CancellationTokenSource(); diff --git a/MareSynchronos/Services/DalamudUtilService.cs b/MareSynchronos/Services/DalamudUtilService.cs index 9259671..4cbdd05 100644 --- a/MareSynchronos/Services/DalamudUtilService.cs +++ b/MareSynchronos/Services/DalamudUtilService.cs @@ -30,6 +30,7 @@ public class DalamudUtilService : IHostedService private readonly List ClassJobIdsIgnoredForPets = new() { 30 }; private uint? _classJobId = 0; private DateTime _delayedFrameworkUpdateCheck = DateTime.Now; + private Dictionary _playerCharas = new(StringComparer.Ordinal); private bool _sentBetweenAreas = false; public DalamudUtilService(ILogger logger, ClientState clientState, ObjectTable objectTable, Framework framework, @@ -111,35 +112,20 @@ public class DalamudUtilService : IHostedService return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false); } - public PlayerCharacter? GetPlayerCharacterFromObjectTableByName(string characterName) + public IntPtr GetPlayerCharacterFromObjectTableByName(string characterName) { - foreach (var item in _objectTable) - { - if (item.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) continue; - if (string.Equals(item.Name.ToString(), characterName, StringComparison.Ordinal)) return (PlayerCharacter)item; - } - - return null; + if (_playerCharas.TryGetValue(characterName, out var pchar)) return pchar; + return IntPtr.Zero; } public List GetPlayerCharacters() { - return _objectTable.Where(obj => - obj.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player && - !string.Equals(obj.Name.ToString(), PlayerName, StringComparison.Ordinal)).Cast().ToList(); + return _objectTable.OfType().ToList(); } public unsafe bool IsGameObjectPresent(IntPtr key) { - foreach (var obj in _objectTable) - { - if (obj.Address == key) - { - return true; - } - } - - return false; + return _objectTable.Any(f => f.Address == key); } public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "", @@ -261,6 +247,9 @@ public class DalamudUtilService : IHostedService private unsafe void FrameworkOnUpdateInternal() { if (_clientState.LocalPlayer?.IsDead ?? false) return; + + _playerCharas = _objectTable.OfType().ToDictionary(p => p.Name.ToString(), p => p.Address, StringComparer.Ordinal); + if (GposeTarget != null && !IsInGpose) { _logger.LogDebug("Gpose start");