some cleanup and sanitizing

This commit is contained in:
Stanley Dimant
2023-05-02 11:27:29 +02:00
parent 3086d82b40
commit f8993916bd
8 changed files with 140 additions and 135 deletions

View File

@@ -169,7 +169,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
private void DalamudUtil_FrameworkUpdate()
{
_cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress().GetAwaiter().GetResult()).ToHashSet();
_cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress()).ToHashSet();
_cachedHandledPaths.Clear();
foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList())
{

View File

@@ -24,7 +24,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter;
private readonly DalamudUtilService _dalamudUtil;
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>? _glamourerApplyOnlyCustomization;
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment;
@@ -167,10 +167,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public bool CheckPenumbraApi() => _penumbraAvailable;
public async Task CustomizePlusRevert(IntPtr character)
public async Task CustomizePlusRevertAsync(IntPtr character)
{
if (!CheckCustomizePlusApi()) return;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj is Character c)
{
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;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj is Character c)
{
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;
var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.PlayerName)).ConfigureAwait(false);
@@ -204,61 +204,61 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
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;
try
{
await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false);
await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false);
if (gameObj is Character c)
{
await PenumbraRedrawAsync(logger, handler, applicationId, () =>
{
logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId);
_glamourerApplyAll!.InvokeAction(customization, c);
}, fireAndForget).ConfigureAwait(false);
}).ConfigureAwait(false);
}
}
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;
try
{
await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false);
await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false);
if (gameObj is Character c)
{
await PenumbraRedrawAsync(logger, handler, applicationid, () =>
{
logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyCustomization", applicationid);
_glamourerApplyOnlyCustomization!.InvokeAction(customization, c);
}, fireAndForget).ConfigureAwait(false);
}).ConfigureAwait(false);
await PenumbraRedrawAsync(logger, handler, applicationid, () =>
{
logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyOnlyEquipment", applicationid);
_glamourerApplyOnlyEquipment!.InvokeAction(equipment, c);
}, fireAndForget).ConfigureAwait(false);
}).ConfigureAwait(false);
}
}
finally
{
_glamourerApplicationSemaphore.Release();
_redrawSemaphore.Release();
}
}
public async Task<string> GlamourerGetCharacterCustomization(IntPtr character)
public async Task<string> GlamourerGetCharacterCustomizationAsync(IntPtr character)
{
if (!CheckGlamourerApi()) return string.Empty;
try
{
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj is Character c)
{
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;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj != null)
{
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;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj != null)
{
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;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj is PlayerCharacter c)
{
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}";
}
public async Task HonorificSetTitle(IntPtr character, string honorificData)
public async Task HonorificSetTitleAsync(IntPtr character, string honorificData)
{
if (!CheckHonorificApi()) return;
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)
{
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;
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));
}
public async Task PalettePlusRemovePalette(IntPtr character)
public async Task PalettePlusRemovePaletteAsync(IntPtr character)
{
if (!CheckPalettePlusApi()) return;
var gameObj = await _dalamudUtil.CreateGameObject(character).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(character).ConfigureAwait(false);
if (gameObj is Character c)
{
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;
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)
{
await _dalamudUtil.RunOnFrameworkThread(() =>
@@ -385,29 +385,29 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
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;
try
{
await _glamourerApplicationSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObject(handler.Address).ConfigureAwait(false);
await _redrawSemaphore.WaitAsync(token).ConfigureAwait(false);
var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false);
if (gameObj is Character c)
{
await PenumbraRedrawAsync(logger, handler, applicationId, () =>
{
logger.LogDebug("[{appid}] Calling on IPC: PenumbraRedraw", applicationId);
_penumbraRedrawObject!.Invoke(c, RedrawType.Redraw);
}, fireAndForget).ConfigureAwait(false);
}).ConfigureAwait(false);
}
}
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;
await _dalamudUtil.RunOnFrameworkThread(() =>
@@ -421,12 +421,12 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
}).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);
}
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;
@@ -650,36 +650,23 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
_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));
_penumbraRedrawRequests[obj.Address] = !fireAndForget;
_penumbraRedrawRequests[obj.Address] = true;
try
{
if (!fireAndForget)
{
while (!await _dalamudUtil.RunOnFrameworkThread(() =>
{
if (obj.IsBeingDrawn()) return false;
action();
return true;
}).ConfigureAwait(false))
{
await Task.Delay(250).ConfigureAwait(false);
}
CancellationTokenSource cancelToken = new CancellationTokenSource();
cancelToken.CancelAfter(TimeSpan.FromSeconds(15));
await obj.ActOnFrameworkAfterEnsureNoDrawAsync(action, cancelToken.Token);
await Task.Delay(TimeSpan.FromSeconds(1), _disposalCts.Token).ConfigureAwait(false);
if (!_disposalCts.Token.IsCancellationRequested)
await _dalamudUtil.WaitWhileCharacterIsDrawing(logger, obj, applicationId, 30000, _disposalCts.Token).ConfigureAwait(false);
}
else
{
_ = _dalamudUtil.RunOnFrameworkThread(action);
}
}
finally
{
_penumbraRedrawRequests[obj.Address] = false;

View File

@@ -65,14 +65,14 @@ public class MareCharaFileManager
}
var applicationId = Guid.NewGuid();
_ipcManager.ToggleGposeQueueMode(on: true);
await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
await _ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(),
await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
await _ipcManager.PenumbraSetTemporaryModsAsync(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(),
extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal),
LoadedCharaFile.CharaFileData.ManipulationData).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);
await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
_ipcManager.ToggleGposeQueueMode(on: false);
}
}

