potential fixes for mediator logspam

This commit is contained in:
rootdarkarchon
2023-02-19 22:24:54 +01:00
parent c66008aa42
commit d99a6f8294
6 changed files with 130 additions and 98 deletions

View File

@@ -230,16 +230,17 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
_downloadCancellationTokenSource?.Cancel(); _downloadCancellationTokenSource?.Cancel();
_downloadCancellationTokenSource?.Dispose(); _downloadCancellationTokenSource?.Dispose();
_downloadCancellationTokenSource = null; _downloadCancellationTokenSource = null;
if (PlayerCharacter != IntPtr.Zero) var ptr = PlayerCharacter;
_currentOtherChara?.Dispose();
_currentOtherChara = null;
if (ptr != IntPtr.Zero)
{ {
var ptr = PlayerCharacter;
foreach (var item in _cachedData.FileReplacements) foreach (var item in _cachedData.FileReplacements)
{ {
Task.Run(async () => await RevertCustomizationData(ptr, item.Key, name, applicationId).ConfigureAwait(false)); Task.Run(async () => await RevertCustomizationData(ptr, item.Key, name, applicationId).ConfigureAwait(false));
} }
} }
_currentOtherChara?.Dispose();
_currentOtherChara = null;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -288,12 +289,13 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
private async Task ApplyCustomizationData(Guid applicationId, KeyValuePair<ObjectKind, HashSet<PlayerChanges>> changes, API.Data.CharacterData charaData) private async Task ApplyCustomizationData(Guid applicationId, KeyValuePair<ObjectKind, HashSet<PlayerChanges>> changes, API.Data.CharacterData charaData)
{ {
if (PlayerCharacter == IntPtr.Zero) return; if (PlayerCharacter == IntPtr.Zero) return;
var ptr = PlayerCharacter;
var handler = changes.Key switch var handler = changes.Key switch
{ {
ObjectKind.Player => _currentOtherChara!, ObjectKind.Player => _currentOtherChara!,
ObjectKind.Companion => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(PlayerCharacter), isWatched: false), ObjectKind.Companion => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(ptr), isWatched: false),
ObjectKind.MinionOrMount => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetMinionOrMount(PlayerCharacter), isWatched: false), ObjectKind.MinionOrMount => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetMinionOrMount(ptr), isWatched: false),
ObjectKind.Pet => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(PlayerCharacter), isWatched: false), ObjectKind.Pet => _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(ptr), isWatched: false),
_ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key) _ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key)
}; };

View File

@@ -214,6 +214,10 @@ public class MarePlugin : MediatorSubscriberBase, IDisposable
_serviceProvider.GetRequiredService<PerformanceCollector>().PrintPerformanceStats(); _serviceProvider.GetRequiredService<PerformanceCollector>().PrintPerformanceStats();
} }
} }
else if (string.Equals(splitArgs[0], "medi", StringComparison.OrdinalIgnoreCase))
{
_serviceProvider.GetRequiredService<MareMediator>().PrintSubscriberInfo();
}
} }
private void OpenUi() private void OpenUi()

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>0.7.33</Version> <Version>0.7.34</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>

View File

