From 0c48508dbcb1a4a70c8cf01a2462106a02fd95d9 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Fri, 17 Feb 2023 09:49:18 +0100 Subject: [PATCH] attempts to fix some waiting issues I guess --- MareSynchronos/Export/MareCharaFileManager.cs | 11 +++- .../Factories/CharacterDataFactory.cs | 2 +- MareSynchronos/Managers/CachedPlayer.cs | 48 +++++++++----- MareSynchronos/Managers/IpcManager.cs | 47 +++++++------- MareSynchronos/Mediator/MareMediator.cs | 3 +- MareSynchronos/Models/GameObjectHandler.cs | 62 ++++++++++++------- MareSynchronos/Utils/DalamudUtil.cs | 26 +++----- 7 files changed, 115 insertions(+), 84 deletions(-) diff --git a/MareSynchronos/Export/MareCharaFileManager.cs b/MareSynchronos/Export/MareCharaFileManager.cs index 11593b0..72a7660 100644 --- a/MareSynchronos/Export/MareCharaFileManager.cs +++ b/MareSynchronos/Export/MareCharaFileManager.cs @@ -3,13 +3,16 @@ using LZ4; using MareSynchronos.FileCache; using MareSynchronos.Managers; using MareSynchronos.Utils; -using MareSynchronos.API.Data; using MareSynchronos.API.Data.Enum; using MareSynchronos.MareConfiguration; +using MareSynchronos.Mediator; +using MareSynchronos.Models; +using CharacterData = MareSynchronos.API.Data.CharacterData; namespace MareSynchronos.Export; public class MareCharaFileManager { + private readonly MareMediator _mediator; private readonly FileCacheManager _manager; private readonly IpcManager _ipcManager; private readonly MareConfigService _configService; @@ -19,9 +22,10 @@ public class MareCharaFileManager public bool CurrentlyWorking { get; private set; } = false; private static int GlobalFileCounter = 0; - public MareCharaFileManager(FileCacheManager manager, IpcManager ipcManager, MareConfigService configService, DalamudUtil dalamudUtil) + public MareCharaFileManager(MareMediator mediator, FileCacheManager manager, IpcManager ipcManager, MareConfigService configService, DalamudUtil dalamudUtil) { _factory = new(manager); + _mediator = mediator; _manager = manager; _ipcManager = ipcManager; _configService = configService; @@ -119,7 +123,8 @@ public class MareCharaFileManager _ipcManager.PenumbraSetTemporaryMods(charaTarget.Name.TextValue, extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal), LoadedCharaFile.CharaFileData.ManipulationData); - await _ipcManager.GlamourerApplyAll(LoadedCharaFile.CharaFileData.GlamourerData, charaTarget.Address, disposeCts.Token).ConfigureAwait(false); + using GameObjectHandler tempHandler = new(_mediator, ObjectKind.Player, () => charaTarget.Address, false); + await _ipcManager.GlamourerApplyAll(LoadedCharaFile.CharaFileData.GlamourerData, tempHandler, disposeCts.Token).ConfigureAwait(false); _dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000); _ipcManager.PenumbraRemoveTemporaryCollection(charaTarget.Name.TextValue); _ipcManager.ToggleGposeQueueMode(on: false); diff --git a/MareSynchronos/Factories/CharacterDataFactory.cs b/MareSynchronos/Factories/CharacterDataFactory.cs index 67a1e71..b6bacb6 100644 --- a/MareSynchronos/Factories/CharacterDataFactory.cs +++ b/MareSynchronos/Factories/CharacterDataFactory.cs @@ -120,7 +120,7 @@ public class CharacterDataFactory : MediatorSubscriberBase } // wait until chara is not drawing and present so nothing spontaneously explodes - _dalamudUtil.WaitWhileCharacterIsDrawing(playerRelatedObject.ObjectKind.ToString(), playerRelatedObject.Address, 30000, ct: token); + _dalamudUtil.WaitWhileCharacterIsDrawing(playerRelatedObject, 30000, ct: token); var chara = _dalamudUtil.CreateGameObject(charaPointer)!; while (!DalamudUtil.IsObjectPresent(chara)) { diff --git a/MareSynchronos/Managers/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs index 9bfb37b..8727bb6 100644 --- a/MareSynchronos/Managers/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -281,18 +281,18 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable switch (objectKind) { case ObjectKind.Player: - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 30000); + _dalamudUtil.WaitWhileCharacterIsDrawing(_currentOtherChara!, 30000); _ipcManager.HeelsSetOffsetForPlayer(_cachedData.HeelsOffset, PlayerCharacter); _ipcManager.CustomizePlusSetBodyScale(PlayerCharacter, _cachedData.CustomizePlusData); _ipcManager.PalettePlusSetPalette(PlayerCharacter, _cachedData.PalettePlusData); Logger.Debug($"Request Redraw for {PlayerName}"); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { - await _ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.GlamourerApplyAll(glamourerData, _currentOtherChara!, applicationTokenSource.Token).ConfigureAwait(false); } else { - await _ipcManager.PenumbraRedraw(PlayerCharacter, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(_currentOtherChara!, applicationTokenSource.Token).ConfigureAwait(false); } break; @@ -301,15 +301,18 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable var minionOrMount = _dalamudUtil.GetMinionOrMount(PlayerCharacter); if (minionOrMount != null) { + using GameObjectHandler tempHandler = new(Mediator, ObjectKind.MinionOrMount, + () => minionOrMount.Value, false); + Logger.Debug($"Request Redraw for {PlayerName} Minion/Mount"); - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " minion or mount", (IntPtr)minionOrMount, 30000); + _dalamudUtil.WaitWhileCharacterIsDrawing(tempHandler, 30000); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { - await _ipcManager.GlamourerApplyAll(glamourerData, (IntPtr)minionOrMount, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.GlamourerApplyAll(glamourerData, tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } else { - await _ipcManager.PenumbraRedraw((IntPtr)minionOrMount, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } } @@ -334,13 +337,15 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable newPet = _dalamudUtil.GetPet(PlayerCharacter); } while (newPet == pet && totalWait < maxWait); + using var tempHandler = new GameObjectHandler(Mediator, ObjectKind.Pet, () => newPet, false); + if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { - await _ipcManager.GlamourerApplyAll(glamourerData, newPet, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.GlamourerApplyAll(glamourerData, tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } else { - await _ipcManager.PenumbraRedraw(newPet, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } } @@ -353,14 +358,17 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (companion != IntPtr.Zero) { Logger.Debug($"Request Redraw for {PlayerName} Companion"); - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " companion", companion, 30000); + + using GameObjectHandler tempHandler = new(Mediator, ObjectKind.Companion, () => companion, false); + + _dalamudUtil.WaitWhileCharacterIsDrawing(tempHandler, 30000); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { - await _ipcManager.GlamourerApplyAll(glamourerData, companion, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.GlamourerApplyAll(glamourerData, tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } else { - await _ipcManager.PenumbraRedraw(companion, applicationTokenSource.Token).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(tempHandler, applicationTokenSource.Token).ConfigureAwait(false); } } @@ -465,7 +473,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable Task.Run(async () => { - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, ct: token); + _dalamudUtil.WaitWhileCharacterIsDrawing(_currentOtherChara!, ct: token); Logger.Debug("Unauthorized character change detected"); await ApplyCustomizationData(ObjectKind.Player).ConfigureAwait(false); }, token); @@ -481,9 +489,9 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (objectKind == ObjectKind.Player) { Logger.Debug($"Restoring Customization for {OnlineUser.User.AliasOrUID}/{PlayerName}: {_originalGlamourerData}"); - await _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerCharacter, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, _currentOtherChara!, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); Logger.Debug($"Restoring Equipment for {OnlineUser.User.AliasOrUID}/{PlayerName}: {_lastGlamourerData}"); - await _ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, _currentOtherChara!, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); Logger.Debug($"Restoring Heels for {OnlineUser.User.AliasOrUID}/{PlayerName}"); _ipcManager.HeelsRestoreOffsetForPlayer(PlayerCharacter); Logger.Debug($"Restoring C+ for {OnlineUser.User.AliasOrUID}/{PlayerName}"); @@ -495,7 +503,9 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable var minionOrMount = _dalamudUtil.GetMinionOrMount(PlayerCharacter); if (minionOrMount != null) { - await _ipcManager.PenumbraRedraw(minionOrMount.Value, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + using GameObjectHandler tempHandler = new(Mediator, ObjectKind.MinionOrMount, () => minionOrMount.Value, + false); + await _ipcManager.PenumbraRedraw(tempHandler, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); } } else if (objectKind == ObjectKind.Pet) @@ -503,7 +513,9 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable var pet = _dalamudUtil.GetPet(PlayerCharacter); if (pet != IntPtr.Zero) { - await _ipcManager.PenumbraRedraw(pet, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + using GameObjectHandler tempHandler = new(Mediator, ObjectKind.Pet, () => pet, + false); + await _ipcManager.PenumbraRedraw(tempHandler, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); } } else if (objectKind == ObjectKind.Companion) @@ -511,7 +523,9 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable var companion = _dalamudUtil.GetCompanion(PlayerCharacter); if (companion != IntPtr.Zero) { - await _ipcManager.PenumbraRedraw(companion, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + using GameObjectHandler tempHandler = new(Mediator, ObjectKind.Pet, () => companion, + false); + await _ipcManager.PenumbraRedraw(tempHandler, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); } } } diff --git a/MareSynchronos/Managers/IpcManager.cs b/MareSynchronos/Managers/IpcManager.cs index 2d66bb8..37b06ae 100644 --- a/MareSynchronos/Managers/IpcManager.cs +++ b/MareSynchronos/Managers/IpcManager.cs @@ -9,6 +9,7 @@ using Penumbra.Api.Enums; using Penumbra.Api.Helpers; using MareSynchronos.Mediator; using Dalamud.Interface.Internal.Notifications; +using MareSynchronos.Models; namespace MareSynchronos.Managers; @@ -396,10 +397,11 @@ public class IpcManager : MediatorSubscriberBase, IDisposable }); } - private async Task PenumbraRedrawAction(IntPtr obj, Action action, CancellationToken token, bool fireAndForget) + private async Task PenumbraRedrawAction(GameObjectHandler obj, Action action, CancellationToken token, bool fireAndForget) { - Mediator.Publish(new PenumbraStartRedrawMessage(obj)); - _penumbraRedrawRequests[obj] = !fireAndForget; + Mediator.Publish(new PenumbraStartRedrawMessage(obj.Address)); + + _penumbraRedrawRequests[obj.Address] = !fireAndForget; ActionQueue.Enqueue(action); @@ -407,48 +409,45 @@ public class IpcManager : MediatorSubscriberBase, IDisposable { var disposeToken = _disposalCts.Token; var combinedToken = CancellationTokenSource.CreateLinkedTokenSource(disposeToken, token).Token; - while (_penumbraRedrawRequests[obj] && !combinedToken.IsCancellationRequested) - { - Logger.Debug("Waiting for Penumbra Reply"); - await Task.Delay(100).ConfigureAwait(true); - } - Logger.Debug("Received Penumbra reply, waiting for draw"); + await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); if (!combinedToken.IsCancellationRequested) - _dalamudUtil.WaitWhileCharacterIsDrawing(obj.ToString("X"), obj, 10000, combinedToken); - } + _dalamudUtil.WaitWhileCharacterIsDrawing(obj, 30000, combinedToken); + + _penumbraRedrawRequests[obj.Address] = false; + } + Mediator.Publish(new PenumbraEndRedrawMessage(obj.Address)); - Mediator.Publish(new PenumbraEndRedrawMessage(obj)); } - public async Task GlamourerApplyAll(string? customization, IntPtr obj, CancellationToken token, bool fireAndForget = false) + public async Task GlamourerApplyAll(string? customization, GameObjectHandler handler, CancellationToken token, bool fireAndForget = false) { if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; - var gameObj = _dalamudUtil.CreateGameObject(obj); + var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { - await PenumbraRedrawAction(obj, () => _glamourerApplyAll!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); + await PenumbraRedrawAction(handler, () => _glamourerApplyAll!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); } } - public async Task GlamourerApplyOnlyEquipment(string customization, IntPtr obj, CancellationToken token, bool fireAndForget = false) + public async Task GlamourerApplyOnlyEquipment(string customization, GameObjectHandler handler, CancellationToken token, bool fireAndForget = false) { if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; - var gameObj = _dalamudUtil.CreateGameObject(obj); + var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { - await PenumbraRedrawAction(obj, () => _glamourerApplyOnlyEquipment!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); + await PenumbraRedrawAction(handler, () => _glamourerApplyOnlyEquipment!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); } } - public async Task GlamourerApplyOnlyCustomization(string customization, IntPtr obj, CancellationToken token, bool fireAndForget = false) + public async Task GlamourerApplyOnlyCustomization(string customization, GameObjectHandler handler, CancellationToken token, bool fireAndForget = false) { if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; - var gameObj = _dalamudUtil.CreateGameObject(obj); + var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { - await PenumbraRedrawAction(obj, () => _glamourerApplyOnlyCustomization!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); + await PenumbraRedrawAction(handler, () => _glamourerApplyOnlyCustomization!.InvokeAction(customization, c), token, fireAndForget).ConfigureAwait(false); } } @@ -495,13 +494,13 @@ public class IpcManager : MediatorSubscriberBase, IDisposable return _penumbraResolveModDir!.Invoke().ToLowerInvariant(); } - public async Task PenumbraRedraw(IntPtr obj, CancellationToken token, bool fireAndForget = false) + public async Task PenumbraRedraw(GameObjectHandler handler, CancellationToken token, bool fireAndForget = false) { if (!CheckPenumbraApi()) return; - var gameObj = _dalamudUtil.CreateGameObject(obj); + var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { - await PenumbraRedrawAction(obj, () => _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw), token, fireAndForget).ConfigureAwait(false); + await PenumbraRedrawAction(handler, () => _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw), token, fireAndForget).ConfigureAwait(false); } } diff --git a/MareSynchronos/Mediator/MareMediator.cs b/MareSynchronos/Mediator/MareMediator.cs index fedd5f9..e3fa93d 100644 --- a/MareSynchronos/Mediator/MareMediator.cs +++ b/MareSynchronos/Mediator/MareMediator.cs @@ -38,7 +38,8 @@ public class MareMediator : IDisposable } catch (Exception ex) { - Logger.Error("Error executing " + subscriber.Action.Method, ex); + Logger.Error("Error executing " + subscriber, ex); + subscribers.RemoveWhere(s => s == subscriber); } } } diff --git a/MareSynchronos/Models/GameObjectHandler.cs b/MareSynchronos/Models/GameObjectHandler.cs index 6135d8d..6164aab 100644 --- a/MareSynchronos/Models/GameObjectHandler.cs +++ b/MareSynchronos/Models/GameObjectHandler.cs @@ -1,9 +1,11 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Client.Game.Object; +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using System.Runtime.InteropServices; using MareSynchronos.Utils; using Penumbra.String; -using MareSynchronos.API.Data.Enum; using MareSynchronos.Mediator; +using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind; namespace MareSynchronos.Models; @@ -18,9 +20,15 @@ public class GameObjectHandler : MediatorSubscriberBase public string Name { get; private set; } public ObjectKind ObjectKind { get; } public IntPtr Address { get; set; } - public IntPtr DrawObjectAddress { get; set; } + private IntPtr DrawObjectAddress { get; set; } private Task? _delayedZoningTask; private CancellationTokenSource _zoningCts = new(); + private bool _haltProcessing = false; + + public override string ToString() + { + return $"{Name} (Addr: {Address.ToString("X")}, DrawObj: {DrawObjectAddress.ToString("X")})"; + } public IntPtr CurrentAddress { @@ -63,26 +71,24 @@ public class GameObjectHandler : MediatorSubscriberBase Mediator.Subscribe(this, (_) => { - Mediator.Unsubscribe(this); - Mediator.Unsubscribe(this); + _haltProcessing = true; }); Mediator.Subscribe(this, (_) => { - Mediator.Subscribe(this, (_) => ZoneSwitchStart()); - Mediator.Subscribe(this, (_) => FrameworkUpdate()); + _haltProcessing = false; }); Mediator.Subscribe(this, (msg) => { if (((PenumbraStartRedrawMessage)msg).Address == Address) { - Mediator.Unsubscribe(this); + _haltProcessing = true; } }); Mediator.Subscribe(this, (msg) => { if (((PenumbraEndRedrawMessage)msg).Address == Address) { - Mediator.Subscribe(this, (_) => FrameworkUpdate()); + _haltProcessing = false; } }); } @@ -97,7 +103,7 @@ public class GameObjectHandler : MediatorSubscriberBase private void ZoneSwitchEnd() { - if (!_sendUpdates) return; + if (!_sendUpdates || _haltProcessing) return; _clearCts?.Cancel(); _clearCts?.Dispose(); @@ -107,7 +113,7 @@ public class GameObjectHandler : MediatorSubscriberBase private void ZoneSwitchStart() { - if (!_sendUpdates) return; + if (!_sendUpdates || _haltProcessing) return; _zoningCts = new(); Logger.Debug("Starting Delay After Zoning for " + ObjectKind + " " + Name); @@ -126,18 +132,37 @@ public class GameObjectHandler : MediatorSubscriberBase }); } - public byte[] EquipSlotData { get; set; } = new byte[40]; - public byte[] CustomizeData { get; set; } = new byte[26]; + 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(); - public byte? HatState { get; set; } - public byte? VisorWeaponState { get; set; } + private byte? HatState { get; set; } + private byte? VisorWeaponState { get; set; } private bool _doNotSendUpdate; - private unsafe bool CheckAndUpdateObject() + private unsafe void CheckAndUpdateObject() { var curPtr = CurrentAddress; - if (curPtr != IntPtr.Zero && (IntPtr)((Character*)curPtr)->GameObject.DrawObject != IntPtr.Zero) + bool drawObj = false; + try + { + var drawObjAddr = (IntPtr)((GameObject*)curPtr)->GetDrawObject(); + drawObj = drawObjAddr != DrawObjectAddress; + DrawObjectAddress = drawObjAddr; + + IsBeingDrawn = (((CharacterBase*)drawObjAddr)->HasModelInSlotLoaded != 0) + || (((CharacterBase*)drawObjAddr)->HasModelFilesInSlotLoaded != 0) + || (((GameObject*)curPtr)->RenderFlags & 0b100000000000) == 0b100000000000; + } + catch + { + IsBeingDrawn = true; + } + + if (_haltProcessing) return; + + if (curPtr != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero) { if (_clearCts != null) { @@ -149,7 +174,6 @@ public class GameObjectHandler : MediatorSubscriberBase bool addr = Address == IntPtr.Zero || Address != curPtr; bool equip = CompareAndUpdateEquipByteData(chara->EquipSlotData); var customize = CompareAndUpdateCustomizeData(chara->CustomizeData); - bool drawObj = (IntPtr)chara->GameObject.DrawObject != DrawObjectAddress; var name = new ByteString(chara->GameObject.Name).ToString(); bool nameChange = (!string.Equals(name, Name, StringComparison.Ordinal)); if (addr || equip || customize || drawObj || nameChange) @@ -169,8 +193,6 @@ public class GameObjectHandler : MediatorSubscriberBase { Mediator.Publish(new CharacterChangedMessage(this)); } - - return true; } } else if (Address != IntPtr.Zero || DrawObjectAddress != IntPtr.Zero) @@ -187,8 +209,6 @@ public class GameObjectHandler : MediatorSubscriberBase _clearTask = Task.Run(() => ClearTask(token), token); } } - - return false; } private async Task ClearTask(CancellationToken token) diff --git a/MareSynchronos/Utils/DalamudUtil.cs b/MareSynchronos/Utils/DalamudUtil.cs index 54432a9..5aae030 100644 --- a/MareSynchronos/Utils/DalamudUtil.cs +++ b/MareSynchronos/Utils/DalamudUtil.cs @@ -7,6 +7,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using MareSynchronos.Mediator; +using MareSynchronos.Models; using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; namespace MareSynchronos.Utils; @@ -249,42 +250,33 @@ public class DalamudUtil : IDisposable return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false); } - public unsafe void WaitWhileCharacterIsDrawing(string name, IntPtr characterAddress, int timeOut = 5000, CancellationToken? ct = null) + public unsafe void WaitWhileCharacterIsDrawing(GameObjectHandler handler, int timeOut = 5000, CancellationToken? ct = null) { - if (!_clientState.IsLoggedIn || characterAddress == IntPtr.Zero) return; + if (!_clientState.IsLoggedIn || handler.Address == IntPtr.Zero) return; - Logger.Verbose($"Starting wait for {name} to draw"); + Logger.Verbose($"Starting wait for {handler} to draw"); - var obj = (GameObject*)characterAddress; const int tick = 250; int curWaitTime = 0; try { // ReSharper disable once LoopVariableIsNeverChangedInsideLoop - var stillDrawing = _framework.RunOnFrameworkThread(() => ((obj->GetDrawObject() == null - || ((CharacterBase*)obj->GetDrawObject())->HasModelInSlotLoaded != 0 - || ((CharacterBase*)obj->GetDrawObject())->HasModelFilesInSlotLoaded != 0)) - || ((obj->RenderFlags & 0b100000000000) == 0b100000000000)).Result; while ((!ct?.IsCancellationRequested ?? true) - && curWaitTime < timeOut - && stillDrawing) // 0b100000000000 is "still rendering" or something + && curWaitTime < timeOut + && handler.IsBeingDrawn) // 0b100000000000 is "still rendering" or something { - Logger.Verbose($"Waiting for {name} to finish drawing"); + Logger.Verbose($"Waiting for {handler} to finish drawing"); curWaitTime += tick; Thread.Sleep(tick); - stillDrawing = _framework.RunOnFrameworkThread(() => ((obj->GetDrawObject() == null - || ((CharacterBase*)obj->GetDrawObject())->HasModelInSlotLoaded != 0 - || ((CharacterBase*)obj->GetDrawObject())->HasModelFilesInSlotLoaded != 0)) - || ((obj->RenderFlags & 0b100000000000) == 0b100000000000)).Result; } } catch (NullReferenceException ex) { - Logger.Warn("Error accessing " + characterAddress.ToString("X") + ", object does not exist anymore?", ex); + Logger.Warn("Error accessing " + handler + ", object does not exist anymore?", ex); } catch (AccessViolationException ex) { - Logger.Warn("Error accessing " + characterAddress.ToString("X") + ", object does not exist anymore?", ex); + Logger.Warn("Error accessing " + handler + ", object does not exist anymore?", ex); } }