From 307c90f40eac7d21b6f4b13275b33ca2ef685c64 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Tue, 26 Jul 2022 12:49:44 +0200 Subject: [PATCH] save but not send hat/visor/weapon state, fix sync of mounts, speed up cache generation a bit --- .../Factories/CharacterDataFactory.cs | 16 ++++++ MareSynchronos/Managers/CachedPlayer.cs | 56 +++++++++++++------ MareSynchronos/Managers/IpcManager.cs | 10 +--- MareSynchronos/Managers/PlayerManager.cs | 6 +- MareSynchronos/MareSynchronos.csproj | 2 +- MareSynchronos/Models/PlayerRelatedObject.cs | 22 ++++++++ MareSynchronos/Utils/DalamudUtil.cs | 4 +- 7 files changed, 86 insertions(+), 30 deletions(-) diff --git a/MareSynchronos/Factories/CharacterDataFactory.cs b/MareSynchronos/Factories/CharacterDataFactory.cs index 986e954..9a312d8 100644 --- a/MareSynchronos/Factories/CharacterDataFactory.cs +++ b/MareSynchronos/Factories/CharacterDataFactory.cs @@ -125,6 +125,14 @@ public class CharacterDataFactory //Logger.Verbose("Adding File Replacement for Material " + fileName); var mtrlPath = fileName.Split("|")[2]; + if (cache.FileReplacements.ContainsKey(objectKind)) + { + if (cache.FileReplacements[objectKind].Any(c => c.ResolvedPath.Contains(mtrlPath))) + { + return; + } + } + var mtrlFileReplacement = CreateFileReplacement(mtrlPath); DebugPrint(mtrlFileReplacement, objectKind, "Material", inheritanceLevel); @@ -155,6 +163,14 @@ public class CharacterDataFactory //Logger.Verbose("Adding File Replacement for Texture " + texPath); + if (cache.FileReplacements.ContainsKey(objectKind)) + { + if (cache.FileReplacements[objectKind].Any(c => c.GamePaths.Contains(texPath))) + { + return; + } + } + var texFileReplacement = CreateFileReplacement(texPath, doNotReverseResolve); DebugPrint(texFileReplacement, objectKind, "Texture", inheritanceLevel); diff --git a/MareSynchronos/Managers/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs index 66de9f7..aa43400 100644 --- a/MareSynchronos/Managers/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -73,21 +73,45 @@ public class CachedPlayer List charaDataToUpdate = new List(); foreach (var objectKind in Enum.GetValues()) { - bool doesntContainKey = !_cachedData.FileReplacements.ContainsKey(objectKind) - || (_cachedData.FileReplacements.ContainsKey(objectKind) && !characterData.FileReplacements.ContainsKey(objectKind)); - if (doesntContainKey) + _cachedData.FileReplacements.TryGetValue(objectKind, out var existingFileReplacements); + characterData.FileReplacements.TryGetValue(objectKind, out var newFileReplacements); + _cachedData.GlamourerData.TryGetValue(objectKind, out var existingGlamourerData); + characterData.GlamourerData.TryGetValue(objectKind, out var newGlamourerData); + + bool hasNewButNotOldFileReplacements = newFileReplacements != null && existingFileReplacements == null; + bool hasOldButNotNewFileReplacements = existingFileReplacements != null && newFileReplacements == null; + bool hasNewButNotOldGlamourerData = newGlamourerData != null && existingGlamourerData == null; + bool hasOldButNotNewGlamourerData = existingGlamourerData != null && newGlamourerData == null; + bool hasNewAndOldFileReplacements = newFileReplacements != null && existingFileReplacements != null; + bool hasNewAndOldGlamourerData = newGlamourerData != null && existingGlamourerData != null; + + if (hasNewButNotOldFileReplacements || hasOldButNotNewFileReplacements || hasNewButNotOldGlamourerData || hasOldButNotNewGlamourerData) { + Logger.Debug("Updating " + objectKind); charaDataToUpdate.Add(objectKind); continue; } - bool listsAreEqual = Enumerable.SequenceEqual(_cachedData.FileReplacements[objectKind], characterData.FileReplacements[objectKind]); - bool glamourerDataDifferent = _cachedData.GlamourerData[objectKind] != characterData.GlamourerData[objectKind]; - if (!listsAreEqual || glamourerDataDifferent) + if (hasNewAndOldFileReplacements) { - Logger.Debug("Updating " + objectKind); + bool listsAreEqual = Enumerable.SequenceEqual(_cachedData.FileReplacements[objectKind], characterData.FileReplacements[objectKind]); + if (!listsAreEqual) + { + Logger.Debug("Updating " + objectKind); + charaDataToUpdate.Add(objectKind); + continue; + } + } - charaDataToUpdate.Add(objectKind); + if (hasNewAndOldGlamourerData) + { + bool glamourerDataDifferent = _cachedData.GlamourerData[objectKind] != characterData.GlamourerData[objectKind]; + if (glamourerDataDifferent) + { + Logger.Debug("Updating " + objectKind); + charaDataToUpdate.Add(objectKind); + continue; + } } } @@ -138,10 +162,7 @@ public class CachedPlayer foreach (var kind in objectKind) { - if (_cachedData.GlamourerData.ContainsKey(kind)) - { - ApplyCustomizationData(kind); - } + ApplyCustomizationData(kind); } }, downloadToken).ContinueWith(task => { @@ -195,14 +216,15 @@ public class CachedPlayer private unsafe void ApplyCustomizationData(ObjectKind objectKind) { if (PlayerCharacter is null) return; + _cachedData.GlamourerData.TryGetValue(objectKind, out var glamourerData); if (objectKind == ObjectKind.Player) { - _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter!.Address); + _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address); RequestedPenumbraRedraw = true; Logger.Debug( $"Request Redraw for {PlayerName}"); - _ipcManager.GlamourerApplyAll(_cachedData.GlamourerData[objectKind], PlayerCharacter!); + _ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter.Address); } else if (objectKind == ObjectKind.Minion) { @@ -210,7 +232,7 @@ public class CachedPlayer if (minion != null) { Logger.Debug($"Request Redraw for Minion"); - _ipcManager.GlamourerApplyAll(_cachedData.GlamourerData[objectKind], obj: (IntPtr)minion); + _ipcManager.GlamourerApplyAll(glamourerData, obj: (IntPtr)minion); } } else if (objectKind == ObjectKind.Pet) @@ -219,7 +241,7 @@ public class CachedPlayer if (pet != IntPtr.Zero) { Logger.Debug("Request Redraw for Pet"); - _ipcManager.GlamourerApplyAll(_cachedData.GlamourerData[objectKind], pet); + _ipcManager.GlamourerApplyAll(glamourerData, pet); } } else if (objectKind == ObjectKind.Companion) @@ -228,7 +250,7 @@ public class CachedPlayer if (companion != IntPtr.Zero) { Logger.Debug("Request Redraw for Companion"); - _ipcManager.GlamourerApplyAll(_cachedData.GlamourerData[objectKind], companion); + _ipcManager.GlamourerApplyAll(glamourerData, companion); } } else if (objectKind == ObjectKind.Mount) diff --git a/MareSynchronos/Managers/IpcManager.cs b/MareSynchronos/Managers/IpcManager.cs index 1f9cb1c..7aa4a75 100644 --- a/MareSynchronos/Managers/IpcManager.cs +++ b/MareSynchronos/Managers/IpcManager.cs @@ -116,9 +116,9 @@ namespace MareSynchronos.Managers _penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent); } - public void GlamourerApplyAll(string customization, IntPtr obj) + public void GlamourerApplyAll(string? customization, IntPtr obj) { - if (!CheckGlamourerApi()) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; var gameObj = _dalamudUtil.CreateGameObject(obj); if (gameObj != null) { @@ -126,12 +126,6 @@ namespace MareSynchronos.Managers } } - public void GlamourerApplyAll(string customization, GameObject character) - { - if (!CheckGlamourerApi()) return; - _glamourerApplyAll!.InvokeAction(customization, character); - } - public void GlamourerApplyOnlyEquipment(string customization, GameObject character) { if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; diff --git a/MareSynchronos/Managers/PlayerManager.cs b/MareSynchronos/Managers/PlayerManager.cs index 6bb6b66..8f7fcb0 100644 --- a/MareSynchronos/Managers/PlayerManager.cs +++ b/MareSynchronos/Managers/PlayerManager.cs @@ -149,7 +149,7 @@ namespace MareSynchronos.Managers { if (_dalamudUtil.IsInGpose) return; - var unprocessedObjects = playerRelatedObjects.Where(c => c.HasUnprocessedUpdate); + var unprocessedObjects = playerRelatedObjects.Where(c => c.HasUnprocessedUpdate).ToList(); foreach (var unprocessedObject in unprocessedObjects) { unprocessedObject.IsProcessing = true; @@ -195,11 +195,13 @@ namespace MareSynchronos.Managers LastCreatedCharacterData = cacheDto; } - if (_apiController.IsConnected && !token.IsCancellationRequested) + if (_apiController.IsConnected && !token.IsCancellationRequested && !unprocessedObjects.All(c => c.DoNotSendUpdate)) { Logger.Verbose("Invoking PlayerHasChanged"); PlayerHasChanged?.Invoke(cacheDto); } + + unprocessedObjects.ForEach(p => p.DoNotSendUpdate = false); }, token); } } diff --git a/MareSynchronos/MareSynchronos.csproj b/MareSynchronos/MareSynchronos.csproj index 8332d53..2de854b 100644 --- a/MareSynchronos/MareSynchronos.csproj +++ b/MareSynchronos/MareSynchronos.csproj @@ -3,7 +3,7 @@ - 0.2.3.0 + 0.2.4.0 https://github.com/Penumbra-Sync/client diff --git a/MareSynchronos/Models/PlayerRelatedObject.cs b/MareSynchronos/Models/PlayerRelatedObject.cs index fcf8606..772c6d5 100644 --- a/MareSynchronos/Models/PlayerRelatedObject.cs +++ b/MareSynchronos/Models/PlayerRelatedObject.cs @@ -32,8 +32,11 @@ namespace MareSynchronos.Models public byte[] EquipSlotData { get; set; } = new byte[40]; public byte[] CustomizeData { get; set; } = new byte[26]; + public byte? HatState { get; set; } + public byte? VisorWeaponState { get; set; } public bool HasUnprocessedUpdate { get; set; } = false; + public bool DoNotSendUpdate { get; set; } = false; public bool IsProcessing { get; set; } = false; public unsafe void CheckAndUpdateObject() @@ -94,6 +97,25 @@ namespace MareSynchronos.Models } } + if (ObjectKind is not ObjectKind.Mount) + { + var newHatState = Marshal.ReadByte((IntPtr)customizeData + 30, 0); + var newWeaponOrVisorState = Marshal.ReadByte((IntPtr)customizeData + 31, 0); + if (newHatState != HatState) + { + if (HatState != null) DoNotSendUpdate = true; + HatState = newHatState; + hasChanges = true; + } + + if (newWeaponOrVisorState != VisorWeaponState) + { + if (VisorWeaponState != null) DoNotSendUpdate = true; + VisorWeaponState = newWeaponOrVisorState; + hasChanges = true; + } + } + return hasChanges; } } diff --git a/MareSynchronos/Utils/DalamudUtil.cs b/MareSynchronos/Utils/DalamudUtil.cs index 9cc4721..4588bc5 100644 --- a/MareSynchronos/Utils/DalamudUtil.cs +++ b/MareSynchronos/Utils/DalamudUtil.cs @@ -139,8 +139,8 @@ namespace MareSynchronos.Utils } if (ct?.IsCancellationRequested ?? false) return; - // wait half a second just in case - Thread.Sleep(500); + // wait quarter a second just in case + Thread.Sleep(250); } public void WaitWhileSelfIsDrawing(CancellationToken? token) => WaitWhileCharacterIsDrawing(_clientState.LocalPlayer?.Address ?? new IntPtr(), token);