the need for speed
This commit is contained in:
@@ -12,6 +12,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using MareSynchronos.PlayerData.Handlers;
|
using MareSynchronos.PlayerData.Handlers;
|
||||||
using MareSynchronos.Services.Mediator;
|
using MareSynchronos.Services.Mediator;
|
||||||
using MareSynchronos.Services;
|
using MareSynchronos.Services;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MareSynchronos.Interop;
|
namespace MareSynchronos.Interop;
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter;
|
private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter;
|
||||||
private readonly DalamudUtilService _dalamudUtil;
|
private readonly DalamudUtilService _dalamudUtil;
|
||||||
private readonly ICallGateSubscriber<int> _glamourerApiVersion;
|
private readonly ICallGateSubscriber<int> _glamourerApiVersion;
|
||||||
|
private readonly SemaphoreSlim _glamourerApplicationSemaphore = new(2);
|
||||||
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyAll;
|
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyAll;
|
||||||
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization;
|
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization;
|
||||||
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment;
|
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment;
|
||||||
@@ -212,30 +214,37 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
||||||
{
|
{
|
||||||
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
||||||
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
try
|
||||||
if (gameObj is Character c)
|
|
||||||
{
|
{
|
||||||
await PenumbraRedrawAsync(logger, handler, applicationId, () => _glamourerApplyAll!.InvokeAction(customization, c), fireAndForget, token).ConfigureAwait(false);
|
await _glamourerApplicationSemaphore.WaitAsync().ConfigureAwait(true);
|
||||||
|
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
||||||
|
if (gameObj is Character c)
|
||||||
|
{
|
||||||
|
await PenumbraRedrawAsync(logger, handler, applicationId, () => _glamourerApplyAll!.InvokeAction(customization, c), fireAndForget, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_glamourerApplicationSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GlamourerApplyOnlyCustomization(ILogger logger, GameObjectHandler handler, string customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
public async Task GlamourerApplyCustomizationAndEquipment(ILogger logger, GameObjectHandler handler, string customization, string equipment, Guid applicationid, CancellationToken token, bool fireAndForget = false)
|
||||||
{
|
{
|
||||||
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
||||||
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
try
|
||||||
if (gameObj is Character c)
|
|
||||||
{
|
{
|
||||||
await PenumbraRedrawAsync(logger, handler, applicationId, () => _glamourerApplyOnlyCustomization!.InvokeAction(customization, c), fireAndForget, token).ConfigureAwait(false);
|
await _glamourerApplicationSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
||||||
|
if (gameObj is Character c)
|
||||||
|
{
|
||||||
|
await PenumbraRedrawAsync(logger, handler, applicationid, () => _glamourerApplyOnlyEquipment!.InvokeAction(customization, c), fireAndForget, token).ConfigureAwait(false);
|
||||||
|
await PenumbraRedrawAsync(logger, handler, applicationid, () => _glamourerApplyOnlyEquipment!.InvokeAction(equipment, c), fireAndForget, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
finally
|
||||||
|
|
||||||
public async Task GlamourerApplyOnlyEquipment(ILogger logger, GameObjectHandler handler, string customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
|
||||||
{
|
|
||||||
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
|
||||||
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
|
||||||
if (gameObj is Character c)
|
|
||||||
{
|
{
|
||||||
await PenumbraRedrawAsync(logger, handler, applicationId, () => _glamourerApplyOnlyEquipment!.InvokeAction(customization, c), fireAndForget, token).ConfigureAwait(false);
|
_glamourerApplicationSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,11 +396,14 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
public async Task PenumbraRedraw(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
public async Task PenumbraRedraw(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
||||||
{
|
{
|
||||||
if (!CheckPenumbraApi() || _dalamudUtil.IsZoning) return;
|
if (!CheckPenumbraApi() || _dalamudUtil.IsZoning) return;
|
||||||
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
await _dalamudUtil.RunOnFrameworkThread(async () =>
|
||||||
if (gameObj is Character c)
|
|
||||||
{
|
{
|
||||||
await PenumbraRedrawAsync(logger, handler, applicationId, () => _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw), fireAndForget, token).ConfigureAwait(false);
|
var gameObj = _dalamudUtil.CreateGameObject(handler.Address);
|
||||||
}
|
if (gameObj is Character c)
|
||||||
|
{
|
||||||
|
await PenumbraRedrawAsync(logger, handler, applicationId, () => _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw), fireAndForget, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PenumbraRemoveTemporaryCollection(ILogger logger, Guid applicationId, string characterName)
|
public async Task PenumbraRemoveTemporaryCollection(ILogger logger, Guid applicationId, string characterName)
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
: ((GameObject*)_charaHandler!.Address)->ObjectID;
|
: ((GameObject*)_charaHandler!.Address)->ObjectID;
|
||||||
public string? PlayerName { get; private set; }
|
public string? PlayerName { get; private set; }
|
||||||
public string PlayerNameHash => OnlineUser.Ident;
|
public string PlayerNameHash => OnlineUser.Ident;
|
||||||
public uint? PlayerWorld { get; private set; }
|
|
||||||
|
|
||||||
public void ApplyCharacterData(CharacterData characterData, bool forced = false)
|
public void ApplyCharacterData(CharacterData characterData, bool forced = false)
|
||||||
{
|
{
|
||||||
@@ -157,7 +156,6 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
SetUploading(false);
|
SetUploading(false);
|
||||||
_downloadManager.Dispose();
|
_downloadManager.Dispose();
|
||||||
var name = PlayerName;
|
var name = PlayerName;
|
||||||
var world = PlayerWorld;
|
|
||||||
Logger.LogDebug("Disposing {name} ({user})", name, OnlineUser);
|
Logger.LogDebug("Disposing {name} ({user})", name, OnlineUser);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -180,7 +178,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RevertCustomizationData(item.Key, name, world ?? 0, applicationId).GetAwaiter().GetResult();
|
RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
@@ -469,6 +467,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
foreach (var kind in updatedData)
|
foreach (var kind in updatedData)
|
||||||
{
|
{
|
||||||
await ApplyCustomizationData(_applicationId, kind, charaData, token).ConfigureAwait(false);
|
await ApplyCustomizationData(_applicationId, kind, charaData, token).ConfigureAwait(false);
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.LogDebug("[{applicationId}] Application finished", _applicationId);
|
Logger.LogDebug("[{applicationId}] Application finished", _applicationId);
|
||||||
@@ -488,7 +487,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
var pc = _dalamudUtil.FindPlayerByNameHash(OnlineUser.Ident);
|
var pc = _dalamudUtil.FindPlayerByNameHash(OnlineUser.Ident);
|
||||||
if (pc == null) return;
|
if (pc == null) return;
|
||||||
Logger.LogDebug("One-Time Initializing {this}", this);
|
Logger.LogDebug("One-Time Initializing {this}", this);
|
||||||
Initialize(pc.Name.ToString(), pc.HomeWorld.Id);
|
Initialize(pc.Name.ToString());
|
||||||
Logger.LogDebug("One-Time Initialized {this}", this);
|
Logger.LogDebug("One-Time Initialized {this}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,10 +497,13 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
Mediator.Publish(new CachedPlayerVisibleMessage(this));
|
Mediator.Publish(new CachedPlayerVisibleMessage(this));
|
||||||
Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible);
|
Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible);
|
||||||
_framesSinceNotVisible = 0;
|
_framesSinceNotVisible = 0;
|
||||||
_lastGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).GetAwaiter().GetResult();
|
|
||||||
if (_cachedData != null)
|
if (_cachedData != null)
|
||||||
{
|
{
|
||||||
Task.Run(() => ApplyCharacterData(_cachedData, true));
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
_lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false);
|
||||||
|
ApplyCharacterData(_cachedData, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_charaHandler?.Address == IntPtr.Zero && IsVisible)
|
else if (_charaHandler?.Address == IntPtr.Zero && IsVisible)
|
||||||
@@ -515,11 +517,10 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Initialize(string name, uint worldid)
|
private void Initialize(string name)
|
||||||
{
|
{
|
||||||
PlayerName = name;
|
PlayerName = name;
|
||||||
PlayerWorld = worldid;
|
_charaHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false);
|
||||||
_charaHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName, worldid), false);
|
|
||||||
|
|
||||||
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult();
|
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
_lastGlamourerData = _originalGlamourerData;
|
_lastGlamourerData = _originalGlamourerData;
|
||||||
@@ -589,13 +590,13 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RevertCustomizationData(ObjectKind objectKind, string name, uint world, Guid applicationId)
|
private async Task RevertCustomizationData(ObjectKind objectKind, string name, Guid applicationId)
|
||||||
{
|
{
|
||||||
nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(name, world);
|
nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident);
|
||||||
if (address == IntPtr.Zero) return;
|
if (address == IntPtr.Zero) return;
|
||||||
|
|
||||||
var cancelToken = new CancellationTokenSource();
|
var cancelToken = new CancellationTokenSource();
|
||||||
cancelToken.CancelAfter(TimeSpan.FromSeconds(10));
|
cancelToken.CancelAfter(TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
Logger.LogDebug("[{applicationId}] Reverting all Customization for {alias}/{name} {objectKind}", applicationId, OnlineUser.User.AliasOrUID, name, objectKind);
|
Logger.LogDebug("[{applicationId}] Reverting all Customization for {alias}/{name} {objectKind}", applicationId, OnlineUser.User.AliasOrUID, name, objectKind);
|
||||||
|
|
||||||
@@ -603,11 +604,8 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => address, false);
|
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => address, false);
|
||||||
CheckForNameAndThrow(tempHandler, name);
|
CheckForNameAndThrow(tempHandler, name);
|
||||||
Logger.LogDebug("[{applicationId}] Restoring Customization for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData);
|
Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData);
|
||||||
await _ipcManager.GlamourerApplyOnlyCustomization(Logger, tempHandler, _originalGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
|
await _ipcManager.GlamourerApplyCustomizationAndEquipment(Logger, tempHandler, _originalGlamourerData, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
|
||||||
CheckForNameAndThrow(tempHandler, name);
|
|
||||||
Logger.LogDebug("[{applicationId}] Restoring Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _lastGlamourerData);
|
|
||||||
await _ipcManager.GlamourerApplyOnlyEquipment(Logger, tempHandler, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
|
|
||||||
CheckForNameAndThrow(tempHandler, name);
|
CheckForNameAndThrow(tempHandler, name);
|
||||||
Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
|
Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
|
||||||
await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false);
|
await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace MareSynchronos.PlayerData.Pairs;
|
|||||||
public class Pair
|
public class Pair
|
||||||
{
|
{
|
||||||
private readonly Func<OnlineUserIdentDto, CachedPlayer> _cachedPlayerFactory;
|
private readonly Func<OnlineUserIdentDto, CachedPlayer> _cachedPlayerFactory;
|
||||||
|
private readonly SemaphoreSlim _creationSemaphore = new(1);
|
||||||
private readonly ILogger<Pair> _logger;
|
private readonly ILogger<Pair> _logger;
|
||||||
private readonly MareMediator _mediator;
|
private readonly MareMediator _mediator;
|
||||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||||
@@ -89,19 +90,28 @@ public class Pair
|
|||||||
|
|
||||||
public void CreateCachedPlayer(OnlineUserIdentDto? dto = null)
|
public void CreateCachedPlayer(OnlineUserIdentDto? dto = null)
|
||||||
{
|
{
|
||||||
if (dto == null && _onlineUserIdentDto == null)
|
try
|
||||||
{
|
{
|
||||||
CachedPlayer?.Dispose();
|
_creationSemaphore.Wait();
|
||||||
CachedPlayer = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dto != null)
|
|
||||||
{
|
|
||||||
_onlineUserIdentDto = dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
CachedPlayer?.Dispose();
|
if (dto == null && _onlineUserIdentDto == null)
|
||||||
CachedPlayer = _cachedPlayerFactory(_onlineUserIdentDto!);
|
{
|
||||||
|
CachedPlayer?.Dispose();
|
||||||
|
CachedPlayer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dto != null)
|
||||||
|
{
|
||||||
|
_onlineUserIdentDto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedPlayer?.Dispose();
|
||||||
|
CachedPlayer = _cachedPlayerFactory(_onlineUserIdentDto!);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_creationSemaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetNote()
|
public string? GetNote()
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Dalamud.ContextMenu;
|
using Dalamud.ContextMenu;
|
||||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using MareSynchronos.API.Data;
|
using MareSynchronos.API.Data;
|
||||||
using MareSynchronos.API.Data.Comparer;
|
using MareSynchronos.API.Data.Comparer;
|
||||||
@@ -8,7 +7,6 @@ using MareSynchronos.API.Dto.Group;
|
|||||||
using MareSynchronos.API.Dto.User;
|
using MareSynchronos.API.Dto.User;
|
||||||
using MareSynchronos.MareConfiguration;
|
using MareSynchronos.MareConfiguration;
|
||||||
using MareSynchronos.Services.Mediator;
|
using MareSynchronos.Services.Mediator;
|
||||||
using MareSynchronos.Utils;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
@@ -20,7 +18,6 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
|||||||
private readonly ConcurrentDictionary<GroupData, GroupFullInfoDto> _allGroups = new(GroupDataComparer.Instance);
|
private readonly ConcurrentDictionary<GroupData, GroupFullInfoDto> _allGroups = new(GroupDataComparer.Instance);
|
||||||
private readonly MareConfigService _configurationService;
|
private readonly MareConfigService _configurationService;
|
||||||
private readonly DalamudContextMenu _dalamudContextMenu;
|
private readonly DalamudContextMenu _dalamudContextMenu;
|
||||||
private readonly Dictionary<string, Pair> _indexedPairs = new(StringComparer.Ordinal);
|
|
||||||
private readonly Func<Pair> _pairFactory;
|
private readonly Func<Pair> _pairFactory;
|
||||||
private Lazy<List<Pair>> _directPairsInternal;
|
private Lazy<List<Pair>> _directPairsInternal;
|
||||||
private Lazy<Dictionary<GroupFullInfoDto, List<Pair>>> _groupPairsInternal;
|
private Lazy<Dictionary<GroupFullInfoDto, List<Pair>>> _groupPairsInternal;
|
||||||
@@ -32,7 +29,6 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
|||||||
_pairFactory = pairFactory;
|
_pairFactory = pairFactory;
|
||||||
_configurationService = configurationService;
|
_configurationService = configurationService;
|
||||||
_dalamudContextMenu = dalamudContextMenu;
|
_dalamudContextMenu = dalamudContextMenu;
|
||||||
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => DalamudUtilOnDelayedFrameworkUpdate());
|
|
||||||
Mediator.Subscribe<DisconnectedMessage>(this, (_) => ClearPairs());
|
Mediator.Subscribe<DisconnectedMessage>(this, (_) => ClearPairs());
|
||||||
Mediator.Subscribe<CutsceneEndMessage>(this, (_) => ReapplyPairData());
|
Mediator.Subscribe<CutsceneEndMessage>(this, (_) => ReapplyPairData());
|
||||||
_directPairsInternal = DirectPairsLazy();
|
_directPairsInternal = DirectPairsLazy();
|
||||||
@@ -89,18 +85,6 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
|||||||
RecreateLazy();
|
RecreateLazy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(PlayerCharacter Character, Pair Pair)> FindAllPairs(List<PlayerCharacter> playerCharacters)
|
|
||||||
{
|
|
||||||
return playerCharacters.Select(p => (p, _indexedPairs.TryGetValue(p.GetHash256(), out var pair) ? pair : null)).Where(p => p.Item2 != null).ToList()!;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pair? FindPair(PlayerCharacter? pChar)
|
|
||||||
{
|
|
||||||
if (pChar == null) return null;
|
|
||||||
var hash = pChar.GetHash256();
|
|
||||||
return _allClientPairs.Values.FirstOrDefault(f => string.Equals(hash, f.GetPlayerNameHash()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Pair> GetOnlineUserPairs() => _allClientPairs.Where(p => !string.IsNullOrEmpty(p.Value.GetPlayerNameHash())).Select(p => p.Value).ToList();
|
public List<Pair> GetOnlineUserPairs() => _allClientPairs.Where(p => !string.IsNullOrEmpty(p.Value.GetPlayerNameHash())).Select(p => p.Value).ToList();
|
||||||
|
|
||||||
public List<UserData> GetVisibleUsers() => _allClientPairs.Where(p => p.Value.IsVisible).Select(p => p.Key).ToList();
|
public List<UserData> GetVisibleUsers() => _allClientPairs.Where(p => p.Value.IsVisible).Select(p => p.Key).ToList();
|
||||||
@@ -341,17 +325,6 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DalamudUtilOnDelayedFrameworkUpdate()
|
|
||||||
{
|
|
||||||
_indexedPairs.Clear();
|
|
||||||
foreach (var pair in _allClientPairs.Values.Where(p => string.IsNullOrEmpty(p.PlayerName)))
|
|
||||||
{
|
|
||||||
var hash = pair.GetPlayerNameHash();
|
|
||||||
if (string.IsNullOrEmpty(hash)) continue;
|
|
||||||
_indexedPairs[hash] = pair;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Lazy<List<Pair>> DirectPairsLazy() => new(() => _allClientPairs.Select(k => k.Value).Where(k => k.UserPair != null).ToList());
|
private Lazy<List<Pair>> DirectPairsLazy() => new(() => _allClientPairs.Select(k => k.Value).Where(k => k.UserPair != null).ToList());
|
||||||
|
|
||||||
private void DisposePairs()
|
private void DisposePairs()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using MareSynchronos.Services.Mediator;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Globalization;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
||||||
@@ -31,7 +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 Dictionary<string, PlayerCharacter> _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,
|
||||||
@@ -113,17 +112,12 @@ public class DalamudUtilService : IHostedService
|
|||||||
return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false);
|
return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntPtr GetPlayerCharacterFromObjectTableByName(string characterName, uint worldid)
|
public IntPtr GetPlayerCharacterFromObjectTableByIdent(string characterName)
|
||||||
{
|
{
|
||||||
if (_playerCharas.TryGetValue(characterName + worldid.ToString(CultureInfo.InvariantCulture), out var pchar)) return pchar;
|
if (_playerCharas.TryGetValue(characterName, out var pchar)) return pchar.Address;
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PlayerCharacter> GetPlayerCharacters()
|
|
||||||
{
|
|
||||||
return _objectTable.OfType<PlayerCharacter>().ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe bool IsGameObjectPresent(IntPtr key)
|
public unsafe bool IsGameObjectPresent(IntPtr key)
|
||||||
{
|
{
|
||||||
return _objectTable.Any(f => f.Address == key);
|
return _objectTable.Any(f => f.Address == key);
|
||||||
@@ -238,7 +232,8 @@ public class DalamudUtilService : IHostedService
|
|||||||
|
|
||||||
internal PlayerCharacter? FindPlayerByNameHash(string ident)
|
internal PlayerCharacter? FindPlayerByNameHash(string ident)
|
||||||
{
|
{
|
||||||
return _objectTable.OfType<PlayerCharacter>().FirstOrDefault(p => p.GetHash256().Equals(ident, StringComparison.Ordinal));
|
_playerCharas.TryGetValue(ident, out var result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FrameworkOnUpdate(Framework framework)
|
private void FrameworkOnUpdate(Framework framework)
|
||||||
@@ -250,7 +245,7 @@ public class DalamudUtilService : IHostedService
|
|||||||
{
|
{
|
||||||
if (_clientState.LocalPlayer?.IsDead ?? false) return;
|
if (_clientState.LocalPlayer?.IsDead ?? false) return;
|
||||||
|
|
||||||
_playerCharas = _objectTable.OfType<PlayerCharacter>().ToDictionary(p => p.Name.ToString() + p.HomeWorld.Id.ToString(), p => p.Address, StringComparer.Ordinal);
|
_playerCharas = _performanceCollector.LogPerformance(this, "ObjTableToCharas", () => _objectTable.OfType<PlayerCharacter>().ToDictionary(p => p.GetHash256(), p => p, StringComparer.Ordinal));
|
||||||
|
|
||||||
if (GposeTarget != null && !IsInGpose)
|
if (GposeTarget != null && !IsInGpose)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public sealed class MareMediator : IHostedService
|
|||||||
private void ExecuteSubscriber<T>(SubscriberAction subscriber, T message) where T : MessageBase
|
private void ExecuteSubscriber<T>(SubscriberAction subscriber, T message) where T : MessageBase
|
||||||
{
|
{
|
||||||
var isSameThread = message.KeepThreadContext ? "$" : string.Empty;
|
var isSameThread = message.KeepThreadContext ? "$" : string.Empty;
|
||||||
_performanceCollector.LogPerformance(this, $"{isSameThread}Execute>{message.GetType().Name}+{subscriber.Subscriber.GetType().Name}", () => ((Action<T>)subscriber.Action).Invoke(message));
|
_performanceCollector.LogPerformance(this, $"{isSameThread}Execute>{message.GetType().Name}+{subscriber.Subscriber.GetType().Name}>{subscriber.Subscriber}", () => ((Action<T>)subscriber.Action).Invoke(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SubscriberAction
|
private sealed class SubscriberAction
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public record DisconnectedMessage : SameThreadMessage;
|
|||||||
public record PenumbraModSettingChangedMessage : MessageBase;
|
public record PenumbraModSettingChangedMessage : MessageBase;
|
||||||
public record PenumbraInitializedMessage : MessageBase;
|
public record PenumbraInitializedMessage : MessageBase;
|
||||||
public record PenumbraDisposedMessage : MessageBase;
|
public record PenumbraDisposedMessage : MessageBase;
|
||||||
public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx, bool WasRequested) : MessageBase;
|
public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx, bool WasRequested) : SameThreadMessage;
|
||||||
public record HeelsOffsetMessage : MessageBase;
|
public record HeelsOffsetMessage : MessageBase;
|
||||||
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : SameThreadMessage;
|
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : SameThreadMessage;
|
||||||
public record CustomizePlusMessage : MessageBase;
|
public record CustomizePlusMessage : MessageBase;
|
||||||
|
|||||||
@@ -130,22 +130,14 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
sb.Append((" " + TimeSpan.FromTicks(pastEntries.Max(m => m.Item2)).TotalMilliseconds.ToString("0.00000", CultureInfo.InvariantCulture)).PadRight(15));
|
sb.Append((" " + TimeSpan.FromTicks(pastEntries.Max(m => m.Item2)).TotalMilliseconds.ToString("0.00000", CultureInfo.InvariantCulture)).PadRight(15));
|
||||||
sb.Append('|');
|
sb.Append('|');
|
||||||
sb.Append((" " + TimeSpan.FromTicks((long)pastEntries.Average(m => m.Item2)).TotalMilliseconds.ToString("0.00000", CultureInfo.InvariantCulture)).PadRight(15));
|
sb.Append((" " + TimeSpan.FromTicks((long)pastEntries.Average(m => m.Item2)).TotalMilliseconds.ToString("0.00000", CultureInfo.InvariantCulture)).PadRight(15));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(" -".PadRight(15));
|
|
||||||
sb.Append('|');
|
sb.Append('|');
|
||||||
sb.Append(" -".PadRight(15));
|
sb.Append((" " + (pastEntries.LastOrDefault()?.Item1.ToString("HH:mm:ss.ffff", CultureInfo.InvariantCulture) ?? "-")).PadRight(15, ' '));
|
||||||
sb.Append('|');
|
sb.Append('|');
|
||||||
sb.Append(" -".PadRight(15));
|
sb.Append((" " + pastEntries.Count).PadRight(10));
|
||||||
|
sb.Append('|');
|
||||||
|
sb.Append(' ').Append(entry.Key);
|
||||||
|
sb.AppendLine();
|
||||||
}
|
}
|
||||||
sb.Append('|');
|
|
||||||
sb.Append((" " + (pastEntries.LastOrDefault()?.Item1.ToString("HH:mm:ss.ffff", CultureInfo.InvariantCulture) ?? "-")).PadRight(15, ' '));
|
|
||||||
sb.Append('|');
|
|
||||||
sb.Append((" " + pastEntries.Count).PadRight(10));
|
|
||||||
sb.Append('|');
|
|
||||||
sb.Append(' ').Append(entry.Key);
|
|
||||||
sb.AppendLine();
|
|
||||||
|
|
||||||
previousCaller = newCaller;
|
previousCaller = newCaller;
|
||||||
}
|
}
|
||||||
@@ -182,9 +174,9 @@ public sealed class PerformanceCollectorService : IHostedService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var last = entries.Value.ToList()[^1];
|
var last = entries.Value.ToList()[^1];
|
||||||
if (last.Item1.AddMinutes(10) < TimeOnly.FromDateTime(DateTime.Now))
|
if (last.Item1.AddMinutes(10) < TimeOnly.FromDateTime(DateTime.Now) && !_performanceCounters.TryRemove(entries.Key, out _))
|
||||||
{
|
{
|
||||||
_performanceCounters.Remove(entries.Key, out _);
|
_logger.LogDebug("Could not remove performance counter {counter}", entries.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
Reference in New Issue
Block a user