something something performance
This commit is contained in:
@@ -11,11 +11,12 @@ namespace MareSynchronos.FileCache;
|
|||||||
|
|
||||||
public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
|
public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
|
||||||
{
|
{
|
||||||
|
private readonly HashSet<string> _cachedHandledPaths = new(StringComparer.Ordinal);
|
||||||
private readonly TransientConfigService _configurationService;
|
private readonly TransientConfigService _configurationService;
|
||||||
private readonly DalamudUtilService _dalamudUtil;
|
private readonly DalamudUtilService _dalamudUtil;
|
||||||
|
|
||||||
private readonly string[] _fileTypesToHandle = new[] { "tmb", "pap", "avfx", "atex", "sklb", "eid", "phyb", "scd", "skp", "shpk" };
|
private readonly string[] _fileTypesToHandle = new[] { "tmb", "pap", "avfx", "atex", "sklb", "eid", "phyb", "scd", "skp", "shpk" };
|
||||||
private readonly HashSet<GameObjectHandler> _playerRelatedPointers = new();
|
private readonly HashSet<GameObjectHandler> _playerRelatedPointers = new();
|
||||||
|
private HashSet<IntPtr> _cachedFrameAddresses = new();
|
||||||
|
|
||||||
public TransientResourceManager(ILogger<TransientResourceManager> logger, TransientConfigService configurationService,
|
public TransientResourceManager(ILogger<TransientResourceManager> logger, TransientConfigService configurationService,
|
||||||
DalamudUtilService dalamudUtil, MareMediator mediator) : base(logger, mediator)
|
DalamudUtilService dalamudUtil, MareMediator mediator) : base(logger, mediator)
|
||||||
@@ -60,7 +61,6 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string PlayerPersistentDataKey => _dalamudUtil.PlayerName + "_" + _dalamudUtil.WorldId;
|
private string PlayerPersistentDataKey => _dalamudUtil.PlayerName + "_" + _dalamudUtil.WorldId;
|
||||||
|
|
||||||
private ConcurrentDictionary<ObjectKind, HashSet<string>> SemiTransientResources { get; } = new();
|
private ConcurrentDictionary<ObjectKind, HashSet<string>> SemiTransientResources { get; } = new();
|
||||||
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
|
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
|
||||||
|
|
||||||
@@ -169,6 +169,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
private void DalamudUtil_FrameworkUpdate()
|
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())
|
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"));
|
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 gamePath = msg.GamePath.ToLowerInvariant();
|
||||||
var gameObject = msg.GameObject;
|
var gameObject = msg.GameObject;
|
||||||
var filePath = msg.FilePath;
|
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)))
|
if (!_fileTypesToHandle.Any(type => gamePath.EndsWith(type, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
|
_cachedHandledPaths.Add(gamePath);
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,18 +232,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
|
|||||||
TransientResources[gameObject] = new(StringComparer.OrdinalIgnoreCase);
|
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) ||
|
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);
|
Logger.LogTrace("Not adding {replacedPath} : {filePath}", replacedGamePath, filePath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
public async Task Initialize(string name)
|
public async Task Initialize(string name)
|
||||||
{
|
{
|
||||||
PlayerName = 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);
|
_originalGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false);
|
||||||
_lastGlamourerData = _originalGlamourerData;
|
_lastGlamourerData = _originalGlamourerData;
|
||||||
@@ -541,7 +541,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
private async Task RevertCustomizationData(ObjectKind objectKind, string name, Guid applicationId)
|
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;
|
if (address == IntPtr.Zero) return;
|
||||||
|
|
||||||
var cancelToken = new CancellationTokenSource();
|
var cancelToken = new CancellationTokenSource();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class DalamudUtilService : IHostedService
|
|||||||
private readonly List<uint> ClassJobIdsIgnoredForPets = new() { 30 };
|
private readonly List<uint> ClassJobIdsIgnoredForPets = new() { 30 };
|
||||||
private uint? _classJobId = 0;
|
private uint? _classJobId = 0;
|
||||||
private DateTime _delayedFrameworkUpdateCheck = DateTime.Now;
|
private DateTime _delayedFrameworkUpdateCheck = DateTime.Now;
|
||||||
|
private Dictionary<string, IntPtr> _playerCharas = new(StringComparer.Ordinal);
|
||||||
private bool _sentBetweenAreas = false;
|
private bool _sentBetweenAreas = false;
|
||||||
|
|
||||||
public DalamudUtilService(ILogger<DalamudUtilService> logger, ClientState clientState, ObjectTable objectTable, Framework framework,
|
public DalamudUtilService(ILogger<DalamudUtilService> logger, ClientState clientState, ObjectTable objectTable, Framework framework,
|
||||||
@@ -111,35 +112,20 @@ public class DalamudUtilService : IHostedService
|
|||||||
return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false);
|
return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerCharacter? GetPlayerCharacterFromObjectTableByName(string characterName)
|
public IntPtr GetPlayerCharacterFromObjectTableByName(string characterName)
|
||||||
{
|
{
|
||||||
foreach (var item in _objectTable)
|
if (_playerCharas.TryGetValue(characterName, out var pchar)) return pchar;
|
||||||
{
|
return IntPtr.Zero;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PlayerCharacter> GetPlayerCharacters()
|
public List<PlayerCharacter> GetPlayerCharacters()
|
||||||
{
|
{
|
||||||
return _objectTable.Where(obj =>
|
return _objectTable.OfType<PlayerCharacter>().ToList();
|
||||||
obj.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player &&
|
|
||||||
!string.Equals(obj.Name.ToString(), PlayerName, StringComparison.Ordinal)).Cast<PlayerCharacter>().ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe bool IsGameObjectPresent(IntPtr key)
|
public unsafe bool IsGameObjectPresent(IntPtr key)
|
||||||
{
|
{
|
||||||
foreach (var obj in _objectTable)
|
return _objectTable.Any(f => f.Address == key);
|
||||||
{
|
|
||||||
if (obj.Address == key)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "",
|
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "",
|
||||||
@@ -261,6 +247,9 @@ public class DalamudUtilService : IHostedService
|
|||||||
private unsafe void FrameworkOnUpdateInternal()
|
private unsafe void FrameworkOnUpdateInternal()
|
||||||
{
|
{
|
||||||
if (_clientState.LocalPlayer?.IsDead ?? false) return;
|
if (_clientState.LocalPlayer?.IsDead ?? false) return;
|
||||||
|
|
||||||
|
_playerCharas = _objectTable.OfType<PlayerCharacter>().ToDictionary(p => p.Name.ToString(), p => p.Address, StringComparer.Ordinal);
|
||||||
|
|
||||||
if (GposeTarget != null && !IsInGpose)
|
if (GposeTarget != null && !IsInGpose)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Gpose start");
|
_logger.LogDebug("Gpose start");
|
||||||
|
|||||||
Reference in New Issue
Block a user