Improve ObjTableToCharas efficiency

This commit is contained in:
Loporrit
2023-10-15 16:03:57 +00:00
parent 692aa41677
commit de9532041e

View File

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