diff --git a/MareSynchronos/FileCache/TransientResourceManager.cs b/MareSynchronos/FileCache/TransientResourceManager.cs index 733755f..ffb6987 100644 --- a/MareSynchronos/FileCache/TransientResourceManager.cs +++ b/MareSynchronos/FileCache/TransientResourceManager.cs @@ -24,6 +24,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase _configurationService = configurationService; _dalamudUtil = dalamudUtil; + PlayerPersistentDataKey = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult() + "_" + _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(); + SemiTransientResources.TryAdd(ObjectKind.Player, new HashSet(StringComparer.Ordinal)); if (_configurationService.Current.PlayerPersistentTransientCache.TryGetValue(PlayerPersistentDataKey, out var gamePaths)) { @@ -60,7 +62,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase }); } - private string PlayerPersistentDataKey => _dalamudUtil.PlayerName + "_" + _dalamudUtil.WorldId; + private string PlayerPersistentDataKey { get; } private ConcurrentDictionary> SemiTransientResources { get; } = new(); private ConcurrentDictionary> TransientResources { get; } = new(); @@ -185,7 +187,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase Logger.LogDebug("Penumbra Mod Settings changed, verifying SemiTransientResources"); foreach (var item in SemiTransientResources) { - Mediator.Publish(new TransientResourceChangedMessage(_dalamudUtil.PlayerPointer)); + Mediator.Publish(new TransientResourceChangedMessage(_dalamudUtil.GetPlayerPointer())); } }); } diff --git a/MareSynchronos/Interop/IpcManager.cs b/MareSynchronos/Interop/IpcManager.cs index 04fffea..ffbea7b 100644 --- a/MareSynchronos/Interop/IpcManager.cs +++ b/MareSynchronos/Interop/IpcManager.cs @@ -24,7 +24,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase private readonly ICallGateSubscriber _customizePlusSetBodyScaleToCharacter; private readonly DalamudUtilService _dalamudUtil; private readonly ICallGateSubscriber _glamourerApiVersion; - private readonly SemaphoreSlim _redrawSemaphore = new(2); private readonly ICallGateSubscriber? _glamourerApplyAll; private readonly ICallGateSubscriber? _glamourerApplyOnlyCustomization; private readonly ICallGateSubscriber? _glamourerApplyOnlyEquipment; @@ -64,6 +63,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase private readonly FuncSubscriber _penumbraRemoveTemporaryMod; private readonly FuncSubscriber _penumbraResolveModDir; private readonly FuncSubscriber _penumbraResolvePaths; + private readonly SemaphoreSlim _redrawSemaphore = new(2); private bool _customizePlusAvailable = false; private CancellationTokenSource _disposalCts = new(); private bool _glamourerAvailable = false; @@ -193,7 +193,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase public async Task GetCustomizePlusScaleAsync() { if (!CheckCustomizePlusApi()) return string.Empty; - var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.PlayerName)).ConfigureAwait(false); + var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.GetPlayerName())).ConfigureAwait(false); if (string.IsNullOrEmpty(scale)) return string.Empty; return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale)); } @@ -340,7 +340,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase public async Task PalettePlusBuildPaletteAsync() { if (!CheckPalettePlusApi()) return string.Empty; - var palette = await _dalamudUtil.RunOnFrameworkThread(() => _palettePlusBuildCharaPalette.InvokeFunc(_dalamudUtil.PlayerCharacter)).ConfigureAwait(false); + var palette = await _dalamudUtil.RunOnFrameworkThread(() => _palettePlusBuildCharaPalette.InvokeFunc(_dalamudUtil.GetPlayerCharacter())).ConfigureAwait(false); if (string.IsNullOrEmpty(palette)) return string.Empty; return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette)); } diff --git a/MareSynchronos/MarePlugin.cs b/MareSynchronos/MarePlugin.cs index fee157e..f956f2f 100644 --- a/MareSynchronos/MarePlugin.cs +++ b/MareSynchronos/MarePlugin.cs @@ -124,7 +124,7 @@ public class MarePlugin : MediatorSubscriberBase, IHostedService private async Task WaitForPlayerAndLaunchCharacterManager() { - while (!_dalamudUtil.IsPlayerPresent) + while (!await _dalamudUtil.GetIsPlayerPresentAsync().ConfigureAwait(false)) { await Task.Delay(100).ConfigureAwait(false); } diff --git a/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs b/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs index cf5d0cb..35104d1 100644 --- a/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs +++ b/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs @@ -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.CreateGameObjectAsync(charaPointer).GetAwaiter().GetResult()).ConfigureAwait(false)) && totalWaitTime > 0) + while (!await _dalamudUtil.IsObjectPresentAsync(await _dalamudUtil.CreateGameObjectAsync(charaPointer).ConfigureAwait(false)).ConfigureAwait(false) && totalWaitTime > 0) { _logger.LogTrace("Character is null but it shouldn't be, waiting"); await Task.Delay(50, token).ConfigureAwait(false); diff --git a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs index 108c33b..2392e09 100644 --- a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs +++ b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs @@ -83,7 +83,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase } }); - CheckAndUpdateObject(); + _dalamudUtil.RunOnFrameworkThread(CheckAndUpdateObject).GetAwaiter().GetResult(); } public IntPtr Address { get; private set; } @@ -93,6 +93,19 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase private IntPtr DrawObjectAddress { get; set; } private byte[] EquipSlotData { get; set; } = new byte[40]; + 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); + } + } + public IntPtr CurrentAddress() { _dalamudUtil.EnsureIsOnFramework(); @@ -104,25 +117,6 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase return _dalamudUtil.CreateGameObject(Address); } - private bool IsBeingDrawn() - { - var curPtr = _getAddress(); - Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X")); - - if (curPtr == IntPtr.Zero) - { - Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr is ZERO, returning", this); - - Address = IntPtr.Zero; - DrawObjectAddress = IntPtr.Zero; - return false; - } - - var drawObj = GetDrawObj(curPtr); - Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, DrawObjPtr: {ptr}", this, drawObj.ToString("X")); - return IsBeingDrawn(drawObj, curPtr); - } - public async Task IsBeingDrawnRunOnFrameworkAsync() { return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false); @@ -142,19 +136,6 @@ 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; @@ -281,6 +262,25 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase return (IntPtr)((GameObject*)curPtr)->DrawObject; } + private bool IsBeingDrawn() + { + var curPtr = _getAddress(); + Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X")); + + if (curPtr == IntPtr.Zero) + { + Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr is ZERO, returning", this); + + Address = IntPtr.Zero; + DrawObjectAddress = IntPtr.Zero; + return false; + } + + var drawObj = GetDrawObj(curPtr); + Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, DrawObjPtr: {ptr}", this, drawObj.ToString("X")); + return IsBeingDrawn(drawObj, curPtr); + } + private unsafe bool IsBeingDrawn(IntPtr drawObj, IntPtr curPtr) { Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Checking IsBeingDrawn for Ptr {curPtr} : DrawObj {drawObj}", this, curPtr.ToString("X"), drawObj.ToString("X")); diff --git a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs index 3de3695..bc69d14 100644 --- a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs +++ b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs @@ -202,7 +202,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase throw new InvalidOperationException("Player pointer is zero, pointer invalid"); } } - + private async Task ApplyCustomizationDataAsync(Guid applicationId, KeyValuePair> changes, CharacterData charaData, CancellationToken token) { if (PlayerCharacter == IntPtr.Zero) return; @@ -211,9 +211,9 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase var handler = changes.Key switch { ObjectKind.Player => _charaHandler!, - ObjectKind.Companion => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false), - ObjectKind.MinionOrMount => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetMinionOrMount(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false), - ObjectKind.Pet => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false), + ObjectKind.Companion => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(ptr), false).ConfigureAwait(false), + ObjectKind.MinionOrMount => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetMinionOrMount(ptr), false).ConfigureAwait(false), + ObjectKind.Pet => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(ptr), false).ConfigureAwait(false), _ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key) }; @@ -447,7 +447,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase { await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => _ipcManager .PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!) - .ConfigureAwait(true).GetAwaiter().GetResult(), token); + .ConfigureAwait(true).GetAwaiter().GetResult(), token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => @@ -457,7 +457,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase var objTableIndex = gameObj.ObjectTableIndex(); _ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData) .ConfigureAwait(true).GetAwaiter().GetResult(); - }, token); + }, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); } @@ -519,7 +519,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase private void Initialize(string name) { PlayerName = name; - _charaHandler = _gameObjectHandlerFactory.Create(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false).GetAwaiter().GetResult(); + _charaHandler = _gameObjectHandlerFactory.Create(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromCachedTableByIdent(OnlineUser.Ident), false).GetAwaiter().GetResult(); _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); _lastGlamourerData = _originalGlamourerData; @@ -594,7 +594,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase private async Task RevertCustomizationDataAsync(ObjectKind objectKind, string name, Guid applicationId) { - nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident); + nint address = _dalamudUtil.GetPlayerCharacterFromCachedTableByIdent(OnlineUser.Ident); if (address == IntPtr.Zero) return; var cancelToken = new CancellationTokenSource(); @@ -623,7 +623,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase } else if (objectKind == ObjectKind.MinionOrMount) { - var minionOrMount = await _dalamudUtil.GetMinionOrMount(address).ConfigureAwait(false); + var minionOrMount = await _dalamudUtil.GetMinionOrMountAsync(address).ConfigureAwait(false); if (minionOrMount != IntPtr.Zero) { using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, false).ConfigureAwait(false); @@ -632,7 +632,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase } else if (objectKind == ObjectKind.Pet) { - var pet = await _dalamudUtil.GetPet(address).ConfigureAwait(false); + var pet = await _dalamudUtil.GetPetAsync(address).ConfigureAwait(false); if (pet != IntPtr.Zero) { using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, false).ConfigureAwait(false); @@ -641,7 +641,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase } else if (objectKind == ObjectKind.Companion) { - var companion = await _dalamudUtil.GetCompanion(address).ConfigureAwait(false); + var companion = await _dalamudUtil.GetCompanionAsync(address).ConfigureAwait(false); if (companion != IntPtr.Zero) { using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, false).ConfigureAwait(false); diff --git a/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs b/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs index 81e9ea8..95888b5 100644 --- a/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs +++ b/MareSynchronos/PlayerData/Pairs/OnlinePlayerManager.cs @@ -45,7 +45,7 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase private void FrameworkOnUpdate() { - if (!_dalamudUtil.IsPlayerPresent || !_apiController.IsConnected) return; + if (!_dalamudUtil.GetIsPlayerPresent() || !_apiController.IsConnected) return; if (!_newVisiblePlayers.Any()) return; var newVisiblePlayers = _newVisiblePlayers.ToList(); diff --git a/MareSynchronos/PlayerData/Services/CacheCreationService.cs b/MareSynchronos/PlayerData/Services/CacheCreationService.cs index fa9cd79..9a5904d 100644 --- a/MareSynchronos/PlayerData/Services/CacheCreationService.cs +++ b/MareSynchronos/PlayerData/Services/CacheCreationService.cs @@ -76,13 +76,13 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase await AddPlayerCacheToCreate().ConfigureAwait(false); }); - _playerRelatedObjects[ObjectKind.Player] = gameObjectHandlerFactory.Create(ObjectKind.Player, () => dalamudUtil.PlayerPointer, true) + _playerRelatedObjects[ObjectKind.Player] = gameObjectHandlerFactory.Create(ObjectKind.Player, () => dalamudUtil.GetPlayerPointer(), true) .GetAwaiter().GetResult(); - _playerRelatedObjects[ObjectKind.MinionOrMount] = gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount().GetAwaiter().GetResult(), true) + _playerRelatedObjects[ObjectKind.MinionOrMount] = gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount(), true) .GetAwaiter().GetResult(); - _playerRelatedObjects[ObjectKind.Pet] = gameObjectHandlerFactory.Create(ObjectKind.Pet, () => dalamudUtil.GetPet().GetAwaiter().GetResult(), true) + _playerRelatedObjects[ObjectKind.Pet] = gameObjectHandlerFactory.Create(ObjectKind.Pet, () => dalamudUtil.GetPet(), true) .GetAwaiter().GetResult(); - _playerRelatedObjects[ObjectKind.Companion] = gameObjectHandlerFactory.Create(ObjectKind.Companion, () => dalamudUtil.GetCompanion().GetAwaiter().GetResult(), true) + _playerRelatedObjects[ObjectKind.Companion] = gameObjectHandlerFactory.Create(ObjectKind.Companion, () => dalamudUtil.GetCompanion(), true) .GetAwaiter().GetResult(); } diff --git a/MareSynchronos/Services/DalamudUtilService.cs b/MareSynchronos/Services/DalamudUtilService.cs index 4cb1080..ac28bd8 100644 --- a/MareSynchronos/Services/DalamudUtilService.cs +++ b/MareSynchronos/Services/DalamudUtilService.cs @@ -54,26 +54,16 @@ public class DalamudUtilService : IHostedService public unsafe GameObject* GposeTarget => TargetSystem.Instance()->GPoseTarget; public unsafe Dalamud.Game.ClientState.Objects.Types.GameObject? GposeTargetGameObject => GposeTarget == null ? null : _objectTable[GposeTarget->ObjectIndex]; public bool IsInCutscene { get; private set; } = false; - public bool IsInFrameworkThread => _framework.IsInFrameworkUpdateThread; public bool IsInGpose { get; private set; } = false; public bool IsLoggedIn { get; private set; } - public bool IsPlayerPresent => _clientState.LocalPlayer != null && _clientState.LocalPlayer.IsValid(); public bool IsZoning => _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51]; - public PlayerCharacter PlayerCharacter => _clientState.LocalPlayer!; - - public string PlayerName => _clientState.LocalPlayer?.Name.ToString() ?? "--"; - - public string PlayerNameHashed => (PlayerName + _clientState.LocalPlayer!.HomeWorld.Id).GetHash256(); - - public IntPtr PlayerPointer => _clientState.LocalPlayer?.Address ?? IntPtr.Zero; public Lazy> WorldData { get; private set; } - public uint WorldId => _clientState.LocalPlayer!.HomeWorld.Id; - - public static bool IsObjectPresent(Dalamud.Game.ClientState.Objects.Types.GameObject? obj) + public Dalamud.Game.ClientState.Objects.Types.GameObject? CreateGameObject(IntPtr reference) { - return obj != null && obj.IsValid(); + EnsureIsOnFramework(); + return _objectTable.CreateObjectReference(reference); } public async Task CreateGameObjectAsync(IntPtr reference) @@ -86,45 +76,128 @@ public class DalamudUtilService : IHostedService 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) { + EnsureIsOnFramework(); var objTableObj = _objectTable[index]; if (objTableObj!.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) return null; return (Dalamud.Game.ClientState.Objects.Types.Character)objTableObj; } - public async Task GetCompanion(IntPtr? playerPointer = null) + public unsafe IntPtr GetCompanion(IntPtr? playerPointer = null) { - return await RunOnFrameworkThread(() => GetCompanionInternal(playerPointer)).ConfigureAwait(false); + EnsureIsOnFramework(); + var mgr = CharacterManager.Instance(); + playerPointer ??= GetPlayerPointer(); + if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero; + return (IntPtr)mgr->LookupBuddyByOwnerObject((BattleChara*)playerPointer); } - public async Task GetMinionOrMount(IntPtr? playerPointer = null) + public async Task GetCompanionAsync(IntPtr? playerPointer = null) { - return await RunOnFrameworkThread(() => GetMinionOrMountInternal(playerPointer)).ConfigureAwait(false); + return await RunOnFrameworkThread(() => GetCompanion(playerPointer)).ConfigureAwait(false); } - public async Task GetPet(IntPtr? playerPointer = null) + public bool GetIsPlayerPresent() { - return await RunOnFrameworkThread(() => GetPetInternal(playerPointer)).ConfigureAwait(false); + EnsureIsOnFramework(); + return _clientState.LocalPlayer != null && _clientState.LocalPlayer.IsValid(); } - public IntPtr GetPlayerCharacterFromObjectTableByIdent(string characterName) + public async Task GetIsPlayerPresentAsync() + { + return await RunOnFrameworkThread(GetIsPlayerPresent).ConfigureAwait(false); + } + + public unsafe IntPtr GetMinionOrMount(IntPtr? playerPointer = null) + { + EnsureIsOnFramework(); + playerPointer ??= GetPlayerPointer(); + if (playerPointer == IntPtr.Zero) return IntPtr.Zero; + return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1); + } + + public async Task GetMinionOrMountAsync(IntPtr? playerPointer = null) + { + return await RunOnFrameworkThread(() => GetMinionOrMount(playerPointer)).ConfigureAwait(false); + } + + public unsafe IntPtr GetPet(IntPtr? playerPointer = null) + { + EnsureIsOnFramework(); + if (_classJobIdsIgnoredForPets.Contains(_classJobId ?? 0)) return IntPtr.Zero; + var mgr = CharacterManager.Instance(); + playerPointer ??= GetPlayerPointer(); + if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero; + return (IntPtr)mgr->LookupPetByOwnerObject((BattleChara*)playerPointer); + } + + public async Task GetPetAsync(IntPtr? playerPointer = null) + { + return await RunOnFrameworkThread(() => GetPet(playerPointer)).ConfigureAwait(false); + } + + public PlayerCharacter GetPlayerCharacter() + { + EnsureIsOnFramework(); + return _clientState.LocalPlayer!; + } + + public IntPtr GetPlayerCharacterFromCachedTableByIdent(string characterName) { if (_playerCharas.TryGetValue(characterName, out var pchar)) return pchar.Address; return IntPtr.Zero; } + public string GetPlayerName() + { + EnsureIsOnFramework(); + return _clientState.LocalPlayer?.Name.ToString() ?? "--"; + } + + public async Task GetPlayerNameAsync() + { + return await RunOnFrameworkThread(GetPlayerName).ConfigureAwait(false); + } + + public async Task GetPlayerNameHashedAsync() + { + return await RunOnFrameworkThread(() => (GetPlayerName() + GetWorldId()).GetHash256()).ConfigureAwait(false); + } + + public IntPtr GetPlayerPointer() + { + EnsureIsOnFramework(); + return _clientState.LocalPlayer?.Address ?? IntPtr.Zero; + } + + public uint GetWorldId() + { + EnsureIsOnFramework(); + return _clientState.LocalPlayer!.HomeWorld.Id; + } + + public async Task GetWorldIdAsync() + { + return await RunOnFrameworkThread(GetWorldId).ConfigureAwait(false); + } + public unsafe bool IsGameObjectPresent(IntPtr key) { return _objectTable.Any(f => f.Address == key); } + public bool IsObjectPresent(Dalamud.Game.ClientState.Objects.Types.GameObject? obj) + { + EnsureIsOnFramework(); + return obj != null && obj.IsValid(); + } + + public async Task IsObjectPresentAsync(Dalamud.Game.ClientState.Objects.Types.GameObject? obj) + { + return await RunOnFrameworkThread(() => IsObjectPresent(obj)).ConfigureAwait(false); + } + public async Task RunOnFrameworkThread(Action act) { if (!_framework.IsInFrameworkUpdateThread) @@ -334,28 +407,4 @@ public class DalamudUtilService : IHostedService _delayedFrameworkUpdateCheck = DateTime.Now; } - - private unsafe IntPtr GetCompanionInternal(IntPtr? playerPointer = null) - { - var mgr = CharacterManager.Instance(); - playerPointer ??= PlayerPointer; - if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero; - return (IntPtr)mgr->LookupBuddyByOwnerObject((BattleChara*)playerPointer); - } - - private unsafe IntPtr GetMinionOrMountInternal(IntPtr? playerPointer = null) - { - playerPointer ??= PlayerPointer; - if (playerPointer == IntPtr.Zero) return IntPtr.Zero; - return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1); - } - - private unsafe IntPtr GetPetInternal(IntPtr? playerPointer = null) - { - if (_classJobIdsIgnoredForPets.Contains(_classJobId ?? 0)) return IntPtr.Zero; - var mgr = CharacterManager.Instance(); - playerPointer ??= PlayerPointer; - if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero; - return (IntPtr)mgr->LookupPetByOwnerObject((BattleChara*)playerPointer); - } } \ No newline at end of file diff --git a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs index 0aea94c..d7bd52f 100644 --- a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs +++ b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs @@ -57,8 +57,8 @@ public class ServerConfigurationManager Save(); } - var charaName = _dalamudUtil.PlayerName; - var worldId = _dalamudUtil.WorldId; + var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(); + var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(); if (!currentServer.Authentications.Any() && currentServer.SecretKeys.Any()) { currentServer.Authentications.Add(new Authentication() @@ -112,8 +112,8 @@ public class ServerConfigurationManager public string? GetToken() { - var charaName = _dalamudUtil.PlayerName; - var worldId = _dalamudUtil.WorldId; + var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(); + var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(); var secretKey = GetSecretKey(); if (secretKey == null) return null; if (_tokenDictionary.TryGetValue(new JwtCache(CurrentApiUrl, charaName, worldId, secretKey), out var token)) @@ -138,8 +138,8 @@ public class ServerConfigurationManager public void SaveToken(string token) { - var charaName = _dalamudUtil.PlayerName; - var worldId = _dalamudUtil.WorldId; + var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(); + var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(); var secretKey = GetSecretKey(); if (string.IsNullOrEmpty(secretKey)) throw new InvalidOperationException("No secret key set"); _tokenDictionary[new JwtCache(CurrentApiUrl, charaName, worldId, secretKey)] = token; @@ -158,8 +158,8 @@ public class ServerConfigurationManager var server = GetServerByIndex(serverSelectionIndex); server.Authentications.Add(new Authentication() { - CharacterName = _dalamudUtil.PlayerName, - WorldId = _dalamudUtil.WorldId, + CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(), + WorldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(), SecretKeyIdx = addLastSecretKey ? server.SecretKeys.Last().Key : -1, }); Save(); diff --git a/MareSynchronos/UI/UISharedService.cs b/MareSynchronos/UI/UISharedService.cs index d9f34c1..8e043a1 100644 --- a/MareSynchronos/UI/UISharedService.cs +++ b/MareSynchronos/UI/UISharedService.cs @@ -64,14 +64,12 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase private bool _heelsExists = false; + private bool _honorificExists = false; private bool _isDirectoryWritable = false; private bool _isPenumbraDirectory = false; private bool _palettePlusExists = false; - - private bool _honorificExists = false; - private bool _penumbraExists = false; private int _serverSelectionIndex = -1; @@ -119,7 +117,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase public bool IsInGpose => _dalamudUtil.IsInCutscene; - public string PlayerName => _dalamudUtil.PlayerName; + public string PlayerName => _dalamudUtil.GetPlayerName(); public ImFontPtr UidFont { get; private set; } @@ -127,7 +125,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase public Dictionary WorldData => _dalamudUtil.WorldData.Value; - public uint WorldId => _dalamudUtil.WorldId; + public uint WorldId => _dalamudUtil.GetWorldId(); public static void AttachToolTip(string text) { diff --git a/MareSynchronos/WebAPI/SignalR/ApiController.cs b/MareSynchronos/WebAPI/SignalR/ApiController.cs index 11b73f6..fa738d2 100644 --- a/MareSynchronos/WebAPI/SignalR/ApiController.cs +++ b/MareSynchronos/WebAPI/SignalR/ApiController.cs @@ -148,7 +148,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM var result = await httpClient.PostAsync(postUri, new FormUrlEncodedContent(new[] { new KeyValuePair("auth", auth), - new KeyValuePair("charaIdent", _dalamudUtil.PlayerNameHashed), + new KeyValuePair("charaIdent", await _dalamudUtil.GetPlayerNameHashedAsync().ConfigureAwait(false)), })).ConfigureAwait(false); AuthFailureMessage = await result.Content.ReadAsStringAsync().ConfigureAwait(false); result.EnsureSuccessStatusCode(); @@ -156,7 +156,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM Logger.LogDebug("JWT Success"); } - while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested) + while (!await _dalamudUtil.GetIsPlayerPresentAsync().ConfigureAwait(false) && !token.IsCancellationRequested) { Logger.LogDebug("Player not loaded in yet, waiting"); await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);