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.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<uint> _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<string, (string Name, nint Address)> _playerCharas = new(StringComparer.Ordinal);
private bool _sentBetweenAreas = false;
private static readonly Dictionary<uint, PlayerInfo> _playerInfoCache = new();
public DalamudUtilService(ILogger<DalamudUtilService> 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<PlayerCharacter>().Where(o => o.ObjectIndex < 200)
.ToDictionary(p => p.GetHash256(), p =>
_playerCharas.Clear();
_performanceCollector.LogPerformance(this, "ObjTableToCharas",
() => {
foreach (var p in _objectTable.OfType<PlayerCharacter>().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();
}
}