diff --git a/MareSynchronos/Factories/CharacterDataFactory.cs b/MareSynchronos/Factories/CharacterDataFactory.cs index ec44446..cf6c11e 100644 --- a/MareSynchronos/Factories/CharacterDataFactory.cs +++ b/MareSynchronos/Factories/CharacterDataFactory.cs @@ -77,8 +77,8 @@ public class CharacterDataFactory try { - pathsToForwardResolve.Clear(); - pathsToReverseResolve.Clear(); + _pathsToForwardResolve.Clear(); + _pathsToReverseResolve.Clear(); return CreateCharacterData(previousData, playerRelatedObject, token); } catch (OperationCanceledException) @@ -215,7 +215,7 @@ public class CharacterDataFactory previousData.FileReplacements[objectKind] = new(FileReplacementComparer.Instance); } - _dalamudUtil.WaitWhileCharacterIsDrawing(playerRelatedObject.ObjectKind.ToString(), playerRelatedObject.Address, ct: token); + _dalamudUtil.WaitWhileCharacterIsDrawing(playerRelatedObject.ObjectKind.ToString(), playerRelatedObject.Address, 30000, ct: token); Stopwatch st = Stopwatch.StartNew(); @@ -233,7 +233,8 @@ public class CharacterDataFactory Thread.Sleep(50); } - var human = (Human*)((Character*)charaPointer)->GameObject.DrawObject; + var human = (Human*)((Character*)charaPointer)->GameObject.GetDrawObject(); + for (var mdlIdx = 0; mdlIdx < human->CharacterBase.SlotCount; ++mdlIdx) { var mdl = (RenderModel*)human->CharacterBase.ModelArray[mdlIdx]; @@ -281,8 +282,8 @@ public class CharacterDataFactory Logger.Debug("Handling transient update for " + objectKind); _transientResourceManager.ClearTransientPaths(charaPointer, previousData.FileReplacements[objectKind].SelectMany(c => c.GamePaths).ToList()); - pathsToForwardResolve.Clear(); - pathsToReverseResolve.Clear(); + _pathsToForwardResolve.Clear(); + _pathsToReverseResolve.Clear(); ManageSemiTransientData(objectKind, charaPointer); @@ -305,10 +306,10 @@ public class CharacterDataFactory private Dictionary> GetFileReplacementsFromPaths() { - var forwardPaths = pathsToForwardResolve.ToArray(); - var reversePaths = pathsToReverseResolve.ToArray(); + var forwardPaths = _pathsToForwardResolve.ToArray(); + var reversePaths = _pathsToReverseResolve.ToArray(); Dictionary> resolvedPaths = new(StringComparer.Ordinal); - var result = _ipcManager.PenumbraResolvePaths(pathsToForwardResolve.ToArray(), pathsToReverseResolve.ToArray()); + var result = _ipcManager.PenumbraResolvePaths(_pathsToForwardResolve.ToArray(), _pathsToReverseResolve.ToArray()); for (int i = 0; i < forwardPaths.Length; i++) { var filePath = result.forward[i].ToLowerInvariant(); @@ -408,10 +409,10 @@ public class CharacterDataFactory private void AddResolvePath(string path, bool doNotReverseResolve = false) { - if (doNotReverseResolve) pathsToForwardResolve.Add(path.ToLowerInvariant()); - else pathsToReverseResolve.Add(path.ToLowerInvariant()); + if (doNotReverseResolve) _pathsToForwardResolve.Add(path.ToLowerInvariant()); + else _pathsToReverseResolve.Add(path.ToLowerInvariant()); } - private HashSet pathsToForwardResolve = new(StringComparer.Ordinal); - private HashSet pathsToReverseResolve = new(StringComparer.Ordinal); + private readonly HashSet _pathsToForwardResolve = new(StringComparer.Ordinal); + private readonly HashSet _pathsToReverseResolve = new(StringComparer.Ordinal); } diff --git a/MareSynchronos/Managers/CacheCreationService.cs b/MareSynchronos/Managers/CacheCreationService.cs index f157708..0eeb9e4 100644 --- a/MareSynchronos/Managers/CacheCreationService.cs +++ b/MareSynchronos/Managers/CacheCreationService.cs @@ -4,27 +4,21 @@ using MareSynchronos.Factories; using MareSynchronos.Mediator; using MareSynchronos.Models; using MareSynchronos.Utils; -using MareSynchronos.WebAPI; namespace MareSynchronos.Managers; public class CacheCreationService : MediatorSubscriberBase, IDisposable { private readonly CharacterDataFactory _characterDataFactory; - private readonly IpcManager _ipcManager; - private readonly ApiController _apiController; private Task? _cacheCreationTask; - private Dictionary _cachesToCreate = new(); - private CharacterData _lastCreatedData = new(); - private CancellationTokenSource cts = new(); - private List _playerRelatedObjects = new(); + private readonly Dictionary _cachesToCreate = new(); + private readonly CharacterData _lastCreatedData = new(); + private readonly CancellationTokenSource _cts = new(); + private readonly List _playerRelatedObjects = new(); - public unsafe CacheCreationService(MareMediator mediator, CharacterDataFactory characterDataFactory, IpcManager ipcManager, - ApiController apiController, DalamudUtil dalamudUtil) : base(mediator) + public unsafe CacheCreationService(MareMediator mediator, CharacterDataFactory characterDataFactory, DalamudUtil dalamudUtil) : base(mediator) { _characterDataFactory = characterDataFactory; - _ipcManager = ipcManager; - _apiController = apiController; Mediator.Subscribe(this, (msg) => { @@ -35,7 +29,7 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable Mediator.Subscribe(this, (msg) => CustomizePlusChanged((CustomizePlusMessage)msg)); Mediator.Subscribe(this, (msg) => HeelsOffsetChanged((HeelsOffsetMessage)msg)); Mediator.Subscribe(this, (msg) => PalettePlusChanged((PalettePlusMessage)msg)); - Mediator.Subscribe(this, (msg) => _cachesToCreate.Add(ObjectKind.Player, _playerRelatedObjects.First(p => p.ObjectKind == ObjectKind.Player))); + Mediator.Subscribe(this, (msg) => _cachesToCreate[ObjectKind.Player] = _playerRelatedObjects.First(p => p.ObjectKind == ObjectKind.Player)); _playerRelatedObjects.AddRange(new List() { @@ -85,7 +79,7 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable { foreach (var obj in toCreate) { - var data = _characterDataFactory.BuildCharacterData(_lastCreatedData, obj.Value, cts.Token); + var data = _characterDataFactory.BuildCharacterData(_lastCreatedData, obj.Value, _cts.Token); } Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData)); } @@ -98,7 +92,7 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable Logger.Debug("Cache Creation complete"); } - }, cts.Token); + }, _cts.Token); } else if (_cachesToCreate.Any()) { @@ -112,6 +106,6 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable { base.Dispose(); _playerRelatedObjects.ForEach(p => p.Dispose()); - cts.Dispose(); + _cts.Dispose(); } } diff --git a/MareSynchronos/Managers/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs index 6f7c2cb..b043159 100644 --- a/MareSynchronos/Managers/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -288,7 +288,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable switch (objectKind) { case ObjectKind.Player: - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 10000, ct); + _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 30000, ct); ct.ThrowIfCancellationRequested(); _ipcManager.HeelsSetOffsetForPlayer(_cachedData.HeelsOffset, PlayerCharacter); _ipcManager.CustomizePlusSetBodyScale(PlayerCharacter, _cachedData.CustomizePlusData); @@ -312,7 +312,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (minionOrMount != null) { Logger.Debug($"Request Redraw for Minion/Mount"); - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " minion or mount", (IntPtr)minionOrMount, 10000, ct); + _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " minion or mount", (IntPtr)minionOrMount, 30000, ct); ct.ThrowIfCancellationRequested(); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { @@ -364,7 +364,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (companion != IntPtr.Zero) { Logger.Debug("Request Redraw for Companion"); - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " companion", companion, 10000, ct); + _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName! + " companion", companion, 30000, ct); ct.ThrowIfCancellationRequested(); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData)) { @@ -456,7 +456,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable PlayerCharacter = msg.Address; var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(10)); - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 10000, cts.Token); + _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 30000, cts.Token); cts.Dispose(); cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(5)); diff --git a/MareSynchronos/MareSynchronos.csproj b/MareSynchronos/MareSynchronos.csproj index a80fc2a..fc213d9 100644 --- a/MareSynchronos/MareSynchronos.csproj +++ b/MareSynchronos/MareSynchronos.csproj @@ -3,7 +3,7 @@ - 0.7.15 + 0.7.16 https://github.com/Penumbra-Sync/client diff --git a/MareSynchronos/Models/GameObjectHandler.cs b/MareSynchronos/Models/GameObjectHandler.cs index 5e1c6b0..feb2a72 100644 --- a/MareSynchronos/Models/GameObjectHandler.cs +++ b/MareSynchronos/Models/GameObjectHandler.cs @@ -10,7 +10,7 @@ namespace MareSynchronos.Models; public class GameObjectHandler : MediatorSubscriberBase { private readonly MareMediator _mediator; - private readonly Func getAddress; + private readonly Func _getAddress; private readonly bool _sendUpdates; public unsafe Character* Character => (Character*)Address; @@ -27,7 +27,7 @@ public class GameObjectHandler : MediatorSubscriberBase { try { - return getAddress.Invoke(); + return _getAddress.Invoke(); } catch { return IntPtr.Zero; } @@ -38,7 +38,7 @@ public class GameObjectHandler : MediatorSubscriberBase { _mediator = mediator; ObjectKind = objectKind; - this.getAddress = getAddress; + this._getAddress = getAddress; _sendUpdates = sendUpdates; _name = string.Empty; @@ -76,8 +76,11 @@ public class GameObjectHandler : MediatorSubscriberBase Address = curPtr; DrawObjectAddress = (IntPtr)chara->GameObject.DrawObject; - if (_sendUpdates && !_doNotSendUpdate) + if (_sendUpdates && !_doNotSendUpdate && DrawObjectAddress != IntPtr.Zero) + { + Logger.Debug("Sending CreateCacheObjectMessage for " + ObjectKind); Mediator.Publish(new CreateCacheForObjectMessage(this)); + } return true; } diff --git a/MareSynchronos/UI/CompactUI.cs b/MareSynchronos/UI/CompactUI.cs index a622ade..04fdbae 100644 --- a/MareSynchronos/UI/CompactUI.cs +++ b/MareSynchronos/UI/CompactUI.cs @@ -61,20 +61,9 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable { #if DEBUG - string dateTime = "DEV VERSION"; + string dev = "Dev Build"; var ver = Assembly.GetExecutingAssembly().GetName().Version; - this.WindowName = "Mare Synchronos " + ver.Major + "." + ver.Minor + "." + ver.Build + "###MareSynchronosMainUI"; - try - { - dateTime = VariousExtensions.GetLinkerTime(Assembly.GetCallingAssembly()).ToString("yyyyMMddHHmmss"); - } - catch (Exception ex) - { - Logger.Warn("Could not get assembly name"); - Logger.Warn(ex.Message); - Logger.Warn(ex.StackTrace); - } - this.WindowName = $"Mare Synchronos {dateTime} ({ver.Major}.{ver.Minor}.{ver.Build})###MareSynchronosMainUI"; + this.WindowName = $"Mare Synchronos {dev} ({ver.Major}.{ver.Minor}.{ver.Build})###MareSynchronosMainUI"; Toggle(); #else var ver = Assembly.GetExecutingAssembly().GetName().Version; diff --git a/MareSynchronos/Utils/DalamudUtil.cs b/MareSynchronos/Utils/DalamudUtil.cs index e690068..d0f05f2 100644 --- a/MareSynchronos/Utils/DalamudUtil.cs +++ b/MareSynchronos/Utils/DalamudUtil.cs @@ -5,7 +5,7 @@ using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.SubKinds; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Control; -using Lumina.Excel.GeneratedSheets; +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using MareSynchronos.Mediator; using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; @@ -53,7 +53,7 @@ public class DalamudUtil : IDisposable } WorldData = new(() => { - return gameData.GetExcelSheet(Dalamud.ClientLanguage.English)! + return gameData.GetExcelSheet(Dalamud.ClientLanguage.English)! .Where(w => w.IsPublic && !w.Name.RawData.IsEmpty) .ToDictionary(w => (ushort)w.RowId, w => w.Name.ToString()); }); @@ -232,16 +232,19 @@ public class DalamudUtil : IDisposable const int tick = 250; int curWaitTime = 0; // ReSharper disable once LoopVariableIsNeverChangedInsideLoop - while ((obj->DrawObject == null || (obj->RenderFlags & 0b100000000000) == 0b100000000000) && (!ct?.IsCancellationRequested ?? true) && curWaitTime < timeOut) // 0b100000000000 is "still rendering" or something + while ((((obj->GetDrawObject() == null + || ((CharacterBase*)obj->GetDrawObject())->HasModelFilesInSlotLoaded != 0 + || ((CharacterBase*)obj->GetDrawObject())->HasModelFilesInSlotLoaded != 0)) + || ((obj->RenderFlags & 0b100000000000) == 0b100000000000)) + && (!ct?.IsCancellationRequested ?? true) + && curWaitTime < timeOut) // 0b100000000000 is "still rendering" or something { Logger.Verbose($"Waiting for {name} to finish drawing"); curWaitTime += tick; Thread.Sleep(tick); } - if (ct?.IsCancellationRequested ?? false) return; - // wait quarter a second just in case - Thread.Sleep(tick); + return; } public unsafe void DisableDraw(IntPtr characterAddress)