some cleanup and sanitizing
This commit is contained in:
		| @@ -169,7 +169,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase | |||||||
|  |  | ||||||
|     private void DalamudUtil_FrameworkUpdate() |     private void DalamudUtil_FrameworkUpdate() | ||||||
|     { |     { | ||||||
|         _cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress().GetAwaiter().GetResult()).ToHashSet(); |         _cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress()).ToHashSet(); | ||||||
|         _cachedHandledPaths.Clear(); |         _cachedHandledPaths.Clear(); | ||||||
|         foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList()) |         foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList()) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|     private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter; |     private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter; | ||||||
|     private readonly DalamudUtilService _dalamudUtil; |     private readonly DalamudUtilService _dalamudUtil; | ||||||
|     private readonly ICallGateSubscriber<int> _glamourerApiVersion; |     private readonly ICallGateSubscriber<int> _glamourerApiVersion; | ||||||
|     private readonly SemaphoreSlim _glamourerApplicationSemaphore = new(2); |     private readonly SemaphoreSlim _redrawSemaphore = new(2); | ||||||
|     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyAll; |     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyAll; | ||||||
|     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization; |     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization; | ||||||
|     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment; |     private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment; | ||||||
| @@ -167,10 +167,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|  |  | ||||||
|     public bool CheckPenumbraApi() => _penumbraAvailable; |     public bool CheckPenumbraApi() => _penumbraAvailable; | ||||||
|  |  | ||||||
|     public async Task CustomizePlusRevert(IntPtr character) |     public async Task CustomizePlusRevertAsync(IntPtr character) | ||||||
|     { |     { | ||||||
|         if (!CheckCustomizePlusApi()) return; |         if (!CheckCustomizePlusApi()) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is Character c) |         if (gameObj is Character c) | ||||||
|         { |         { | ||||||
|             Logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X")); |             Logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X")); | ||||||
| @@ -178,10 +178,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task CustomizePlusSetBodyScale(IntPtr character, string scale) |     public async Task CustomizePlusSetBodyScaleAsync(IntPtr character, string scale) | ||||||
|     { |     { | ||||||
|         if (!CheckCustomizePlusApi() || string.IsNullOrEmpty(scale)) return; |         if (!CheckCustomizePlusApi() || string.IsNullOrEmpty(scale)) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is Character c) |         if (gameObj is Character c) | ||||||
|         { |         { | ||||||
|             string decodedScale = Encoding.UTF8.GetString(Convert.FromBase64String(scale)); |             string decodedScale = Encoding.UTF8.GetString(Convert.FromBase64String(scale)); | ||||||
| @@ -190,7 +190,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<string> GetCustomizePlusScale() |     public async Task<string> GetCustomizePlusScaleAsync() | ||||||
|     { |     { | ||||||
|         if (!CheckCustomizePlusApi()) return string.Empty; |         if (!CheckCustomizePlusApi()) return string.Empty; | ||||||
|         var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.PlayerName)).ConfigureAwait(false); |         var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.PlayerName)).ConfigureAwait(false); | ||||||
| @@ -204,61 +204,61 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         return _heelsGetOffset.InvokeFunc(); |         return _heelsGetOffset.InvokeFunc(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) |     public async Task GlamourerApplyAllAsync(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) | ||||||
|     { |     { | ||||||
|         if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; |         if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false); |             await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false); | ||||||
|             var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false); |             var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false); | ||||||
|             if (gameObj is Character c) |             if (gameObj is Character c) | ||||||
|             { |             { | ||||||
|                 await PenumbraRedrawAsync(logger, handler, applicationId, () => |                 await PenumbraRedrawAsync(logger, handler, applicationId, () => | ||||||
|                 { |                 { | ||||||
|                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId); |                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId); | ||||||
|                     _glamourerApplyAll!.InvokeAction(customization, c); |                     _glamourerApplyAll!.InvokeAction(customization, c); | ||||||
|                 }, fireAndForget).ConfigureAwait(false); |                 }).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         finally |         finally | ||||||
|         { |         { | ||||||
|             _glamourerApplicationSemaphore.Release(); |             _redrawSemaphore.Release(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task GlamourerApplyCustomizationAndEquipment(ILogger logger, GameObjectHandler handler, string customization, string equipment, Guid applicationid, CancellationToken token, bool fireAndForget = false) |     public async Task GlamourerApplyCustomizationAndEquipmentAsync(ILogger logger, GameObjectHandler handler, string customization, string equipment, Guid applicationid, CancellationToken token, bool fireAndForget = false) | ||||||
|     { |     { | ||||||
|         if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; |         if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false); |             await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false); | ||||||
|             var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false); |             var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false); | ||||||
|             if (gameObj is Character c) |             if (gameObj is Character c) | ||||||
|             { |             { | ||||||
|                 await PenumbraRedrawAsync(logger, handler, applicationid, () => |                 await PenumbraRedrawAsync(logger, handler, applicationid, () => | ||||||
|                 { |                 { | ||||||
|                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyCustomization", applicationid); |                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyCustomization", applicationid); | ||||||
|                     _glamourerApplyOnlyCustomization!.InvokeAction(customization, c); |                     _glamourerApplyOnlyCustomization!.InvokeAction(customization, c); | ||||||
|                 }, fireAndForget).ConfigureAwait(false); |                 }).ConfigureAwait(false); | ||||||
|                 await PenumbraRedrawAsync(logger, handler, applicationid, () => |                 await PenumbraRedrawAsync(logger, handler, applicationid, () => | ||||||
|                 { |                 { | ||||||
|                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyEquipment", applicationid); |                     logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyEquipment", applicationid); | ||||||
|                     _glamourerApplyOnlyEquipment!.InvokeAction(equipment, c); |                     _glamourerApplyOnlyEquipment!.InvokeAction(equipment, c); | ||||||
|                 }, fireAndForget).ConfigureAwait(false); |                 }).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         finally |         finally | ||||||
|         { |         { | ||||||
|             _glamourerApplicationSemaphore.Release(); |             _redrawSemaphore.Release(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<string> GlamourerGetCharacterCustomization(IntPtr character) |     public async Task<string> GlamourerGetCharacterCustomizationAsync(IntPtr character) | ||||||
|     { |     { | ||||||
|         if (!CheckGlamourerApi()) return string.Empty; |         if (!CheckGlamourerApi()) return string.Empty; | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |             var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|             if (gameObj is Character c) |             if (gameObj is Character c) | ||||||
|             { |             { | ||||||
|                 var glamourerString = await _dalamudUtil.RunOnFrameworkThread(() => _glamourerGetAllCustomization!.InvokeFunc(c)).ConfigureAwait(false); |                 var glamourerString = await _dalamudUtil.RunOnFrameworkThread(() => _glamourerGetAllCustomization!.InvokeFunc(c)).ConfigureAwait(false); | ||||||
| @@ -276,10 +276,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task HeelsRestoreOffsetForPlayer(IntPtr character) |     public async Task HeelsRestoreOffsetForPlayerAsync(IntPtr character) | ||||||
|     { |     { | ||||||
|         if (!CheckHeelsApi()) return; |         if (!CheckHeelsApi()) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj != null) |         if (gameObj != null) | ||||||
|         { |         { | ||||||
|             Logger.LogTrace("Restoring Heels data to {chara}", character.ToString("X")); |             Logger.LogTrace("Restoring Heels data to {chara}", character.ToString("X")); | ||||||
| @@ -287,10 +287,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task HeelsSetOffsetForPlayer(IntPtr character, float offset) |     public async Task HeelsSetOffsetForPlayerAsync(IntPtr character, float offset) | ||||||
|     { |     { | ||||||
|         if (!CheckHeelsApi()) return; |         if (!CheckHeelsApi()) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj != null) |         if (gameObj != null) | ||||||
|         { |         { | ||||||
|             Logger.LogTrace("Applying Heels data to {chara}", character.ToString("X")); |             Logger.LogTrace("Applying Heels data to {chara}", character.ToString("X")); | ||||||
| @@ -298,10 +298,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task HonorificClearTitle(nint character) |     public async Task HonorificClearTitleAsync(nint character) | ||||||
|     { |     { | ||||||
|         if (!CheckHonorificApi()) return; |         if (!CheckHonorificApi()) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is PlayerCharacter c) |         if (gameObj is PlayerCharacter c) | ||||||
|         { |         { | ||||||
|             Logger.LogTrace("Honorific removing for {addr}", c.Address.ToString("X")); |             Logger.LogTrace("Honorific removing for {addr}", c.Address.ToString("X")); | ||||||
| @@ -316,11 +316,11 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         return string.IsNullOrEmpty(title) ? string.Empty : $"{(isPrefix ? 1 : 0)}{title}"; |         return string.IsNullOrEmpty(title) ? string.Empty : $"{(isPrefix ? 1 : 0)}{title}"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task HonorificSetTitle(IntPtr character, string honorificData) |     public async Task HonorificSetTitleAsync(IntPtr character, string honorificData) | ||||||
|     { |     { | ||||||
|         if (!CheckHonorificApi()) return; |         if (!CheckHonorificApi()) return; | ||||||
|         Logger.LogTrace("Applying Honorific data to {chara}", character.ToString("X")); |         Logger.LogTrace("Applying Honorific data to {chara}", character.ToString("X")); | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is PlayerCharacter pc) |         if (gameObj is PlayerCharacter pc) | ||||||
|         { |         { | ||||||
|             await _dalamudUtil.RunOnFrameworkThread(() => |             await _dalamudUtil.RunOnFrameworkThread(() => | ||||||
| @@ -337,7 +337,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<string> PalettePlusBuildPalette() |     public async Task<string> PalettePlusBuildPaletteAsync() | ||||||
|     { |     { | ||||||
|         if (!CheckPalettePlusApi()) return string.Empty; |         if (!CheckPalettePlusApi()) return string.Empty; | ||||||
|         var palette = await _dalamudUtil.RunOnFrameworkThread(() => _palettePlusBuildCharaPalette.InvokeFunc(_dalamudUtil.PlayerCharacter)).ConfigureAwait(false); |         var palette = await _dalamudUtil.RunOnFrameworkThread(() => _palettePlusBuildCharaPalette.InvokeFunc(_dalamudUtil.PlayerCharacter)).ConfigureAwait(false); | ||||||
| @@ -345,10 +345,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette)); |         return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PalettePlusRemovePalette(IntPtr character) |     public async Task PalettePlusRemovePaletteAsync(IntPtr character) | ||||||
|     { |     { | ||||||
|         if (!CheckPalettePlusApi()) return; |         if (!CheckPalettePlusApi()) return; | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is Character c) |         if (gameObj is Character c) | ||||||
|         { |         { | ||||||
|             Logger.LogTrace("PalettePlus removing for {addr}", c.Address.ToString("X")); |             Logger.LogTrace("PalettePlus removing for {addr}", c.Address.ToString("X")); | ||||||
| @@ -356,11 +356,11 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PalettePlusSetPalette(IntPtr character, string palette) |     public async Task PalettePlusSetPaletteAsync(IntPtr character, string palette) | ||||||
|     { |     { | ||||||
|         if (!CheckPalettePlusApi()) return; |         if (!CheckPalettePlusApi()) return; | ||||||
|         string decodedPalette = Encoding.UTF8.GetString(Convert.FromBase64String(palette)); |         string decodedPalette = Encoding.UTF8.GetString(Convert.FromBase64String(palette)); | ||||||
|         var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false); |         var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false); | ||||||
|         if (gameObj is Character c) |         if (gameObj is Character c) | ||||||
|         { |         { | ||||||
|             await _dalamudUtil.RunOnFrameworkThread(() => |             await _dalamudUtil.RunOnFrameworkThread(() => | ||||||
| @@ -385,29 +385,29 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         return _penumbraGetMetaManipulations.Invoke(); |         return _penumbraGetMetaManipulations.Invoke(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PenumbraRedraw(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token, bool fireAndForget = false) |     public async Task PenumbraRedrawAsync(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token, bool fireAndForget = false) | ||||||
|     { |     { | ||||||
|         if (!CheckPenumbraApi() || _dalamudUtil.IsZoning) return; |         if (!CheckPenumbraApi() || _dalamudUtil.IsZoning) return; | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false); |             await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false); | ||||||
|             var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false); |             var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false); | ||||||
|             if (gameObj is Character c) |             if (gameObj is Character c) | ||||||
|             { |             { | ||||||
|                 await PenumbraRedrawAsync(logger, handler, applicationId, () => |                 await PenumbraRedrawAsync(logger, handler, applicationId, () => | ||||||
|                 { |                 { | ||||||
|                     logger.LogDebug("[{appid}] Calling on IPC: PenumbraRedraw", applicationId); |                     logger.LogDebug("[{appid}] Calling on IPC: PenumbraRedraw", applicationId); | ||||||
|                     _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw); |                     _penumbraRedrawObject!.Invoke(c, RedrawType.Redraw); | ||||||
|                 }, fireAndForget).ConfigureAwait(false); |                 }).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         finally |         finally | ||||||
|         { |         { | ||||||
|             _glamourerApplicationSemaphore.Release(); |             _redrawSemaphore.Release(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PenumbraRemoveTemporaryCollection(ILogger logger, Guid applicationId, string characterName) |     public async Task PenumbraRemoveTemporaryCollectionAsync(ILogger logger, Guid applicationId, string characterName) | ||||||
|     { |     { | ||||||
|         if (!CheckPenumbraApi()) return; |         if (!CheckPenumbraApi()) return; | ||||||
|         await _dalamudUtil.RunOnFrameworkThread(() => |         await _dalamudUtil.RunOnFrameworkThread(() => | ||||||
| @@ -421,12 +421,12 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         }).ConfigureAwait(false); |         }).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePaths(string[] forward, string[] reverse) |     public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePathsAsync(string[] forward, string[] reverse) | ||||||
|     { |     { | ||||||
|         return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false); |         return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PenumbraSetTemporaryMods(ILogger logger, Guid applicationId, string characterName, int? idx, Dictionary<string, string> modPaths, string manipulationData) |     public async Task PenumbraSetTemporaryModsAsync(ILogger logger, Guid applicationId, string characterName, int? idx, Dictionary<string, string> modPaths, string manipulationData) | ||||||
|     { |     { | ||||||
|         if (!CheckPenumbraApi() || idx == null) return; |         if (!CheckPenumbraApi() || idx == null) return; | ||||||
|  |  | ||||||
| @@ -650,36 +650,23 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase | |||||||
|         _penumbraRedraw!.Invoke("self", RedrawType.Redraw); |         _penumbraRedraw!.Invoke("self", RedrawType.Redraw); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private async Task PenumbraRedrawAsync(ILogger logger, GameObjectHandler obj, Guid applicationId, Action action, bool fireAndForget) |     private async Task PenumbraRedrawAsync(ILogger logger, GameObjectHandler obj, Guid applicationId, Action action) | ||||||
|     { |     { | ||||||
|         Mediator.Publish(new PenumbraStartRedrawMessage(obj.Address)); |         Mediator.Publish(new PenumbraStartRedrawMessage(obj.Address)); | ||||||
|  |  | ||||||
|         _penumbraRedrawRequests[obj.Address] = !fireAndForget; |         _penumbraRedrawRequests[obj.Address] = true; | ||||||
|  |  | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             if (!fireAndForget) |             CancellationTokenSource cancelToken = new CancellationTokenSource(); | ||||||
|             { |             cancelToken.CancelAfter(TimeSpan.FromSeconds(15)); | ||||||
|                 while (!await _dalamudUtil.RunOnFrameworkThread(() => |             await obj.ActOnFrameworkAfterEnsureNoDrawAsync(action, cancelToken.Token); | ||||||
|                     { |  | ||||||
|                         if (obj.IsBeingDrawn()) return false; |  | ||||||
|                         action(); |  | ||||||
|                         return true; |  | ||||||
|                     }).ConfigureAwait(false)) |  | ||||||
|                 { |  | ||||||
|                     await Task.Delay(250).ConfigureAwait(false); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             await Task.Delay(TimeSpan.FromSeconds(1), _disposalCts.Token).ConfigureAwait(false); |             await Task.Delay(TimeSpan.FromSeconds(1), _disposalCts.Token).ConfigureAwait(false); | ||||||
|  |  | ||||||
|             if (!_disposalCts.Token.IsCancellationRequested) |             if (!_disposalCts.Token.IsCancellationRequested) | ||||||
|                 await _dalamudUtil.WaitWhileCharacterIsDrawing(logger, obj, applicationId, 30000, _disposalCts.Token).ConfigureAwait(false); |                 await _dalamudUtil.WaitWhileCharacterIsDrawing(logger, obj, applicationId, 30000, _disposalCts.Token).ConfigureAwait(false); | ||||||
|         } |         } | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 _ = _dalamudUtil.RunOnFrameworkThread(action); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         finally |         finally | ||||||
|         { |         { | ||||||
|             _penumbraRedrawRequests[obj.Address] = false; |             _penumbraRedrawRequests[obj.Address] = false; | ||||||
|   | |||||||
| @@ -65,14 +65,14 @@ public class MareCharaFileManager | |||||||
|                 } |                 } | ||||||
|                 var applicationId = Guid.NewGuid(); |                 var applicationId = Guid.NewGuid(); | ||||||
|                 _ipcManager.ToggleGposeQueueMode(on: true); |                 _ipcManager.ToggleGposeQueueMode(on: true); | ||||||
|                 await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); |                 await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); | ||||||
|                 await _ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(), |                 await _ipcManager.PenumbraSetTemporaryModsAsync(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(), | ||||||
|                     extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal), |                     extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal), | ||||||
|                     LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false); |                     LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false); | ||||||
|                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => charaTarget.Address, false).ConfigureAwait(false); |                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => charaTarget.Address, false).ConfigureAwait(false); | ||||||
|                 await _ipcManager.GlamourerApplyAll(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false); |                 await _ipcManager.GlamourerApplyAllAsync(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false); | ||||||
|                 _dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000); |                 _dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000); | ||||||
|                 await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); |                 await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); | ||||||
|                 _ipcManager.ToggleGposeQueueMode(on: false); |                 _ipcManager.ToggleGposeQueueMode(on: false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -316,7 +316,7 @@ public class PlayerDataFactory | |||||||
|         // wait until chara is not drawing and present so nothing spontaneously explodes |         // wait until chara is not drawing and present so nothing spontaneously explodes | ||||||
|         await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, playerRelatedObject, Guid.NewGuid(), 30000, ct: token).ConfigureAwait(false); |         await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, playerRelatedObject, Guid.NewGuid(), 30000, ct: token).ConfigureAwait(false); | ||||||
|         int totalWaitTime = 10000; |         int totalWaitTime = 10000; | ||||||
|         while (!DalamudUtilService.IsObjectPresent(await _dalamudUtil.RunOnFrameworkThread(() => _dalamudUtil.CreateGameObject(charaPointer).GetAwaiter().GetResult()).ConfigureAwait(false)) && totalWaitTime > 0) |         while (!DalamudUtilService.IsObjectPresent(await _dalamudUtil.RunOnFrameworkThread(() => _dalamudUtil.CreateGameObjectAsync(charaPointer).GetAwaiter().GetResult()).ConfigureAwait(false)) && totalWaitTime > 0) | ||||||
|         { |         { | ||||||
|             _logger.LogTrace("Character is null but it shouldn't be, waiting"); |             _logger.LogTrace("Character is null but it shouldn't be, waiting"); | ||||||
|             await Task.Delay(50, token).ConfigureAwait(false); |             await Task.Delay(50, token).ConfigureAwait(false); | ||||||
| @@ -376,9 +376,9 @@ public class PlayerDataFactory | |||||||
|         // gather up data from ipc |         // gather up data from ipc | ||||||
|         previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations(); |         previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations(); | ||||||
|         previousData.HeelsOffset = _ipcManager.GetHeelsOffset(); |         previousData.HeelsOffset = _ipcManager.GetHeelsOffset(); | ||||||
|         Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(playerRelatedObject.Address); |         Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(playerRelatedObject.Address); | ||||||
|         Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScale(); |         Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScaleAsync(); | ||||||
|         Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPalette(); |         Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPaletteAsync(); | ||||||
|         previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false); |         previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false); | ||||||
|         _logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]); |         _logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]); | ||||||
|         previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false); |         previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false); | ||||||
| @@ -399,7 +399,7 @@ public class PlayerDataFactory | |||||||
|         var forwardPaths = forwardResolve.ToArray(); |         var forwardPaths = forwardResolve.ToArray(); | ||||||
|         var reversePaths = reverseResolve.ToArray(); |         var reversePaths = reverseResolve.ToArray(); | ||||||
|         Dictionary<string, List<string>> resolvedPaths = new(StringComparer.Ordinal); |         Dictionary<string, List<string>> resolvedPaths = new(StringComparer.Ordinal); | ||||||
|         var (forward, reverse) = await _ipcManager.PenumbraResolvePaths(forwardPaths, reversePaths).ConfigureAwait(false); |         var (forward, reverse) = await _ipcManager.PenumbraResolvePathsAsync(forwardPaths, reversePaths).ConfigureAwait(false); | ||||||
|         for (int i = 0; i < forwardPaths.Length; i++) |         for (int i = 0; i < forwardPaths.Length; i++) | ||||||
|         { |         { | ||||||
|             var filePath = forward[i].ToLowerInvariant(); |             var filePath = forward[i].ToLowerInvariant(); | ||||||
|   | |||||||
| @@ -28,7 +28,11 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase | |||||||
|         _performanceCollector = performanceCollector; |         _performanceCollector = performanceCollector; | ||||||
|         ObjectKind = objectKind; |         ObjectKind = objectKind; | ||||||
|         _dalamudUtil = dalamudUtil; |         _dalamudUtil = dalamudUtil; | ||||||
|         _getAddress = getAddress; |         _getAddress = () => | ||||||
|  |         { | ||||||
|  |             _dalamudUtil.EnsureIsOnFramework(); | ||||||
|  |             return getAddress.Invoke(); | ||||||
|  |         }; | ||||||
|         _isOwnedObject = watchedObject; |         _isOwnedObject = watchedObject; | ||||||
|         Name = string.Empty; |         Name = string.Empty; | ||||||
|  |  | ||||||
| @@ -82,29 +86,25 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase | |||||||
|         CheckAndUpdateObject(); |         CheckAndUpdateObject(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public IntPtr Address { get; set; } |     public IntPtr Address { get; private set; } | ||||||
|     public unsafe Character* Character => (Character*)Address; |  | ||||||
|     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]; | ||||||
|  |  | ||||||
|     private IntPtr DrawObjectAddress { get; set; } |     private IntPtr DrawObjectAddress { get; set; } | ||||||
|  |  | ||||||
|     private byte[] EquipSlotData { get; set; } = new byte[40]; |     private byte[] EquipSlotData { get; set; } = new byte[40]; | ||||||
|  |  | ||||||
|     public async Task<IntPtr> CurrentAddress() |     public IntPtr CurrentAddress() | ||||||
|     { |     { | ||||||
|         return await _dalamudUtil.RunOnFrameworkThread(_getAddress.Invoke).ConfigureAwait(true); |         _dalamudUtil.EnsureIsOnFramework(); | ||||||
|  |         return _getAddress.Invoke(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<Dalamud.Game.ClientState.Objects.Types.GameObject?> GetGameObject() |     public Dalamud.Game.ClientState.Objects.Types.GameObject? GetGameObject() | ||||||
|     { |     { | ||||||
|         return await _dalamudUtil.CreateGameObject(Address).ConfigureAwait(true); |         return _dalamudUtil.CreateGameObject(Address); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public bool IsBeingDrawn() |     private bool IsBeingDrawn() | ||||||
|     { |     { | ||||||
|         var curPtr = _getAddress(); |         var curPtr = _getAddress(); | ||||||
|         Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X")); |         Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X")); | ||||||
| @@ -123,7 +123,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase | |||||||
|         return IsBeingDrawn(drawObj, curPtr); |         return IsBeingDrawn(drawObj, curPtr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<bool> IsBeingDrawnRunOnFramework() |     public async Task<bool> IsBeingDrawnRunOnFrameworkAsync() | ||||||
|     { |     { | ||||||
|         return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false); |         return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
| @@ -142,6 +142,19 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase | |||||||
|             Mediator.Publish(new RemoveWatchedGameObjectHandler(this)); |             Mediator.Publish(new RemoveWatchedGameObjectHandler(this)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public async Task ActOnFrameworkAfterEnsureNoDrawAsync(Action act, CancellationToken token) | ||||||
|  |     { | ||||||
|  |         while (await _dalamudUtil.RunOnFrameworkThread(() => | ||||||
|  |                { | ||||||
|  |                    if (IsBeingDrawn()) return true; | ||||||
|  |                    act(); | ||||||
|  |                    return false; | ||||||
|  |                }).ConfigureAwait(false)) | ||||||
|  |         { | ||||||
|  |             await Task.Delay(250, token).ConfigureAwait(false); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private unsafe void CheckAndUpdateObject() |     private unsafe void CheckAndUpdateObject() | ||||||
|     { |     { | ||||||
|         if (_haltProcessing) return; |         if (_haltProcessing) return; | ||||||
| @@ -200,12 +213,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase | |||||||
|                 _clearCts?.Dispose(); |                 _clearCts?.Dispose(); | ||||||
|                 _clearCts = new(); |                 _clearCts = new(); | ||||||
|                 var token = _clearCts.Token; |                 var token = _clearCts.Token; | ||||||
|                 _ = Task.Run(() => ClearTask(token), token); |                 _ = Task.Run(() => ClearAsync(token), token); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private async Task ClearTask(CancellationToken token) |     private async Task ClearAsync(CancellationToken token) | ||||||
|     { |     { | ||||||
|         Logger.LogDebug("[{this}] Running Clear Task", this); |         Logger.LogDebug("[{this}] Running Clear Task", this); | ||||||
|         await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false); |         await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false); | ||||||
|   | |||||||
| @@ -14,8 +14,10 @@ using MareSynchronos.Utils; | |||||||
| using MareSynchronos.WebAPI.Files; | using MareSynchronos.WebAPI.Files; | ||||||
| using Microsoft.Extensions.Hosting; | using Microsoft.Extensions.Hosting; | ||||||
| using Microsoft.Extensions.Logging; | using Microsoft.Extensions.Logging; | ||||||
|  | using System; | ||||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
|  | using static System.Net.Mime.MediaTypeNames; | ||||||
| using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind; | using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind; | ||||||
|  |  | ||||||
| namespace MareSynchronos.PlayerData.Pairs; | namespace MareSynchronos.PlayerData.Pairs; | ||||||
| @@ -161,13 +163,13 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             if (_dalamudUtil is { IsZoning: false, IsInCutscene: false }) |             if (_dalamudUtil is { IsZoning: false, IsInCutscene: false }) | ||||||
|             { |             { | ||||||
|                 Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser); |                 Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser); | ||||||
|                 _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name).GetAwaiter().GetResult(); |                 _ipcManager.PenumbraRemoveTemporaryCollectionAsync(Logger, applicationId, name).GetAwaiter().GetResult(); | ||||||
|  |  | ||||||
|                 foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? new()) |                 foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? new()) | ||||||
|                 { |                 { | ||||||
|                     try |                     try | ||||||
|                     { |                     { | ||||||
|                         RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult(); |                         RevertCustomizationDataAsync(item.Key, name, applicationId).GetAwaiter().GetResult(); | ||||||
|                     } |                     } | ||||||
|                     catch (InvalidOperationException ex) |                     catch (InvalidOperationException ex) | ||||||
|                     { |                     { | ||||||
| @@ -201,18 +203,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     private async Task ApplyBaseData(Guid applicationId, Dictionary<string, string> moddedPaths, string manipulationData, CancellationToken token) |     private async Task ApplyCustomizationDataAsync(Guid applicationId, KeyValuePair<ObjectKind, HashSet<PlayerChanges>> changes, CharacterData charaData, CancellationToken token) | ||||||
|     { |  | ||||||
|         await _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, PlayerName!).ConfigureAwait(true); |  | ||||||
|         token.ThrowIfCancellationRequested(); |  | ||||||
|         var gameObj = await _charaHandler!.GetGameObject().ConfigureAwait(true); |  | ||||||
|         if (gameObj == null) return; |  | ||||||
|         var objTableIndex = await _dalamudUtil.RunOnFrameworkThread(() => gameObj.ObjectTableIndex()).ConfigureAwait(true); |  | ||||||
|         await _ipcManager.PenumbraSetTemporaryMods(Logger, applicationId, PlayerName!, objTableIndex, moddedPaths, manipulationData).ConfigureAwait(true); |  | ||||||
|         token.ThrowIfCancellationRequested(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private async Task ApplyCustomizationData(Guid applicationId, KeyValuePair<ObjectKind, HashSet<PlayerChanges>> changes, CharacterData charaData, CancellationToken token) |  | ||||||
|     { |     { | ||||||
|         if (PlayerCharacter == IntPtr.Zero) return; |         if (PlayerCharacter == IntPtr.Zero) return; | ||||||
|         var ptr = PlayerCharacter; |         var ptr = PlayerCharacter; | ||||||
| @@ -242,29 +233,29 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|                 switch (change) |                 switch (change) | ||||||
|                 { |                 { | ||||||
|                     case PlayerChanges.Palette: |                     case PlayerChanges.Palette: | ||||||
|                         await _ipcManager.PalettePlusSetPalette(handler.Address, charaData.PalettePlusData).ConfigureAwait(false); |                         await _ipcManager.PalettePlusSetPaletteAsync(handler.Address, charaData.PalettePlusData).ConfigureAwait(false); | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case PlayerChanges.Customize: |                     case PlayerChanges.Customize: | ||||||
|                         await _ipcManager.CustomizePlusSetBodyScale(handler.Address, charaData.CustomizePlusData).ConfigureAwait(false); |                         await _ipcManager.CustomizePlusSetBodyScaleAsync(handler.Address, charaData.CustomizePlusData).ConfigureAwait(false); | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case PlayerChanges.Heels: |                     case PlayerChanges.Heels: | ||||||
|                         await _ipcManager.HeelsSetOffsetForPlayer(handler.Address, charaData.HeelsOffset).ConfigureAwait(false); |                         await _ipcManager.HeelsSetOffsetForPlayerAsync(handler.Address, charaData.HeelsOffset).ConfigureAwait(false); | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case PlayerChanges.Honorific: |                     case PlayerChanges.Honorific: | ||||||
|                         await _ipcManager.HonorificSetTitle(handler.Address, charaData.HonorificData).ConfigureAwait(false); |                         await _ipcManager.HonorificSetTitleAsync(handler.Address, charaData.HonorificData).ConfigureAwait(false); | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case PlayerChanges.Mods: |                     case PlayerChanges.Mods: | ||||||
|                         if (charaData.GlamourerData.TryGetValue(changes.Key, out var glamourerData)) |                         if (charaData.GlamourerData.TryGetValue(changes.Key, out var glamourerData)) | ||||||
|                         { |                         { | ||||||
|                             await _ipcManager.GlamourerApplyAll(Logger, handler, glamourerData, applicationId, token).ConfigureAwait(false); |                             await _ipcManager.GlamourerApplyAllAsync(Logger, handler, glamourerData, applicationId, token).ConfigureAwait(false); | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
|                         { |                         { | ||||||
|                             await _ipcManager.PenumbraRedraw(Logger, handler, applicationId, token).ConfigureAwait(false); |                             await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false); | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                 } |                 } | ||||||
| @@ -452,26 +443,29 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|  |  | ||||||
|                     token.ThrowIfCancellationRequested(); |                     token.ThrowIfCancellationRequested(); | ||||||
|  |  | ||||||
|                     var applyBaseData = new Action(() => ApplyBaseData(_applicationId, moddedPaths, charaData.ManipulationData, token).ConfigureAwait(true).GetAwaiter().GetResult()); |  | ||||||
|  |  | ||||||
|                     if (updateModdedPaths && (moddedPaths.Any() || !string.IsNullOrEmpty(charaData.ManipulationData))) |                     if (updateModdedPaths && (moddedPaths.Any() || !string.IsNullOrEmpty(charaData.ManipulationData))) | ||||||
|                     { |                     { | ||||||
|                         while (!await _dalamudUtil.RunOnFrameworkThread(() => |                         await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => _ipcManager | ||||||
|  |                             .PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!) | ||||||
|  |                                 .ConfigureAwait(true).GetAwaiter().GetResult(), token); | ||||||
|  |                         token.ThrowIfCancellationRequested(); | ||||||
|  |  | ||||||
|  |                         await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => | ||||||
|                         { |                         { | ||||||
|                             if (_charaHandler!.IsBeingDrawn()) return false; |                             var gameObj = _charaHandler!.GetGameObject(); | ||||||
|                             applyBaseData(); |                             if (gameObj == null) return; | ||||||
|                             return true; |                             var objTableIndex = gameObj.ObjectTableIndex(); | ||||||
|                         }).ConfigureAwait(false)) |                             _ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData) | ||||||
|                         { |                                 .ConfigureAwait(true).GetAwaiter().GetResult(); | ||||||
|                             await Task.Delay(250, token).ConfigureAwait(false); |                         }, token); | ||||||
|                         } |                         token.ThrowIfCancellationRequested(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     token.ThrowIfCancellationRequested(); |                     token.ThrowIfCancellationRequested(); | ||||||
|  |  | ||||||
|                     foreach (var kind in updatedData) |                     foreach (var kind in updatedData) | ||||||
|                     { |                     { | ||||||
|                         await ApplyCustomizationData(_applicationId, kind, charaData, token).ConfigureAwait(false); |                         await ApplyCustomizationDataAsync(_applicationId, kind, charaData, token).ConfigureAwait(false); | ||||||
|                         token.ThrowIfCancellationRequested(); |                         token.ThrowIfCancellationRequested(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -506,7 +500,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             { |             { | ||||||
|                 Task.Run(async () => |                 Task.Run(async () => | ||||||
|                 { |                 { | ||||||
|                     _lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false); |                     _lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false); | ||||||
|                     ApplyCharacterData(_cachedData, true); |                     ApplyCharacterData(_cachedData, true); | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
| @@ -527,7 +521,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|         PlayerName = name; |         PlayerName = name; | ||||||
|         _charaHandler = _gameObjectHandlerFactory.Create(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false).GetAwaiter().GetResult(); |         _charaHandler = _gameObjectHandlerFactory.Create(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false).GetAwaiter().GetResult(); | ||||||
|  |  | ||||||
|         _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); |         _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); | ||||||
|         _lastGlamourerData = _originalGlamourerData; |         _lastGlamourerData = _originalGlamourerData; | ||||||
|         Mediator.Subscribe<PenumbraRedrawMessage>(this, IpcManagerOnPenumbraRedrawEvent); |         Mediator.Subscribe<PenumbraRedrawMessage>(this, IpcManagerOnPenumbraRedrawEvent); | ||||||
|         Mediator.Subscribe<CharacterChangedMessage>(this, async (msg) => |         Mediator.Subscribe<CharacterChangedMessage>(this, async (msg) => | ||||||
| @@ -535,7 +529,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             if (msg.GameObjectHandler == _charaHandler && (_applicationTask?.IsCompleted ?? true)) |             if (msg.GameObjectHandler == _charaHandler && (_applicationTask?.IsCompleted ?? true)) | ||||||
|             { |             { | ||||||
|                 Logger.LogTrace("Saving new Glamourer Data for {this}", this); |                 Logger.LogTrace("Saving new Glamourer Data for {this}", this); | ||||||
|                 _lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false); |                 _lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -557,7 +551,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             Logger.LogDebug("Unauthorized character change detected"); |             Logger.LogDebug("Unauthorized character change detected"); | ||||||
|             if (_cachedData != null) |             if (_cachedData != null) | ||||||
|             { |             { | ||||||
|                 await ApplyCustomizationData(applicationId, new(ObjectKind.Player, |                 await ApplyCustomizationDataAsync(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 })), | ||||||
|                     _cachedData, token).ConfigureAwait(false); |                     _cachedData, token).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
| @@ -598,7 +592,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private async Task RevertCustomizationData(ObjectKind objectKind, string name, Guid applicationId) |     private async Task RevertCustomizationDataAsync(ObjectKind objectKind, string name, Guid applicationId) | ||||||
|     { |     { | ||||||
|         nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident); |         nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident); | ||||||
|         if (address == IntPtr.Zero) return; |         if (address == IntPtr.Zero) return; | ||||||
| @@ -613,19 +607,19 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => address, false).ConfigureAwait(false); |             using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => address, false).ConfigureAwait(false); | ||||||
|             CheckForNameAndThrow(tempHandler, name); |             CheckForNameAndThrow(tempHandler, name); | ||||||
|             Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData); |             Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData); | ||||||
|             await _ipcManager.GlamourerApplyCustomizationAndEquipment(Logger, tempHandler, _originalGlamourerData, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); |             await _ipcManager.GlamourerApplyCustomizationAndEquipmentAsync(Logger, tempHandler, _originalGlamourerData, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); | ||||||
|             CheckForNameAndThrow(tempHandler, name); |             CheckForNameAndThrow(tempHandler, name); | ||||||
|             Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); |             Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); | ||||||
|             await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false); |             await _ipcManager.HeelsRestoreOffsetForPlayerAsync(address).ConfigureAwait(false); | ||||||
|             CheckForNameAndThrow(tempHandler, name); |             CheckForNameAndThrow(tempHandler, name); | ||||||
|             Logger.LogDebug("[{applicationId}] Restoring C+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); |             Logger.LogDebug("[{applicationId}] Restoring C+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); | ||||||
|             await _ipcManager.CustomizePlusRevert(address).ConfigureAwait(false); |             await _ipcManager.CustomizePlusRevertAsync(address).ConfigureAwait(false); | ||||||
|             CheckForNameAndThrow(tempHandler, name); |             CheckForNameAndThrow(tempHandler, name); | ||||||
|             Logger.LogDebug("[{applicationId}] Restoring Palette+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); |             Logger.LogDebug("[{applicationId}] Restoring Palette+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); | ||||||
|             await _ipcManager.PalettePlusRemovePalette(address).ConfigureAwait(false); |             await _ipcManager.PalettePlusRemovePaletteAsync(address).ConfigureAwait(false); | ||||||
|             CheckForNameAndThrow(tempHandler, name); |             CheckForNameAndThrow(tempHandler, name); | ||||||
|             Logger.LogDebug("[{applicationId}] Restoring Honorific for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); |             Logger.LogDebug("[{applicationId}] Restoring Honorific for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); | ||||||
|             await _ipcManager.HonorificClearTitle(address).ConfigureAwait(false); |             await _ipcManager.HonorificClearTitleAsync(address).ConfigureAwait(false); | ||||||
|         } |         } | ||||||
|         else if (objectKind == ObjectKind.MinionOrMount) |         else if (objectKind == ObjectKind.MinionOrMount) | ||||||
|         { |         { | ||||||
| @@ -633,7 +627,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             if (minionOrMount != IntPtr.Zero) |             if (minionOrMount != IntPtr.Zero) | ||||||
|             { |             { | ||||||
|                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, false).ConfigureAwait(false); |                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, false).ConfigureAwait(false); | ||||||
|                 await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); |                 await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else if (objectKind == ObjectKind.Pet) |         else if (objectKind == ObjectKind.Pet) | ||||||
| @@ -642,7 +636,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             if (pet != IntPtr.Zero) |             if (pet != IntPtr.Zero) | ||||||
|             { |             { | ||||||
|                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, false).ConfigureAwait(false); |                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, false).ConfigureAwait(false); | ||||||
|                 await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); |                 await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else if (objectKind == ObjectKind.Companion) |         else if (objectKind == ObjectKind.Companion) | ||||||
| @@ -651,7 +645,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase | |||||||
|             if (companion != IntPtr.Zero) |             if (companion != IntPtr.Zero) | ||||||
|             { |             { | ||||||
|                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, false).ConfigureAwait(false); |                 using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, false).ConfigureAwait(false); | ||||||
|                 await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); |                 await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -76,11 +76,22 @@ public class DalamudUtilService : IHostedService | |||||||
|         return obj != null && obj.IsValid(); |         return obj != null && obj.IsValid(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<Dalamud.Game.ClientState.Objects.Types.GameObject?> CreateGameObject(IntPtr reference) |     public async Task<Dalamud.Game.ClientState.Objects.Types.GameObject?> CreateGameObjectAsync(IntPtr reference) | ||||||
|     { |     { | ||||||
|         return await RunOnFrameworkThread(() => _objectTable.CreateObjectReference(reference)).ConfigureAwait(false); |         return await RunOnFrameworkThread(() => _objectTable.CreateObjectReference(reference)).ConfigureAwait(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public void EnsureIsOnFramework() | ||||||
|  |     { | ||||||
|  |         if (!_framework.IsInFrameworkUpdateThread) throw new InvalidOperationException("Can only be run on Framework"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Dalamud.Game.ClientState.Objects.Types.GameObject? CreateGameObject(IntPtr reference) | ||||||
|  |     { | ||||||
|  |         EnsureIsOnFramework(); | ||||||
|  |         return _objectTable.CreateObjectReference(reference); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public Dalamud.Game.ClientState.Objects.Types.Character? GetCharacterFromObjectTableByIndex(int index) |     public Dalamud.Game.ClientState.Objects.Types.Character? GetCharacterFromObjectTableByIndex(int index) | ||||||
|     { |     { | ||||||
|         var objTableObj = _objectTable[index]; |         var objTableObj = _objectTable[index]; | ||||||
| @@ -176,7 +187,7 @@ public class DalamudUtilService : IHostedService | |||||||
|         { |         { | ||||||
|             while ((!ct?.IsCancellationRequested ?? true) |             while ((!ct?.IsCancellationRequested ?? true) | ||||||
|                    && curWaitTime < timeOut |                    && curWaitTime < timeOut | ||||||
|                    && await handler.IsBeingDrawnRunOnFramework().ConfigureAwait(false)) // 0b100000000000 is "still rendering" or something |                    && await handler.IsBeingDrawnRunOnFrameworkAsync().ConfigureAwait(false)) // 0b100000000000 is "still rendering" or something | ||||||
|             { |             { | ||||||
|                 logger.LogTrace("[{redrawId}] Waiting for {handler} to finish drawing", redrawId, handler); |                 logger.LogTrace("[{redrawId}] Waiting for {handler} to finish drawing", redrawId, handler); | ||||||
|                 curWaitTime += tick; |                 curWaitTime += tick; | ||||||
|   | |||||||
| @@ -139,7 +139,7 @@ public class DownloadUi : WindowMediatorSubscriberBase | |||||||
|  |  | ||||||
|             foreach (var transfer in _currentDownloads.ToList()) |             foreach (var transfer in _currentDownloads.ToList()) | ||||||
|             { |             { | ||||||
|                 var screenPos = _dalamudUtilService.WorldToScreen(transfer.Key.GetGameObject().ConfigureAwait(true).GetAwaiter().GetResult()); |                 var screenPos = _dalamudUtilService.WorldToScreen(transfer.Key.GetGameObject()); | ||||||
|                 if (screenPos == Vector2.Zero) continue; |                 if (screenPos == Vector2.Zero) continue; | ||||||
|  |  | ||||||
|                 var totalBytes = transfer.Value.Sum(c => c.Value.TotalBytes); |                 var totalBytes = transfer.Value.Sum(c => c.Value.TotalBytes); | ||||||
| @@ -182,7 +182,7 @@ public class DownloadUi : WindowMediatorSubscriberBase | |||||||
|             { |             { | ||||||
|                 foreach (var player in _uploadingPlayers.Select(p => p.Key).ToList()) |                 foreach (var player in _uploadingPlayers.Select(p => p.Key).ToList()) | ||||||
|                 { |                 { | ||||||
|                     var screenPos = _dalamudUtilService.WorldToScreen(player.GetGameObject().GetAwaiter().GetResult()); |                     var screenPos = _dalamudUtilService.WorldToScreen(player.GetGameObject()); | ||||||
|                     if (screenPos == Vector2.Zero) continue; |                     if (screenPos == Vector2.Zero) continue; | ||||||
|  |  | ||||||
|                     try |                     try | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stanley Dimant
					Stanley Dimant