View File

@@ -316,7 +316,7 @@ public class PlayerDataFactory
// wait until chara is not drawing and present so nothing spontaneously explodes
await _dalamudUtil.WaitWhileCharacterIsDrawing(_logger, playerRelatedObject, Guid.NewGuid(), 30000, ct: token).ConfigureAwait(false);
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");
await Task.Delay(50, token).ConfigureAwait(false);
@@ -376,9 +376,9 @@ public class PlayerDataFactory
// gather up data from ipc
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
previousData.HeelsOffset = _ipcManager.GetHeelsOffset();
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(playerRelatedObject.Address);
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScale();
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPalette();
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(playerRelatedObject.Address);
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScaleAsync();
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPaletteAsync();
previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false);
_logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]);
previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false);
@@ -399,7 +399,7 @@ public class PlayerDataFactory
var forwardPaths = forwardResolve.ToArray();
var reversePaths = reverseResolve.ToArray();
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++)
{
var filePath = forward[i].ToLowerInvariant();

View File

@@ -28,7 +28,11 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
_performanceCollector = performanceCollector;
ObjectKind = objectKind;
_dalamudUtil = dalamudUtil;
_getAddress = getAddress;
_getAddress = () =>
{
_dalamudUtil.EnsureIsOnFramework();
return getAddress.Invoke();
};
_isOwnedObject = watchedObject;
Name = string.Empty;
@@ -82,29 +86,25 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
CheckAndUpdateObject();
}
public IntPtr Address { get; set; }
public unsafe Character* Character => (Character*)Address;
public IntPtr Address { get; private set; }
public string Name { get; private set; }
public ObjectKind ObjectKind { get; }
private byte[] CustomizeData { get; set; } = new byte[26];
private IntPtr DrawObjectAddress { get; set; }
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();
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X"));
@@ -123,7 +123,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
return IsBeingDrawn(drawObj, curPtr);
}
public async Task<bool> IsBeingDrawnRunOnFramework()
public async Task<bool> IsBeingDrawnRunOnFrameworkAsync()
{
return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false);
}
@@ -142,6 +142,19 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
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()
{
if (_haltProcessing) return;
@@ -200,12 +213,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
_clearCts?.Dispose();
_clearCts = new();
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);
await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);

View File

