add some preliminary vfx work
This commit is contained in:
		| @@ -22,13 +22,15 @@ public class CharacterDataFactory | |||||||
| { | { | ||||||
|     private readonly DalamudUtil _dalamudUtil; |     private readonly DalamudUtil _dalamudUtil; | ||||||
|     private readonly IpcManager _ipcManager; |     private readonly IpcManager _ipcManager; | ||||||
|  |     private readonly TransientResourceManager transientResourceManager; | ||||||
|  |  | ||||||
|     public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager) |     public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager, TransientResourceManager transientResourceManager) | ||||||
|     { |     { | ||||||
|         Logger.Verbose("Creating " + nameof(CharacterDataFactory)); |         Logger.Verbose("Creating " + nameof(CharacterDataFactory)); | ||||||
|  |  | ||||||
|         _dalamudUtil = dalamudUtil; |         _dalamudUtil = dalamudUtil; | ||||||
|         _ipcManager = ipcManager; |         _ipcManager = ipcManager; | ||||||
|  |         this.transientResourceManager = transientResourceManager; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public CharacterData BuildCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr playerPointer, CancellationToken token) |     public CharacterData BuildCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr playerPointer, CancellationToken token) | ||||||
| @@ -167,6 +169,26 @@ public class CharacterDataFactory | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private void AddReplacement(string varPath, ObjectKind objectKind, CharacterData cache, int inheritanceLevel = 0) | ||||||
|  |     { | ||||||
|  |         if (varPath.IsNullOrEmpty()) return; | ||||||
|  |  | ||||||
|  |         //Logger.Verbose("Adding File Replacement for Texture " + texPath); | ||||||
|  |  | ||||||
|  |         if (cache.FileReplacements.ContainsKey(objectKind)) | ||||||
|  |         { | ||||||
|  |             if (cache.FileReplacements[objectKind].Any(c => c.GamePaths.Contains(varPath))) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         var variousReplacement = CreateFileReplacement(varPath, false); | ||||||
|  |         DebugPrint(variousReplacement, objectKind, "Various", inheritanceLevel); | ||||||
|  |  | ||||||
|  |         cache.AddFileReplacement(objectKind, variousReplacement); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void AddReplacementsFromTexture(string texPath, ObjectKind objectKind, CharacterData cache, int inheritanceLevel = 0, bool doNotReverseResolve = true) |     private void AddReplacementsFromTexture(string texPath, ObjectKind objectKind, CharacterData cache, int inheritanceLevel = 0, bool doNotReverseResolve = true) | ||||||
|     { |     { | ||||||
|         if (texPath.IsNullOrEmpty()) return; |         if (texPath.IsNullOrEmpty()) return; | ||||||
| @@ -233,6 +255,11 @@ public class CharacterDataFactory | |||||||
|             AddReplacementsFromRenderModel(mdl, objectKind, previousData, 0); |             AddReplacementsFromRenderModel(mdl, objectKind, previousData, 0); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         foreach (var item in previousData.FileReplacements[objectKind]) | ||||||
|  |         { | ||||||
|  |             transientResourceManager.RemoveTransientResource((IntPtr)human, item); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (objectKind == ObjectKind.Player) |         if (objectKind == ObjectKind.Player) | ||||||
|         { |         { | ||||||
|             var weaponObject = (Weapon*)((Object*)human)->ChildObject; |             var weaponObject = (Weapon*)((Object*)human)->ChildObject; | ||||||
| @@ -243,11 +270,33 @@ public class CharacterDataFactory | |||||||
|  |  | ||||||
|                 AddReplacementsFromRenderModel(mainHandWeapon, objectKind, previousData, 0); |                 AddReplacementsFromRenderModel(mainHandWeapon, objectKind, previousData, 0); | ||||||
|  |  | ||||||
|  |                 foreach (var item in previousData.FileReplacements[objectKind]) | ||||||
|  |                 { | ||||||
|  |                     transientResourceManager.RemoveTransientResource((IntPtr)weaponObject, item); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 foreach (var item in transientResourceManager.GetTransientResources((IntPtr)weaponObject)) | ||||||
|  |                 { | ||||||
|  |                     Logger.Verbose("Found transient weapon resource: " + item); | ||||||
|  |                     AddReplacementsFromTexture(item, objectKind, previousData, 0, false); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 if (weaponObject->NextSibling != (IntPtr)weaponObject) |                 if (weaponObject->NextSibling != (IntPtr)weaponObject) | ||||||
|                 { |                 { | ||||||
|                     var offHandWeapon = ((Weapon*)weaponObject->NextSibling)->WeaponRenderModel->RenderModel; |                     var offHandWeapon = ((Weapon*)weaponObject->NextSibling)->WeaponRenderModel->RenderModel; | ||||||
|  |  | ||||||
|                     AddReplacementsFromRenderModel(offHandWeapon, objectKind, previousData, 1); |                     AddReplacementsFromRenderModel(offHandWeapon, objectKind, previousData, 1); | ||||||
|  |  | ||||||
|  |                     foreach (var item in previousData.FileReplacements[objectKind]) | ||||||
|  |                     { | ||||||
|  |                         transientResourceManager.RemoveTransientResource((IntPtr)offHandWeapon, item); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     foreach (var item in transientResourceManager.GetTransientResources((IntPtr)weaponObject)) | ||||||
|  |                     { | ||||||
|  |                         Logger.Verbose("Found transient offhand weapon resource: " + item); | ||||||
|  |                         AddReplacement(item, objectKind, previousData, 1); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -268,11 +317,21 @@ public class CharacterDataFactory | |||||||
|             { |             { | ||||||
|                 Logger.Warn("Could not get Legacy Body Decal Data"); |                 Logger.Warn("Could not get Legacy Body Decal Data"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             foreach (var item in previousData.FileReplacements[objectKind]) | ||||||
|  |             { | ||||||
|  |                 transientResourceManager.RemoveTransientResource((IntPtr)human, item); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         foreach (var item in transientResourceManager.GetTransientResources((IntPtr)human)) | ||||||
|  |         { | ||||||
|  |             Logger.Verbose("Found transient resource: " + item); | ||||||
|  |             AddReplacement(item, objectKind, previousData, 1); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         st.Stop(); |         st.Stop(); | ||||||
|         Logger.Verbose("Building " + objectKind + " Data took " + st.Elapsed); |         Logger.Verbose("Building " + objectKind + " Data took " + st.Elapsed); | ||||||
|  |  | ||||||
|         return previousData; |         return previousData; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -282,8 +341,6 @@ public class CharacterDataFactory | |||||||
|  |  | ||||||
|         string skeletonPath = $"chara/human/c{raceSexIdString}/skeleton/base/b0001/skl_c{raceSexIdString}b0001.sklb"; |         string skeletonPath = $"chara/human/c{raceSexIdString}/skeleton/base/b0001/skl_c{raceSexIdString}b0001.sklb"; | ||||||
|  |  | ||||||
|         //Logger.Verbose("Adding File Replacement for Skeleton " + skeletonPath); |  | ||||||
|  |  | ||||||
|         var replacement = CreateFileReplacement(skeletonPath, true); |         var replacement = CreateFileReplacement(skeletonPath, true); | ||||||
|         cache.AddFileReplacement(objectKind, replacement); |         cache.AddFileReplacement(objectKind, replacement); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -203,7 +203,7 @@ namespace MareSynchronos.Managers | |||||||
|                     { |                     { | ||||||
|                         PluginLog.Verbose("Removed: " + item); |                         PluginLog.Verbose("Removed: " + item); | ||||||
|  |  | ||||||
|                         db.RemoveRange(db.FileCaches.Where(f => f.Filepath.ToLowerInvariant() == item.ToLowerInvariant())); |                         db.RemoveRange(db.FileCaches.Where(f => f.Filepath.ToLower() == item.ToLowerInvariant())); | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
| @@ -211,7 +211,7 @@ namespace MareSynchronos.Managers | |||||||
|                         var fileCache = Create(item, _rescanTaskCancellationTokenSource.Token); |                         var fileCache = Create(item, _rescanTaskCancellationTokenSource.Token); | ||||||
|                         if (fileCache != null) |                         if (fileCache != null) | ||||||
|                         { |                         { | ||||||
|                             db.RemoveRange(db.FileCaches.Where(f => f.Filepath.ToLowerInvariant() == fileCache.Filepath.ToLowerInvariant())); |                             db.RemoveRange(db.FileCaches.Where(f => f.Filepath.ToLower() == fileCache.Filepath.ToLowerInvariant())); | ||||||
|                             await db.AddAsync(fileCache, _rescanTaskCancellationTokenSource.Token); |                             await db.AddAsync(fileCache, _rescanTaskCancellationTokenSource.Token); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ using MareSynchronos.WebAPI; | |||||||
| namespace MareSynchronos.Managers | namespace MareSynchronos.Managers | ||||||
| { | { | ||||||
|     public delegate void PenumbraRedrawEvent(IntPtr address, int objTblIdx); |     public delegate void PenumbraRedrawEvent(IntPtr address, int objTblIdx); | ||||||
|  |     public delegate void PenumbraResourceLoadEvent(IntPtr drawObject, string gamePath, string filePath); | ||||||
|     public class IpcManager : IDisposable |     public class IpcManager : IDisposable | ||||||
|     { |     { | ||||||
|         private readonly ICallGateSubscriber<int> _glamourerApiVersion; |         private readonly ICallGateSubscriber<int> _glamourerApiVersion; | ||||||
| @@ -31,7 +32,7 @@ namespace MareSynchronos.Managers | |||||||
|         private readonly ICallGateSubscriber<string, string[]>? _reverseResolvePlayer; |         private readonly ICallGateSubscriber<string, string[]>? _reverseResolvePlayer; | ||||||
|         private readonly ICallGateSubscriber<string, string, Dictionary<string, string>, string, int, int> |         private readonly ICallGateSubscriber<string, string, Dictionary<string, string>, string, int, int> | ||||||
|             _penumbraSetTemporaryMod; |             _penumbraSetTemporaryMod; | ||||||
|         private readonly ICallGateSubscriber<string, string, string> _penumbraPlayerPathResolved; |         private readonly ICallGateSubscriber<IntPtr, string, string, string> _penumbraResourceLoaded; | ||||||
|         private readonly DalamudUtil _dalamudUtil; |         private readonly DalamudUtil _dalamudUtil; | ||||||
|  |  | ||||||
|         public IpcManager(DalamudPluginInterface pi, DalamudUtil dalamudUtil) |         public IpcManager(DalamudPluginInterface pi, DalamudUtil dalamudUtil) | ||||||
| @@ -56,9 +57,9 @@ namespace MareSynchronos.Managers | |||||||
|             _glamourerApplyOnlyCustomization = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyCustomizationToCharacter"); |             _glamourerApplyOnlyCustomization = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyCustomizationToCharacter"); | ||||||
|             _glamourerApplyOnlyEquipment = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyEquipmentToCharacter"); |             _glamourerApplyOnlyEquipment = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyEquipmentToCharacter"); | ||||||
|             _glamourerRevertCustomization = pi.GetIpcSubscriber<GameObject?, object>("Glamourer.RevertCharacter"); |             _glamourerRevertCustomization = pi.GetIpcSubscriber<GameObject?, object>("Glamourer.RevertCharacter"); | ||||||
|             _penumbraPlayerPathResolved = pi.GetIpcSubscriber<string, string, string>("Penumbra.PlayerFileResourceResolved"); |             _penumbraResourceLoaded = pi.GetIpcSubscriber<IntPtr, string, string, string>("Penumbra.ResourceLoaded"); | ||||||
|  |  | ||||||
|             _penumbraPlayerPathResolved.Subscribe(PlayerPathResolved); |             _penumbraResourceLoaded.Subscribe(ResourceLoaded); | ||||||
|             _penumbraObjectIsRedrawn.Subscribe(RedrawEvent); |             _penumbraObjectIsRedrawn.Subscribe(RedrawEvent); | ||||||
|             _penumbraInit.Subscribe(PenumbraInit); |             _penumbraInit.Subscribe(PenumbraInit); | ||||||
|             _penumbraDispose.Subscribe(PenumbraDispose); |             _penumbraDispose.Subscribe(PenumbraDispose); | ||||||
| @@ -81,14 +82,19 @@ namespace MareSynchronos.Managers | |||||||
|             this._dalamudUtil = dalamudUtil; |             this._dalamudUtil = dalamudUtil; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void PlayerPathResolved(string arg1, string arg2) |         private void ResourceLoaded(IntPtr ptr, string arg1, string arg2) | ||||||
|         { |         { | ||||||
|             Logger.Debug($"Resolved {arg1} => {arg2}"); |             if (ptr != IntPtr.Zero && string.Compare(arg1, arg2, true, System.Globalization.CultureInfo.InvariantCulture) != 0) | ||||||
|  |             { | ||||||
|  |                 PenumbraResourceLoadEvent?.Invoke(ptr, arg1, arg2); | ||||||
|  |                 //Logger.Debug($"Resolved {ptr:X}: {arg1} => {arg2}"); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public event VoidDelegate? PenumbraInitialized; |         public event VoidDelegate? PenumbraInitialized; | ||||||
|         public event VoidDelegate? PenumbraDisposed; |         public event VoidDelegate? PenumbraDisposed; | ||||||
|         public event PenumbraRedrawEvent? PenumbraRedrawEvent; |         public event PenumbraRedrawEvent? PenumbraRedrawEvent; | ||||||
|  |         public event PenumbraResourceLoadEvent? PenumbraResourceLoadEvent; | ||||||
|  |  | ||||||
|         public bool Initialized => CheckPenumbraApi(); |         public bool Initialized => CheckPenumbraApi(); | ||||||
|         public bool CheckGlamourerApi() |         public bool CheckGlamourerApi() | ||||||
| @@ -122,6 +128,7 @@ namespace MareSynchronos.Managers | |||||||
|             _penumbraDispose.Unsubscribe(PenumbraDispose); |             _penumbraDispose.Unsubscribe(PenumbraDispose); | ||||||
|             _penumbraInit.Unsubscribe(PenumbraInit); |             _penumbraInit.Unsubscribe(PenumbraInit); | ||||||
|             _penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent); |             _penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent); | ||||||
|  |             _penumbraResourceLoaded.Unsubscribe(ResourceLoaded); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void GlamourerApplyAll(string? customization, IntPtr obj) |         public void GlamourerApplyAll(string? customization, IntPtr obj) | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ namespace MareSynchronos.Managers | |||||||
|         private readonly ApiController _apiController; |         private readonly ApiController _apiController; | ||||||
|         private readonly CharacterDataFactory _characterDataFactory; |         private readonly CharacterDataFactory _characterDataFactory; | ||||||
|         private readonly DalamudUtil _dalamudUtil; |         private readonly DalamudUtil _dalamudUtil; | ||||||
|  |         private readonly TransientResourceManager _transientResourceManager; | ||||||
|         private readonly IpcManager _ipcManager; |         private readonly IpcManager _ipcManager; | ||||||
|         public event PlayerHasChanged? PlayerHasChanged; |         public event PlayerHasChanged? PlayerHasChanged; | ||||||
|         public CharacterCacheDto? LastCreatedCharacterData { get; private set; } |         public CharacterCacheDto? LastCreatedCharacterData { get; private set; } | ||||||
| @@ -34,7 +35,7 @@ namespace MareSynchronos.Managers | |||||||
|         private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>(); |         private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>(); | ||||||
|  |  | ||||||
|         public unsafe PlayerManager(ApiController apiController, IpcManager ipcManager, |         public unsafe PlayerManager(ApiController apiController, IpcManager ipcManager, | ||||||
|             CharacterDataFactory characterDataFactory, DalamudUtil dalamudUtil) |             CharacterDataFactory characterDataFactory, DalamudUtil dalamudUtil, TransientResourceManager transientResourceManager) | ||||||
|         { |         { | ||||||
|             Logger.Verbose("Creating " + nameof(PlayerManager)); |             Logger.Verbose("Creating " + nameof(PlayerManager)); | ||||||
|  |  | ||||||
| @@ -42,10 +43,11 @@ namespace MareSynchronos.Managers | |||||||
|             _ipcManager = ipcManager; |             _ipcManager = ipcManager; | ||||||
|             _characterDataFactory = characterDataFactory; |             _characterDataFactory = characterDataFactory; | ||||||
|             _dalamudUtil = dalamudUtil; |             _dalamudUtil = dalamudUtil; | ||||||
|  |             _transientResourceManager = transientResourceManager; | ||||||
|             _apiController.Connected += ApiControllerOnConnected; |             _apiController.Connected += ApiControllerOnConnected; | ||||||
|             _apiController.Disconnected += ApiController_Disconnected; |             _apiController.Disconnected += ApiController_Disconnected; | ||||||
|             _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; |             _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; | ||||||
|  |             _transientResourceManager.TransientResourceLoaded += HandleTransientResourceLoad; | ||||||
|  |  | ||||||
|             Logger.Debug("Watching Player, ApiController is Connected: " + _apiController.IsConnected); |             Logger.Debug("Watching Player, ApiController is Connected: " + _apiController.IsConnected); | ||||||
|             if (_apiController.IsConnected) |             if (_apiController.IsConnected) | ||||||
| @@ -63,6 +65,19 @@ namespace MareSynchronos.Managers | |||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public void HandleTransientResourceLoad(IntPtr drawObj) | ||||||
|  |         { | ||||||
|  |             foreach (var obj in playerRelatedObjects) | ||||||
|  |             { | ||||||
|  |                 if (obj.DrawObjectAddress == drawObj && !obj.HasUnprocessedUpdate) | ||||||
|  |                 { | ||||||
|  |                     obj.HasUnprocessedUpdate = true; | ||||||
|  |                     OnPlayerOrAttachedObjectsChanged(); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public void Dispose() |         public void Dispose() | ||||||
|         { |         { | ||||||
|             Logger.Verbose("Disposing " + nameof(PlayerManager)); |             Logger.Verbose("Disposing " + nameof(PlayerManager)); | ||||||
| @@ -72,13 +87,17 @@ namespace MareSynchronos.Managers | |||||||
|  |  | ||||||
|             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; |             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; | ||||||
|             _dalamudUtil.FrameworkUpdate -= DalamudUtilOnFrameworkUpdate; |             _dalamudUtil.FrameworkUpdate -= DalamudUtilOnFrameworkUpdate; | ||||||
|  |  | ||||||
|  |             _transientResourceManager.TransientResourceLoaded -= HandleTransientResourceLoad; | ||||||
|  |  | ||||||
|  |             _playerChangedCts?.Cancel(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private unsafe void DalamudUtilOnFrameworkUpdate() |         private unsafe void DalamudUtilOnFrameworkUpdate() | ||||||
|         { |         { | ||||||
|             if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized) return; |             //if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized) return; | ||||||
|  |  | ||||||
|             if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; |             //if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; | ||||||
|  |  | ||||||
|             playerRelatedObjects.ForEach(k => k.CheckAndUpdateObject()); |             playerRelatedObjects.ForEach(k => k.CheckAndUpdateObject()); | ||||||
|             if (playerRelatedObjects.Any(c => c.HasUnprocessedUpdate && !c.IsProcessing)) |             if (playerRelatedObjects.Any(c => c.HasUnprocessedUpdate && !c.IsProcessing)) | ||||||
| @@ -86,7 +105,7 @@ namespace MareSynchronos.Managers | |||||||
|                 OnPlayerOrAttachedObjectsChanged(); |                 OnPlayerOrAttachedObjectsChanged(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             _lastPlayerObjectCheck = DateTime.Now; |             //_lastPlayerObjectCheck = DateTime.Now; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ApiControllerOnConnected() |         private void ApiControllerOnConnected() | ||||||
| @@ -119,6 +138,7 @@ namespace MareSynchronos.Managers | |||||||
|  |  | ||||||
|             while (!PermanentDataCache.IsReady && !token.IsCancellationRequested) |             while (!PermanentDataCache.IsReady && !token.IsCancellationRequested) | ||||||
|             { |             { | ||||||
|  |                 Logger.Verbose("Waiting until cache is ready"); | ||||||
|                 await Task.Delay(50, token); |                 await Task.Delay(50, token); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								MareSynchronos/Managers/TransientResourceManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								MareSynchronos/Managers/TransientResourceManager.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | using MareSynchronos.Models; | ||||||
|  | using MareSynchronos.Utils; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace MareSynchronos.Managers | ||||||
|  | { | ||||||
|  |     public delegate void TransientResourceLoadedEvent(IntPtr drawObject); | ||||||
|  |  | ||||||
|  |     public class TransientResourceManager : IDisposable | ||||||
|  |     { | ||||||
|  |         private readonly IpcManager manager; | ||||||
|  |         private readonly DalamudUtil dalamudUtil; | ||||||
|  |         public event TransientResourceLoadedEvent? TransientResourceLoaded; | ||||||
|  |  | ||||||
|  |         private Dictionary<IntPtr, HashSet<string>> TransientResources { get; } = new(); | ||||||
|  |         public TransientResourceManager(IpcManager manager, DalamudUtil dalamudUtil) | ||||||
|  |         { | ||||||
|  |             manager.PenumbraResourceLoadEvent += Manager_PenumbraResourceLoadEvent; | ||||||
|  |             this.manager = manager; | ||||||
|  |             this.dalamudUtil = dalamudUtil; | ||||||
|  |             dalamudUtil.FrameworkUpdate += DalamudUtil_FrameworkUpdate; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void DalamudUtil_FrameworkUpdate() | ||||||
|  |         { | ||||||
|  |             foreach (var item in TransientResources.ToList()) | ||||||
|  |             { | ||||||
|  |                 if (!dalamudUtil.IsDrawObjectPresent(item.Key)) | ||||||
|  |                 { | ||||||
|  |                     Logger.Debug("Object not present anymore: " + item.Key); | ||||||
|  |                     TransientResources.Remove(item.Key); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public List<string> GetTransientResources(IntPtr drawObject) | ||||||
|  |         { | ||||||
|  |             if (TransientResources.TryGetValue(drawObject, out var result)) | ||||||
|  |             { | ||||||
|  |                 return result.ToList(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return new List<string>(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void Manager_PenumbraResourceLoadEvent(IntPtr drawObject, string gamePath, string filePath) | ||||||
|  |         { | ||||||
|  |             if (!TransientResources.ContainsKey(drawObject)) | ||||||
|  |             { | ||||||
|  |                 TransientResources[drawObject] = new(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (filePath.StartsWith("|")) | ||||||
|  |             { | ||||||
|  |                 filePath = filePath.Split("|")[2]; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var newPath = filePath.ToLowerInvariant().Replace("\\", "/"); | ||||||
|  |  | ||||||
|  |             if (filePath != gamePath && !TransientResources[drawObject].Contains(newPath)) | ||||||
|  |             { | ||||||
|  |                 TransientResources[drawObject].Add(newPath); | ||||||
|  |                 Logger.Debug($"Adding {filePath.ToLowerInvariant().Replace("\\", "/")} for {drawObject}"); | ||||||
|  |                 TransientResourceLoaded?.Invoke(drawObject); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void RemoveTransientResource(IntPtr drawObject, FileReplacement fileReplacement) | ||||||
|  |         { | ||||||
|  |             if (TransientResources.ContainsKey(drawObject)) | ||||||
|  |             { | ||||||
|  |                 TransientResources[drawObject].RemoveWhere(f => fileReplacement.ResolvedPath == f); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Dispose() | ||||||
|  |         { | ||||||
|  |             dalamudUtil.FrameworkUpdate -= DalamudUtil_FrameworkUpdate; | ||||||
|  |             manager.PenumbraResourceLoadEvent -= Manager_PenumbraResourceLoadEvent; | ||||||
|  |             TransientResources.Clear(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -93,6 +93,7 @@ namespace MareSynchronos.Models | |||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|  |                 Logger.Debug("Adding new file to DB: " + fi.FullName + ", " + hash); | ||||||
|                 db.Add(new FileCache() |                 db.Add(new FileCache() | ||||||
|                 { |                 { | ||||||
|                     Hash = hash, |                     Hash = hash, | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ namespace MareSynchronos.Models | |||||||
|                 if (addr || equip || drawObj || nameChange) |                 if (addr || equip || drawObj || nameChange) | ||||||
|                 { |                 { | ||||||
|                     _name = name; |                     _name = name; | ||||||
|                     Logger.Verbose(ObjectKind + " Changed: " + _name + ", now: " + curPtr + ", " + (IntPtr)chara->GameObject.DrawObject); |                     Logger.Verbose($"{ObjectKind} changed: {_name}, now: {curPtr:X}, {(IntPtr)chara->GameObject.DrawObject:X}"); | ||||||
|  |  | ||||||
|                     Address = curPtr; |                     Address = curPtr; | ||||||
|                     DrawObjectAddress = (IntPtr)chara->GameObject.DrawObject; |                     DrawObjectAddress = (IntPtr)chara->GameObject.DrawObject; | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ namespace MareSynchronos | |||||||
|         private readonly SettingsUi _settingsUi; |         private readonly SettingsUi _settingsUi; | ||||||
|         private readonly WindowSystem _windowSystem; |         private readonly WindowSystem _windowSystem; | ||||||
|         private PlayerManager? _playerManager; |         private PlayerManager? _playerManager; | ||||||
|  |         private TransientResourceManager? _transientResourceManager; | ||||||
|         private readonly DalamudUtil _dalamudUtil; |         private readonly DalamudUtil _dalamudUtil; | ||||||
|         private OnlinePlayerManager? _characterCacheManager; |         private OnlinePlayerManager? _characterCacheManager; | ||||||
|         private readonly DownloadUi _downloadUi; |         private readonly DownloadUi _downloadUi; | ||||||
| @@ -129,6 +130,7 @@ namespace MareSynchronos | |||||||
|             _ipcManager?.Dispose(); |             _ipcManager?.Dispose(); | ||||||
|             _playerManager?.Dispose(); |             _playerManager?.Dispose(); | ||||||
|             _characterCacheManager?.Dispose(); |             _characterCacheManager?.Dispose(); | ||||||
|  |             _transientResourceManager?.Dispose(); | ||||||
|             Logger.Debug("Shut down"); |             Logger.Debug("Shut down"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -160,6 +162,7 @@ namespace MareSynchronos | |||||||
|             Logger.Debug("Client logout"); |             Logger.Debug("Client logout"); | ||||||
|             _characterCacheManager?.Dispose(); |             _characterCacheManager?.Dispose(); | ||||||
|             _playerManager?.Dispose(); |             _playerManager?.Dispose(); | ||||||
|  |             _transientResourceManager?.Dispose(); | ||||||
|             PluginInterface.UiBuilder.Draw -= Draw; |             PluginInterface.UiBuilder.Draw -= Draw; | ||||||
|             PluginInterface.UiBuilder.OpenConfigUi -= OpenUi; |             PluginInterface.UiBuilder.OpenConfigUi -= OpenUi; | ||||||
|             _commandManager.RemoveHandler(CommandName); |             _commandManager.RemoveHandler(CommandName); | ||||||
| @@ -169,6 +172,7 @@ namespace MareSynchronos | |||||||
|         { |         { | ||||||
|             _characterCacheManager?.Dispose(); |             _characterCacheManager?.Dispose(); | ||||||
|             _playerManager?.Dispose(); |             _playerManager?.Dispose(); | ||||||
|  |             _transientResourceManager?.Dispose(); | ||||||
|  |  | ||||||
|             Task.Run(WaitForPlayerAndLaunchCharacterManager); |             Task.Run(WaitForPlayerAndLaunchCharacterManager); | ||||||
|         } |         } | ||||||
| @@ -182,10 +186,11 @@ namespace MareSynchronos | |||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|  |                 _transientResourceManager = new TransientResourceManager(_ipcManager, _dalamudUtil); | ||||||
|                 var characterCacheFactory = |                 var characterCacheFactory = | ||||||
|                     new CharacterDataFactory(_dalamudUtil, _ipcManager); |                     new CharacterDataFactory(_dalamudUtil, _ipcManager, _transientResourceManager); | ||||||
|                 _playerManager = new PlayerManager(_apiController, _ipcManager, |                 _playerManager = new PlayerManager(_apiController, _ipcManager, | ||||||
|                     characterCacheFactory, _dalamudUtil); |                     characterCacheFactory, _dalamudUtil, _transientResourceManager); | ||||||
|                 _characterCacheManager = new OnlinePlayerManager(_framework, |                 _characterCacheManager = new OnlinePlayerManager(_framework, | ||||||
|                     _apiController, _dalamudUtil, _ipcManager, _playerManager); |                     _apiController, _dalamudUtil, _ipcManager, _playerManager); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -28,6 +28,19 @@ namespace MareSynchronos.Utils | |||||||
|         public event LogOut? LogOut; |         public event LogOut? LogOut; | ||||||
|         public event FrameworkUpdate? FrameworkUpdate; |         public event FrameworkUpdate? FrameworkUpdate; | ||||||
|  |  | ||||||
|  |         public unsafe bool IsDrawObjectPresent(IntPtr key) | ||||||
|  |         { | ||||||
|  |             foreach (var obj in _objectTable) | ||||||
|  |             { | ||||||
|  |                 if ((IntPtr)((GameObject*)obj.Address)->GetDrawObject() == key) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public DalamudUtil(ClientState clientState, ObjectTable objectTable, Framework framework) |         public DalamudUtil(ClientState clientState, ObjectTable objectTable, Framework framework) | ||||||
|         { |         { | ||||||
|             _clientState = clientState; |             _clientState = clientState; | ||||||
|   | |||||||
| @@ -172,7 +172,7 @@ namespace MareSynchronos.WebAPI | |||||||
|                     { |                     { | ||||||
|                         CurrentUploads.Add(new UploadFileTransfer(file) |                         CurrentUploads.Add(new UploadFileTransfer(file) | ||||||
|                         { |                         { | ||||||
|                             Total = new FileInfo(db.FileCaches.FirstOrDefault(f => f.Hash.ToLowerInvariant() == file.Hash.ToLowerInvariant()) |                             Total = new FileInfo(db.FileCaches.FirstOrDefault(f => f.Hash.ToLower() == file.Hash.ToLower()) | ||||||
|                                 ?.Filepath ?? string.Empty).Length |                                 ?.Filepath ?? string.Empty).Length | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -128,6 +128,10 @@ namespace MareSynchronos.WebAPI | |||||||
|  |  | ||||||
|         public async Task CreateConnections() |         public async Task CreateConnections() | ||||||
|         { |         { | ||||||
|  |             Logger.Info("Recreating Connection"); | ||||||
|  |  | ||||||
|  |             await StopConnection(_connectionCancellationTokenSource.Token); | ||||||
|  |  | ||||||
|             if (_pluginConfiguration.FullPause) |             if (_pluginConfiguration.FullPause) | ||||||
|             { |             { | ||||||
|                 ServerState = ServerState.Disconnected; |                 ServerState = ServerState.Disconnected; | ||||||
| @@ -135,10 +139,6 @@ namespace MareSynchronos.WebAPI | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             Logger.Info("Recreating Connection"); |  | ||||||
|  |  | ||||||
|             await StopConnection(_connectionCancellationTokenSource.Token); |  | ||||||
|  |  | ||||||
|             _connectionCancellationTokenSource.Cancel(); |             _connectionCancellationTokenSource.Cancel(); | ||||||
|             _connectionCancellationTokenSource = new CancellationTokenSource(); |             _connectionCancellationTokenSource = new CancellationTokenSource(); | ||||||
|             var token = _connectionCancellationTokenSource.Token; |             var token = _connectionCancellationTokenSource.Token; | ||||||
| @@ -329,6 +329,7 @@ namespace MareSynchronos.WebAPI | |||||||
|         { |         { | ||||||
|             if (_mareHub is not null) |             if (_mareHub is not null) | ||||||
|             { |             { | ||||||
|  |                 _uploadCancellationTokenSource?.Cancel(); | ||||||
|                 Logger.Info("Stopping existing connection"); |                 Logger.Info("Stopping existing connection"); | ||||||
|                 await _mareHub.StopAsync(token); |                 await _mareHub.StopAsync(token); | ||||||
|                 _mareHub.Closed -= MareHubOnClosed; |                 _mareHub.Closed -= MareHubOnClosed; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stanley Dimant
					Stanley Dimant