diff --git a/MareSynchronos/Services/DalamudUtilService.cs b/MareSynchronos/Services/DalamudUtilService.cs index 4f5c812..aa7a69d 100644 --- a/MareSynchronos/Services/DalamudUtilService.cs +++ b/MareSynchronos/Services/DalamudUtilService.cs @@ -1,5 +1,6 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects; +using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.Character; @@ -18,6 +19,13 @@ namespace MareSynchronos.Services; public class DalamudUtilService : IHostedService, IMediatorSubscriber { + private struct PlayerInfo + { + public String Name; + public uint WorldId; + public String Hash; + }; + private readonly List _classJobIdsIgnoredForPets = [30]; private readonly IClientState _clientState; private readonly ICondition _condition; @@ -33,6 +41,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber private ushort _lastZone = 0; private Dictionary _playerCharas = new(StringComparer.Ordinal); private bool _sentBetweenAreas = false; + private static readonly Dictionary _playerInfoCache = new(); public DalamudUtilService(ILogger logger, IClientState clientState, IObjectTable objectTable, IFramework framework, IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, @@ -360,13 +369,28 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber return result; } + private PlayerInfo GetPlayerInfo(PlayerCharacter p) + { + uint id = p.ObjectId; + + if (!_playerInfoCache.TryGetValue(id, out var info)) + { + info.Name = p.Name.ToString(); + info.WorldId = p.HomeWorld.Id; + info.Hash = Crypto.GetHash256(info.Name + info.WorldId.ToString()); + _playerInfoCache[id] = info; + } + + return info; + } + private unsafe void CheckCharacterForDrawing(PlayerCharacter p) { if (!IsAnythingDrawing) { var gameObj = (GameObject*)p.Address; var drawObj = gameObj->DrawObject; - var playerName = p.Name.ToString(); + var playerInfo = GetPlayerInfo(p); bool isDrawing = false; bool isDrawingChanged = false; if ((nint)drawObj != IntPtr.Zero) @@ -378,20 +402,20 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber if (!isDrawing) { isDrawing = ((CharacterBase*)drawObj)->HasModelFilesInSlotLoaded != 0; - if (isDrawing && !string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal) + if (isDrawing && !string.Equals(_lastGlobalBlockPlayer, playerInfo.Name, StringComparison.Ordinal) && !string.Equals(_lastGlobalBlockReason, "HasModelFilesInSlotLoaded", StringComparison.Ordinal)) { - _lastGlobalBlockPlayer = playerName; + _lastGlobalBlockPlayer = playerInfo.Name; _lastGlobalBlockReason = "HasModelFilesInSlotLoaded"; isDrawingChanged = true; } } else { - if (!string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal) + if (!string.Equals(_lastGlobalBlockPlayer, playerInfo.Name, StringComparison.Ordinal) && !string.Equals(_lastGlobalBlockReason, "HasModelInSlotLoaded", StringComparison.Ordinal)) { - _lastGlobalBlockPlayer = playerName; + _lastGlobalBlockPlayer = playerInfo.Name; _lastGlobalBlockReason = "HasModelInSlotLoaded"; isDrawingChanged = true; } @@ -399,10 +423,10 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber } else { - if (!string.Equals(_lastGlobalBlockPlayer, playerName, StringComparison.Ordinal) + if (!string.Equals(_lastGlobalBlockPlayer, playerInfo.Name, StringComparison.Ordinal) && !string.Equals(_lastGlobalBlockReason, "RenderFlags", StringComparison.Ordinal)) { - _lastGlobalBlockPlayer = playerName; + _lastGlobalBlockPlayer = playerInfo.Name; _lastGlobalBlockReason = "RenderFlags"; isDrawingChanged = true; } @@ -411,7 +435,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber if (isDrawingChanged) { - _logger.LogTrace("Global draw block: START => {name} ({reason})", playerName, _lastGlobalBlockReason); + _logger.LogTrace("Global draw block: START => {name} ({reason})", playerInfo.Name, _lastGlobalBlockReason); } IsAnythingDrawing |= isDrawing; @@ -431,13 +455,17 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber } IsAnythingDrawing = false; - _playerCharas = _performanceCollector.LogPerformance(this, "ObjTableToCharas", - () => _objectTable.OfType().Where(o => o.ObjectIndex < 200) - .ToDictionary(p => p.GetHash256(), p => + _playerCharas.Clear(); + _performanceCollector.LogPerformance(this, "ObjTableToCharas", + () => { + foreach (var p in _objectTable.OfType().Where(o => o.ObjectIndex < 200)) { CheckCharacterForDrawing(p); - return (p.Name.ToString(), p.Address); - }, StringComparer.Ordinal)); + var info = GetPlayerInfo(p); + _playerCharas.Add(info.Hash, (info.Name, p.Address)); + } + } + ); if (!IsAnythingDrawing && !string.IsNullOrEmpty(_lastGlobalBlockPlayer)) { @@ -503,6 +531,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber _sentBetweenAreas = true; Mediator.Publish(new ZoneSwitchStartMessage()); Mediator.Publish(new HaltScanMessage(nameof(ConditionFlag.BetweenAreas))); + _playerInfoCache.Clear(); } }