async waitwhilecharacterisdrawing
This commit is contained in:
@@ -131,7 +131,7 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait until chara is not drawing and present so nothing spontaneously explodes
|
// wait until chara is not drawing and present so nothing spontaneously explodes
|
||||||
_dalamudUtil.WaitWhileCharacterIsDrawing(_logger, playerRelatedObject, Guid.NewGuid(), 30000, ct: token);
|
await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, playerRelatedObject, Guid.NewGuid(), 30000, ct: token).ConfigureAwait(false);
|
||||||
int totalWaitTime = 10000;
|
int totalWaitTime = 10000;
|
||||||
while (!DalamudUtil.IsObjectPresent(_dalamudUtil.CreateGameObject(charaPointer)) && totalWaitTime > 0)
|
while (!DalamudUtil.IsObjectPresent(_dalamudUtil.CreateGameObject(charaPointer)) && totalWaitTime > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,16 +11,18 @@ public class GameObjectHandlerFactory
|
|||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly MareMediator _mediator;
|
private readonly MareMediator _mediator;
|
||||||
private readonly PerformanceCollector _performanceCollector;
|
private readonly PerformanceCollector _performanceCollector;
|
||||||
|
private readonly DalamudUtil _dalamudUtil;
|
||||||
|
|
||||||
public GameObjectHandlerFactory(ILoggerFactory loggerFactory, MareMediator mediator, PerformanceCollector performanceCollector)
|
public GameObjectHandlerFactory(ILoggerFactory loggerFactory, MareMediator mediator, PerformanceCollector performanceCollector, DalamudUtil dalamudUtil)
|
||||||
{
|
{
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
_performanceCollector = performanceCollector;
|
_performanceCollector = performanceCollector;
|
||||||
|
_dalamudUtil = dalamudUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameObjectHandler Create(ObjectKind objectKind, Func<IntPtr> getAddress, bool isWatched)
|
public GameObjectHandler Create(ObjectKind objectKind, Func<IntPtr> getAddress, bool isWatched)
|
||||||
{
|
{
|
||||||
return new GameObjectHandler(_loggerFactory.CreateLogger<GameObjectHandler>(), _performanceCollector, _mediator, objectKind, getAddress, isWatched);
|
return new GameObjectHandler(_loggerFactory.CreateLogger<GameObjectHandler>(), _performanceCollector, _mediator, _dalamudUtil, objectKind, getAddress, isWatched);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,7 +310,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("[{applicationId}] Applying Customization Data for {handler}", applicationId, handler);
|
_logger.LogDebug("[{applicationId}] Applying Customization Data for {handler}", applicationId, handler);
|
||||||
_dalamudUtil.WaitWhileCharacterIsDrawing(_logger, handler, applicationId, 30000);
|
await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, handler, applicationId, 30000).ConfigureAwait(false);
|
||||||
foreach (var change in changes.Value)
|
foreach (var change in changes.Value)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("[{applicationId}] Processing {change} for {handler}", applicationId, change, handler);
|
_logger.LogDebug("[{applicationId}] Processing {change} for {handler}", applicationId, change, handler);
|
||||||
@@ -445,7 +445,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
|
|||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var applicationId = Guid.NewGuid();
|
var applicationId = Guid.NewGuid();
|
||||||
_dalamudUtil.WaitWhileCharacterIsDrawing(_logger, _currentOtherChara!, applicationId, ct: token);
|
await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, _currentOtherChara!, applicationId, ct: token).ConfigureAwait(false);
|
||||||
_logger.LogDebug("Unauthorized character change detected");
|
_logger.LogDebug("Unauthorized character change detected");
|
||||||
await ApplyCustomizationData(applicationId, new(ObjectKind.Player,
|
await ApplyCustomizationData(applicationId, new(ObjectKind.Player,
|
||||||
new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Mods })),
|
new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Mods })),
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable
|
|||||||
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
|
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!combinedToken.IsCancellationRequested)
|
if (!combinedToken.IsCancellationRequested)
|
||||||
_dalamudUtil.WaitWhileCharacterIsDrawing(logger, obj, applicationId, 30000, combinedToken);
|
await _dalamudUtil.WaitWhileCharacterIsDrawing(logger, obj, applicationId, 30000, combinedToken).ConfigureAwait(false);
|
||||||
|
|
||||||
_penumbraRedrawRequests[obj.Address] = false;
|
_penumbraRedrawRequests[obj.Address] = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
private readonly Func<IntPtr> _getAddress;
|
private readonly Func<IntPtr> _getAddress;
|
||||||
private readonly bool _isOwnedObject;
|
private readonly bool _isOwnedObject;
|
||||||
private readonly MareMediator _mediator;
|
private readonly MareMediator _mediator;
|
||||||
|
private readonly DalamudUtil _dalamudUtil;
|
||||||
private readonly PerformanceCollector _performanceCollector;
|
private readonly PerformanceCollector _performanceCollector;
|
||||||
private CancellationTokenSource? _clearCts = new();
|
private CancellationTokenSource? _clearCts = new();
|
||||||
private Task? _clearTask;
|
private Task? _clearTask;
|
||||||
@@ -22,11 +23,13 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
private bool _haltProcessing = false;
|
private bool _haltProcessing = false;
|
||||||
private bool _ignoreSendAfterRedraw = false;
|
private bool _ignoreSendAfterRedraw = false;
|
||||||
private CancellationTokenSource _zoningCts = new();
|
private CancellationTokenSource _zoningCts = new();
|
||||||
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, DalamudUtil dalamudUtil, ObjectKind objectKind, Func<IntPtr> getAddress, bool watchedObject = true) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
_performanceCollector = performanceCollector;
|
_performanceCollector = performanceCollector;
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
ObjectKind = objectKind;
|
ObjectKind = objectKind;
|
||||||
|
_dalamudUtil = dalamudUtil;
|
||||||
_getAddress = getAddress;
|
_getAddress = getAddress;
|
||||||
_isOwnedObject = watchedObject;
|
_isOwnedObject = watchedObject;
|
||||||
Name = string.Empty;
|
Name = string.Empty;
|
||||||
@@ -86,7 +89,6 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
public unsafe Character* Character => (Character*)Address;
|
public unsafe Character* Character => (Character*)Address;
|
||||||
|
|
||||||
public IntPtr CurrentAddress => _getAddress.Invoke();
|
public IntPtr CurrentAddress => _getAddress.Invoke();
|
||||||
public bool IsBeingDrawn { get; private set; }
|
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
public ObjectKind ObjectKind { get; }
|
public ObjectKind ObjectKind { get; }
|
||||||
private byte[] CustomizeData { get; set; } = new byte[26];
|
private byte[] CustomizeData { get; set; } = new byte[26];
|
||||||
@@ -110,6 +112,41 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
return $"{owned}/{ObjectKind}:{Name} ({Address:X},{DrawObjectAddress:X})";
|
return $"{owned}/{ObjectKind}:{Name} ({Address:X},{DrawObjectAddress:X})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe IntPtr GetDrawObj()
|
||||||
|
{
|
||||||
|
return (IntPtr)((GameObject*)_getAddress.Invoke())->GetDrawObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe bool IsBeingDrawn(IntPtr drawObj, IntPtr curPtr)
|
||||||
|
{
|
||||||
|
return drawObj == IntPtr.Zero || (((CharacterBase*)drawObj)->HasModelInSlotLoaded != 0)
|
||||||
|
|| (((CharacterBase*)drawObj)->HasModelFilesInSlotLoaded != 0)
|
||||||
|
|| (((GameObject*)curPtr)->RenderFlags & 0b100000000000) == 0b100000000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsBeingDrawn()
|
||||||
|
{
|
||||||
|
var curPtr = _getAddress.Invoke();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||||
|
{
|
||||||
|
var drawObj = GetDrawObj();
|
||||||
|
return IsBeingDrawn(drawObj, curPtr);
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error during checking for draw object for {name}", curPtr);
|
||||||
|
if (curPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void CheckAndUpdateObject()
|
private unsafe void CheckAndUpdateObject()
|
||||||
{
|
{
|
||||||
if (_haltProcessing) return;
|
if (_haltProcessing) return;
|
||||||
@@ -123,21 +160,12 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
var drawObjAddr = (IntPtr)((GameObject*)curPtr)->GetDrawObject();
|
var drawObjAddr = (IntPtr)((GameObject*)curPtr)->GetDrawObject();
|
||||||
drawObjDiff = drawObjAddr != DrawObjectAddress;
|
drawObjDiff = drawObjAddr != DrawObjectAddress;
|
||||||
DrawObjectAddress = drawObjAddr;
|
DrawObjectAddress = drawObjAddr;
|
||||||
|
|
||||||
IsBeingDrawn = DrawObjectAddress == IntPtr.Zero || (((CharacterBase*)DrawObjectAddress)->HasModelInSlotLoaded != 0)
|
|
||||||
|| (((CharacterBase*)DrawObjectAddress)->HasModelFilesInSlotLoaded != 0)
|
|
||||||
|| (((GameObject*)curPtr)->RenderFlags & 0b100000000000) == 0b100000000000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var name = new ByteString(((Character*)curPtr)->GameObject.Name).ToString();
|
var name = new ByteString(((Character*)curPtr)->GameObject.Name).ToString();
|
||||||
|
|
||||||
_logger.LogError(ex, "Error during checking for draw object for {name}", this);
|
_logger.LogError(ex, "Error during checking for draw object for {name}", this);
|
||||||
if (curPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
IsBeingDrawn = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curPtr != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
if (curPtr != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
||||||
@@ -206,7 +234,7 @@ public class GameObjectHandler : MediatorSubscriberBase
|
|||||||
private unsafe bool CompareAndUpdateCustomizeData(byte* customizeData)
|
private unsafe bool CompareAndUpdateCustomizeData(byte* customizeData)
|
||||||
{
|
{
|
||||||
bool hasChanges = false;
|
bool hasChanges = false;
|
||||||
|
|
||||||
for (int i = 0; i < CustomizeData.Length; i++)
|
for (int i = 0; i < CustomizeData.Length; i++)
|
||||||
{
|
{
|
||||||
var data = Marshal.ReadByte((IntPtr)customizeData, i);
|
var data = Marshal.ReadByte((IntPtr)customizeData, i);
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ public class DalamudUtil : IDisposable
|
|||||||
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
|
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void WaitWhileCharacterIsDrawing(ILogger logger, GameObjectHandler handler, Guid redrawId, int timeOut = 5000, CancellationToken? ct = null)
|
public async Task WaitWhileCharacterIsDrawing(ILogger logger, GameObjectHandler handler, Guid redrawId, int timeOut = 5000, CancellationToken? ct = null)
|
||||||
{
|
{
|
||||||
if (!_clientState.IsLoggedIn || handler.Address == IntPtr.Zero) return;
|
if (!_clientState.IsLoggedIn || handler.Address == IntPtr.Zero) return;
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ public class DalamudUtil : IDisposable
|
|||||||
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
|
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
|
||||||
while ((!ct?.IsCancellationRequested ?? true)
|
while ((!ct?.IsCancellationRequested ?? true)
|
||||||
&& curWaitTime < timeOut
|
&& curWaitTime < timeOut
|
||||||
&& handler.IsBeingDrawn) // 0b100000000000 is "still rendering" or something
|
&& await handler.IsBeingDrawn().ConfigureAwait(false)) // 0b100000000000 is "still rendering" or something
|
||||||
{
|
{
|
||||||
logger.LogTrace($"[{redrawId}] Waiting for {handler} to finish drawing");
|
logger.LogTrace($"[{redrawId}] Waiting for {handler} to finish drawing");
|
||||||
curWaitTime += tick;
|
curWaitTime += tick;
|
||||||
|
|||||||
Reference in New Issue
Block a user