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() 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())
{ {

View File

@@ -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,35 +650,22 @@ 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
{ {

View File

@@ -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);
} }
} }

View File

@@ -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();

View File

@@ -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);

View File

@@ -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)
{ {
@@ -200,19 +202,8 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
throw new InvalidOperationException("Player pointer is zero, pointer invalid"); throw new InvalidOperationException("Player pointer is zero, pointer invalid");
} }
} }
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);
} }
} }
} }

View File

@@ -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;

View File

@@ -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