@@ -14,8 +14,10 @@ using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Files;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using static System.Net.Mime.MediaTypeNames;
using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind;
namespace MareSynchronos.PlayerData.Pairs;
@@ -161,13 +163,13 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
{
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())
{
try
{
RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult();
RevertCustomizationDataAsync(item.Key, name, applicationId).GetAwaiter().GetResult();
}
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)
{
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)
private async Task ApplyCustomizationDataAsync(Guid applicationId, KeyValuePair<ObjectKind, HashSet<PlayerChanges>> changes, CharacterData charaData, CancellationToken token)
{
if (PlayerCharacter == IntPtr.Zero) return;
var ptr = PlayerCharacter;
@@ -242,29 +233,29 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
switch (change)
{
case PlayerChanges.Palette:
await _ipcManager.PalettePlusSetPalette(handler.Address, charaData.PalettePlusData).ConfigureAwait(false);
await _ipcManager.PalettePlusSetPaletteAsync(handler.Address, charaData.PalettePlusData).ConfigureAwait(false);
break;
case PlayerChanges.Customize:
await _ipcManager.CustomizePlusSetBodyScale(handler.Address, charaData.CustomizePlusData).ConfigureAwait(false);
await _ipcManager.CustomizePlusSetBodyScaleAsync(handler.Address, charaData.CustomizePlusData).ConfigureAwait(false);
break;
case PlayerChanges.Heels:
await _ipcManager.HeelsSetOffsetForPlayer(handler.Address, charaData.HeelsOffset).ConfigureAwait(false);
await _ipcManager.HeelsSetOffsetForPlayerAsync(handler.Address, charaData.HeelsOffset).ConfigureAwait(false);
break;
case PlayerChanges.Honorific:
await _ipcManager.HonorificSetTitle(handler.Address, charaData.HonorificData).ConfigureAwait(false);
await _ipcManager.HonorificSetTitleAsync(handler.Address, charaData.HonorificData).ConfigureAwait(false);
break;
case PlayerChanges.Mods:
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
{
await _ipcManager.PenumbraRedraw(Logger, handler, applicationId, token).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false);
}
break;
}
@@ -452,26 +443,29 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
token.ThrowIfCancellationRequested();
var applyBaseData = new Action(() => ApplyBaseData(_applicationId, moddedPaths, charaData.ManipulationData, token).ConfigureAwait(true).GetAwaiter().GetResult());
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;
applyBaseData();
return true;
}).ConfigureAwait(false))
{
await Task.Delay(250, token).ConfigureAwait(false);
}
var gameObj = _charaHandler!.GetGameObject();
if (gameObj == null) return;
var objTableIndex = gameObj.ObjectTableIndex();
_ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData)
.ConfigureAwait(true).GetAwaiter().GetResult();
}, token);
token.ThrowIfCancellationRequested();
}
token.ThrowIfCancellationRequested();
foreach (var kind in updatedData)
{
await ApplyCustomizationData(_applicationId, kind, charaData, token).ConfigureAwait(false);
await ApplyCustomizationDataAsync(_applicationId, kind, charaData, token).ConfigureAwait(false);
token.ThrowIfCancellationRequested();
}
@@ -506,7 +500,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
{
Task.Run(async () =>
{
_lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false);
_lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false);
ApplyCharacterData(_cachedData, true);
});
}
@@ -527,7 +521,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
PlayerName = name;
_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;
Mediator.Subscribe<PenumbraRedrawMessage>(this, IpcManagerOnPenumbraRedrawEvent);
Mediator.Subscribe<CharacterChangedMessage>(this, async (msg) =>
@@ -535,7 +529,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (msg.GameObjectHandler == _charaHandler && (_applicationTask?.IsCompleted ?? true))
{
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");
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 })),
_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);
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);
CheckForNameAndThrow(tempHandler, name);
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);
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);
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);
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);
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)
{
@@ -633,7 +627,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (minionOrMount != IntPtr.Zero)
{
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)
@@ -642,7 +636,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (pet != IntPtr.Zero)
{
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)
@@ -651,7 +645,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (companion != IntPtr.Zero)
{
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);
}
}
}

View File

@@ -76,11 +76,22 @@ public class DalamudUtilService : IHostedService
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);
}
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)
{
var objTableObj = _objectTable[index];
@@ -176,7 +187,7 @@ public class DalamudUtilService : IHostedService
{
while ((!ct?.IsCancellationRequested ?? true)
&& 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);
curWaitTime += tick;

View File

@@ -139,7 +139,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
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;
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())
{
var screenPos = _dalamudUtilService.WorldToScreen(player.GetGameObject().GetAwaiter().GetResult());
var screenPos = _dalamudUtilService.WorldToScreen(player.GetGameObject());
if (screenPos == Vector2.Zero) continue;
try