@@ -1,6 +1,7 @@
using MareSynchronos.Utils; using MareSynchronos.Utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Diagnostics; using System.Diagnostics;
using System.Text;
namespace MareSynchronos.Mediator; namespace MareSynchronos.Mediator;
@@ -63,12 +64,33 @@ public class MareMediator : IDisposable
{ {
foreach (var kvp in _subscriberDict.ToList()) foreach (var kvp in _subscriberDict.ToList())
{ {
var unSubbed = kvp.Value.RemoveWhere(p => p.Subscriber == subscriber); var unSubbed = _subscriberDict[kvp.Key].RemoveWhere(p => p.Subscriber == subscriber);
if (unSubbed > 0) if (unSubbed > 0)
_logger.LogDebug("{sub} unsubscribed from {msg}", subscriber, kvp.Key.Name); _logger.LogDebug("{sub} unsubscribed from {msg}", subscriber, kvp.Key.Name);
} }
} }
public void PrintSubscriberInfo()
{
foreach (var kvp in _subscriberDict.ToList().SelectMany(c => c.Value.Select(v => v))
.DistinctBy(p => p.Subscriber).OrderBy(p => p.Subscriber.GetType().FullName, StringComparer.Ordinal))
{
_logger.LogInformation("Subscriber {type}: {sub}", kvp.Subscriber.GetType().FullName, kvp);
StringBuilder sb = new();
sb.Append("=> ");
foreach (var item in _subscriberDict.ToList())
{
if (item.Value.Any(v => v.Subscriber == kvp.Subscriber))
{
sb.Append(item.Key.Name + ", ");
}
}
if (!string.Equals(sb.ToString(), "=> ", StringComparison.Ordinal))
_logger.LogInformation("{sb}", sb.ToString());
_logger.LogInformation("---");
}
}
public void Dispose() public void Dispose()
{ {
_logger.LogTrace("Disposing {type}", GetType()); _logger.LogTrace("Disposing {type}", GetType());

View File

@@ -1,38 +1,27 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using System.Runtime.InteropServices;
using Penumbra.String;
using MareSynchronos.Mediator; using MareSynchronos.Mediator;
using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind;
using Microsoft.Extensions.Logging;
using MareSynchronos.Utils; using MareSynchronos.Utils;
using Microsoft.Extensions.Logging;
using Penumbra.String;
using System.Runtime.InteropServices;
using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind;
namespace MareSynchronos.Models; namespace MareSynchronos.Models;
public class GameObjectHandler : MediatorSubscriberBase public class GameObjectHandler : MediatorSubscriberBase
{ {
private readonly PerformanceCollector _performanceCollector;
private readonly MareMediator _mediator;
private readonly Func<IntPtr> _getAddress; private readonly Func<IntPtr> _getAddress;
private readonly bool _isOwnedObject; private readonly bool _isOwnedObject;
public unsafe Character* Character => (Character*)Address; private readonly MareMediator _mediator;
private readonly PerformanceCollector _performanceCollector;
public string Name { get; private set; } private CancellationTokenSource? _clearCts = new();
public ObjectKind ObjectKind { get; } private Task? _clearTask;
public IntPtr Address { get; set; }
public IntPtr CurrentAddress => _getAddress.Invoke();
private IntPtr DrawObjectAddress { get; set; }
private Task? _delayedZoningTask; private Task? _delayedZoningTask;
private CancellationTokenSource _zoningCts = new();
private bool _haltProcessing = false; private bool _haltProcessing = false;
private bool _ignoreSendAfterRedraw = false; private bool _ignoreSendAfterRedraw = false;
private CancellationTokenSource _zoningCts = new();
public override string ToString()
{
return $"{ObjectKind}:{Name} ({Address:X},{DrawObjectAddress:X})";
}
public GameObjectHandler(ILogger<GameObjectHandler> logger, PerformanceCollector performanceCollector, MareMediator mediator, ObjectKind objectKind, Func<IntPtr> getAddress, bool watchedObject = true) : base(logger, mediator) public GameObjectHandler(ILogger<GameObjectHandler> logger, PerformanceCollector performanceCollector, MareMediator mediator, ObjectKind objectKind, Func<IntPtr> getAddress, bool watchedObject = true) : base(logger, mediator)
{ {
_performanceCollector = performanceCollector; _performanceCollector = performanceCollector;
@@ -93,66 +82,34 @@ public class GameObjectHandler : MediatorSubscriberBase
CheckAndUpdateObject(); CheckAndUpdateObject();
} }
public IntPtr Address { get; set; }
public unsafe Character* Character => (Character*)Address;
public IntPtr CurrentAddress => _getAddress.Invoke();
public bool IsBeingDrawn { get; private set; }
public string Name { get; private set; }
public ObjectKind ObjectKind { get; }
private byte[] CustomizeData { get; set; } = new byte[26];
private IntPtr DrawObjectAddress { get; set; }
private byte[] EquipSlotData { get; set; } = new byte[40];
private byte? HatState { get; set; }
private byte? VisorWeaponState { get; set; }
public override void Dispose() public override void Dispose()
{ {
base.Dispose(); base.Dispose();
Mediator.Publish(new RemoveWatchedGameObjectHandler(this)); if (_isOwnedObject)
Mediator.Publish(new RemoveWatchedGameObjectHandler(this));
} }
private void FrameworkUpdate() public override string ToString()
{ {
if (!_delayedZoningTask?.IsCompleted ?? false) return; var owned = (_isOwnedObject ? "Self" : "Other");
return $"{owned}/{ObjectKind}:{Name} ({Address:X},{DrawObjectAddress:X})";
try
{
_performanceCollector.LogPerformance(this, "CheckAndUpdateObject>" + (_isOwnedObject ? "Self+" : "Other+") + ObjectKind + "/"
+ (string.IsNullOrEmpty(Name) ? "Unk" : Name) + "+" + Address.ToString("X"), CheckAndUpdateObject);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error during FrameworkUpdate of {this}", this);
}
} }
private void ZoneSwitchEnd()
{
if (!_isOwnedObject || _haltProcessing) return;
_clearCts?.Cancel();
_clearCts?.Dispose();
_clearCts = null;
_zoningCts.CancelAfter(2500);
}
private void ZoneSwitchStart()
{
if (!_isOwnedObject || _haltProcessing) return;
_zoningCts = new();
_logger.LogDebug("[{obj}] Starting Delay After Zoning", this);
_delayedZoningTask = Task.Run(async () =>
{
try
{
await Task.Delay(TimeSpan.FromSeconds(120), _zoningCts.Token).ConfigureAwait(false);
}
catch { }
finally
{
_logger.LogDebug("[{this}] Delay after zoning complete", this);
_zoningCts.Dispose();
}
});
}
public bool IsBeingDrawn { get; private set; }
private byte[] EquipSlotData { get; set; } = new byte[40];
private byte[] CustomizeData { get; set; } = new byte[26];
private Task? _clearTask;
private CancellationTokenSource? _clearCts = new();
private byte? HatState { get; set; }
private byte? VisorWeaponState { get; set; }
private unsafe void CheckAndUpdateObject() private unsafe void CheckAndUpdateObject()
{ {
if (_haltProcessing) return; if (_haltProcessing) return;
@@ -246,22 +203,6 @@ public class GameObjectHandler : MediatorSubscriberBase
_clearCts = null; _clearCts = null;
} }
private unsafe bool CompareAndUpdateEquipByteData(byte* equipSlotData)
{
bool hasChanges = false;
for (int i = 0; i < EquipSlotData.Length; i++)
{
var data = Marshal.ReadByte((IntPtr)equipSlotData, i);
if (EquipSlotData[i] != data)
{
EquipSlotData[i] = data;
hasChanges = true;
}
}
return hasChanges;
}
private unsafe bool CompareAndUpdateCustomizeData(byte* customizeData, out bool doNotSendUpdate) private unsafe bool CompareAndUpdateCustomizeData(byte* customizeData, out bool doNotSendUpdate)
{ {
bool hasChanges = false; bool hasChanges = false;
@@ -303,4 +244,66 @@ public class GameObjectHandler : MediatorSubscriberBase
return hasChanges; return hasChanges;
} }
}
private unsafe bool CompareAndUpdateEquipByteData(byte* equipSlotData)
{
bool hasChanges = false;
for (int i = 0; i < EquipSlotData.Length; i++)
{
var data = Marshal.ReadByte((IntPtr)equipSlotData, i);
if (EquipSlotData[i] != data)
{
EquipSlotData[i] = data;
hasChanges = true;
}
}
return hasChanges;
}
private void FrameworkUpdate()
{
if (!_delayedZoningTask?.IsCompleted ?? false) return;
try
{
_performanceCollector.LogPerformance(this, "CheckAndUpdateObject>" + (_isOwnedObject ? "Self+" : "Other+") + ObjectKind + "/"
+ (string.IsNullOrEmpty(Name) ? "Unk" : Name) + "+" + Address.ToString("X"), CheckAndUpdateObject);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error during FrameworkUpdate of {this}", this);
}
}
private void ZoneSwitchEnd()
{
if (!_isOwnedObject || _haltProcessing) return;
_clearCts?.Cancel();
_clearCts?.Dispose();
_clearCts = null;
_zoningCts.CancelAfter(2500);
}
private void ZoneSwitchStart()
{
if (!_isOwnedObject || _haltProcessing) return;
_zoningCts = new();
_logger.LogDebug("[{obj}] Starting Delay After Zoning", this);
_delayedZoningTask = Task.Run(async () =>
{
try
{
await Task.Delay(TimeSpan.FromSeconds(120), _zoningCts.Token).ConfigureAwait(false);
}
catch { }
finally
{
_logger.LogDebug("[{this}] Delay after zoning complete", this);
_zoningCts.Dispose();
}
});
}
}

View File

@@ -201,6 +201,7 @@ public class DalamudUtil : IDisposable
public unsafe IntPtr GetMinionOrMount(IntPtr? playerPointer = null) public unsafe IntPtr GetMinionOrMount(IntPtr? playerPointer = null)
{ {
playerPointer ??= PlayerPointer; playerPointer ??= PlayerPointer;
if (playerPointer == IntPtr.Zero) return IntPtr.Zero;
return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1); return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1);
} }