This commit is contained in:
rootdarkarchon
2023-05-02 20:56:07 +02:00
parent f8993916bd
commit ae5f1e9527
12 changed files with 170 additions and 121 deletions

View File

@@ -24,6 +24,8 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
_configurationService = configurationService; _configurationService = configurationService;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
PlayerPersistentDataKey = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult() + "_" + _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult();
SemiTransientResources.TryAdd(ObjectKind.Player, new HashSet<string>(StringComparer.Ordinal)); SemiTransientResources.TryAdd(ObjectKind.Player, new HashSet<string>(StringComparer.Ordinal));
if (_configurationService.Current.PlayerPersistentTransientCache.TryGetValue(PlayerPersistentDataKey, out var gamePaths)) 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<ObjectKind, HashSet<string>> SemiTransientResources { get; } = new(); private ConcurrentDictionary<ObjectKind, HashSet<string>> SemiTransientResources { get; } = new();
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new(); private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
@@ -185,7 +187,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
Logger.LogDebug("Penumbra Mod Settings changed, verifying SemiTransientResources"); Logger.LogDebug("Penumbra Mod Settings changed, verifying SemiTransientResources");
foreach (var item in SemiTransientResources) foreach (var item in SemiTransientResources)
{ {
Mediator.Publish(new TransientResourceChangedMessage(_dalamudUtil.PlayerPointer)); Mediator.Publish(new TransientResourceChangedMessage(_dalamudUtil.GetPlayerPointer()));
} }
}); });
} }

View File

@@ -24,7 +24,6 @@ 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 _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;
@@ -64,6 +63,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly FuncSubscriber<string, string, int, PenumbraApiEc> _penumbraRemoveTemporaryMod; private readonly FuncSubscriber<string, string, int, PenumbraApiEc> _penumbraRemoveTemporaryMod;
private readonly FuncSubscriber<string> _penumbraResolveModDir; private readonly FuncSubscriber<string> _penumbraResolveModDir;
private readonly FuncSubscriber<string[], string[], (string[], string[][])> _penumbraResolvePaths; private readonly FuncSubscriber<string[], string[], (string[], string[][])> _penumbraResolvePaths;
private readonly SemaphoreSlim _redrawSemaphore = new(2);
private bool _customizePlusAvailable = false; private bool _customizePlusAvailable = false;
private CancellationTokenSource _disposalCts = new(); private CancellationTokenSource _disposalCts = new();
private bool _glamourerAvailable = false; private bool _glamourerAvailable = false;
@@ -193,7 +193,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public async Task<string> GetCustomizePlusScaleAsync() 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.GetPlayerName())).ConfigureAwait(false);
if (string.IsNullOrEmpty(scale)) return string.Empty; if (string.IsNullOrEmpty(scale)) return string.Empty;
return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale)); return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale));
} }
@@ -340,7 +340,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public async Task<string> PalettePlusBuildPaletteAsync() 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.GetPlayerCharacter())).ConfigureAwait(false);
if (string.IsNullOrEmpty(palette)) return string.Empty; if (string.IsNullOrEmpty(palette)) return string.Empty;
return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette)); return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette));
} }

View File

@@ -124,7 +124,7 @@ public class MarePlugin : MediatorSubscriberBase, IHostedService
private async Task WaitForPlayerAndLaunchCharacterManager() private async Task WaitForPlayerAndLaunchCharacterManager()
{ {
while (!_dalamudUtil.IsPlayerPresent) while (!await _dalamudUtil.GetIsPlayerPresentAsync().ConfigureAwait(false))
{ {
await Task.Delay(100).ConfigureAwait(false); await Task.Delay(100).ConfigureAwait(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.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"); _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);

View File

@@ -83,7 +83,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
} }
}); });
CheckAndUpdateObject(); _dalamudUtil.RunOnFrameworkThread(CheckAndUpdateObject).GetAwaiter().GetResult();
} }
public IntPtr Address { get; private set; } public IntPtr Address { get; private set; }
@@ -93,6 +93,19 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
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 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() public IntPtr CurrentAddress()
{ {
_dalamudUtil.EnsureIsOnFramework(); _dalamudUtil.EnsureIsOnFramework();
@@ -104,25 +117,6 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
return _dalamudUtil.CreateGameObject(Address); 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<bool> IsBeingDrawnRunOnFrameworkAsync() public async Task<bool> IsBeingDrawnRunOnFrameworkAsync()
{ {
return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false); return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false);
@@ -142,19 +136,6 @@ 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;
@@ -281,6 +262,25 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
return (IntPtr)((GameObject*)curPtr)->DrawObject; 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) 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")); Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Checking IsBeingDrawn for Ptr {curPtr} : DrawObj {drawObj}", this, curPtr.ToString("X"), drawObj.ToString("X"));

View File

@@ -211,9 +211,9 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
var handler = changes.Key switch var handler = changes.Key switch
{ {
ObjectKind.Player => _charaHandler!, ObjectKind.Player => _charaHandler!,
ObjectKind.Companion => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(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).GetAwaiter().GetResult(), 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).GetAwaiter().GetResult(), false).ConfigureAwait(false), ObjectKind.Pet => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(ptr), false).ConfigureAwait(false),
_ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key) _ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key)
}; };
@@ -447,7 +447,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
{ {
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => _ipcManager await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => _ipcManager
.PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!) .PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!)
.ConfigureAwait(true).GetAwaiter().GetResult(), token); .ConfigureAwait(true).GetAwaiter().GetResult(), token).ConfigureAwait(false);
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() =>
@@ -457,7 +457,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
var objTableIndex = gameObj.ObjectTableIndex(); var objTableIndex = gameObj.ObjectTableIndex();
_ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData) _ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData)
.ConfigureAwait(true).GetAwaiter().GetResult(); .ConfigureAwait(true).GetAwaiter().GetResult();
}, token); }, token).ConfigureAwait(false);
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
} }
@@ -519,7 +519,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private void Initialize(string name) private void Initialize(string name)
{ {
PlayerName = 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(); _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult();
_lastGlamourerData = _originalGlamourerData; _lastGlamourerData = _originalGlamourerData;
@@ -594,7 +594,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private async Task RevertCustomizationDataAsync(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.GetPlayerCharacterFromCachedTableByIdent(OnlineUser.Ident);
if (address == IntPtr.Zero) return; if (address == IntPtr.Zero) return;
var cancelToken = new CancellationTokenSource(); var cancelToken = new CancellationTokenSource();
@@ -623,7 +623,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
else if (objectKind == ObjectKind.MinionOrMount) 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) 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);
@@ -632,7 +632,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
else if (objectKind == ObjectKind.Pet) 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) 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);
@@ -641,7 +641,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
else if (objectKind == ObjectKind.Companion) 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) 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);

View File

@@ -45,7 +45,7 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase
private void FrameworkOnUpdate() private void FrameworkOnUpdate()
{ {
if (!_dalamudUtil.IsPlayerPresent || !_apiController.IsConnected) return; if (!_dalamudUtil.GetIsPlayerPresent() || !_apiController.IsConnected) return;
if (!_newVisiblePlayers.Any()) return; if (!_newVisiblePlayers.Any()) return;
var newVisiblePlayers = _newVisiblePlayers.ToList(); var newVisiblePlayers = _newVisiblePlayers.ToList();

View File

@@ -76,13 +76,13 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
await AddPlayerCacheToCreate().ConfigureAwait(false); 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(); .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(); .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(); .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(); .GetAwaiter().GetResult();
} }

View File

@@ -54,26 +54,16 @@ public class DalamudUtilService : IHostedService
public unsafe GameObject* GposeTarget => TargetSystem.Instance()->GPoseTarget; public unsafe GameObject* GposeTarget => TargetSystem.Instance()->GPoseTarget;
public unsafe Dalamud.Game.ClientState.Objects.Types.GameObject? GposeTargetGameObject => GposeTarget == null ? null : _objectTable[GposeTarget->ObjectIndex]; public unsafe Dalamud.Game.ClientState.Objects.Types.GameObject? GposeTargetGameObject => GposeTarget == null ? null : _objectTable[GposeTarget->ObjectIndex];
public bool IsInCutscene { get; private set; } = false; public bool IsInCutscene { get; private set; } = false;
public bool IsInFrameworkThread => _framework.IsInFrameworkUpdateThread;
public bool IsInGpose { get; private set; } = false; public bool IsInGpose { get; private set; } = false;
public bool IsLoggedIn { get; private set; } 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 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<Dictionary<ushort, string>> WorldData { get; private set; } public Lazy<Dictionary<ushort, string>> WorldData { get; private set; }
public uint WorldId => _clientState.LocalPlayer!.HomeWorld.Id; public Dalamud.Game.ClientState.Objects.Types.GameObject? CreateGameObject(IntPtr reference)
public static bool IsObjectPresent(Dalamud.Game.ClientState.Objects.Types.GameObject? obj)
{ {
return obj != null && obj.IsValid(); EnsureIsOnFramework();
return _objectTable.CreateObjectReference(reference);
} }
public async Task<Dalamud.Game.ClientState.Objects.Types.GameObject?> CreateGameObjectAsync(IntPtr reference) public async Task<Dalamud.Game.ClientState.Objects.Types.GameObject?> CreateGameObjectAsync(IntPtr reference)
@@ -86,45 +76,128 @@ public class DalamudUtilService : IHostedService
if (!_framework.IsInFrameworkUpdateThread) throw new InvalidOperationException("Can only be run on Framework"); 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)
{ {
EnsureIsOnFramework();
var objTableObj = _objectTable[index]; var objTableObj = _objectTable[index];
if (objTableObj!.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) return null; if (objTableObj!.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) return null;
return (Dalamud.Game.ClientState.Objects.Types.Character)objTableObj; return (Dalamud.Game.ClientState.Objects.Types.Character)objTableObj;
} }
public async Task<IntPtr> 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<IntPtr> GetMinionOrMount(IntPtr? playerPointer = null) public async Task<IntPtr> GetCompanionAsync(IntPtr? playerPointer = null)
{ {
return await RunOnFrameworkThread(() => GetMinionOrMountInternal(playerPointer)).ConfigureAwait(false); return await RunOnFrameworkThread(() => GetCompanion(playerPointer)).ConfigureAwait(false);
} }
public async Task<IntPtr> 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<bool> 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<IntPtr> 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<IntPtr> 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; if (_playerCharas.TryGetValue(characterName, out var pchar)) return pchar.Address;
return IntPtr.Zero; return IntPtr.Zero;
} }
public string GetPlayerName()
{
EnsureIsOnFramework();
return _clientState.LocalPlayer?.Name.ToString() ?? "--";
}
public async Task<string> GetPlayerNameAsync()
{
return await RunOnFrameworkThread(GetPlayerName).ConfigureAwait(false);
}
public async Task<string> 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<uint> GetWorldIdAsync()
{
return await RunOnFrameworkThread(GetWorldId).ConfigureAwait(false);
}
public unsafe bool IsGameObjectPresent(IntPtr key) public unsafe bool IsGameObjectPresent(IntPtr key)
{ {
return _objectTable.Any(f => f.Address == 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<bool> IsObjectPresentAsync(Dalamud.Game.ClientState.Objects.Types.GameObject? obj)
{
return await RunOnFrameworkThread(() => IsObjectPresent(obj)).ConfigureAwait(false);
}
public async Task RunOnFrameworkThread(Action act) public async Task RunOnFrameworkThread(Action act)
{ {
if (!_framework.IsInFrameworkUpdateThread) if (!_framework.IsInFrameworkUpdateThread)
@@ -334,28 +407,4 @@ public class DalamudUtilService : IHostedService
_delayedFrameworkUpdateCheck = DateTime.Now; _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);
}
} }

View File

@@ -57,8 +57,8 @@ public class ServerConfigurationManager
Save(); Save();
} }
var charaName = _dalamudUtil.PlayerName; var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.WorldId; var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult();
if (!currentServer.Authentications.Any() && currentServer.SecretKeys.Any()) if (!currentServer.Authentications.Any() && currentServer.SecretKeys.Any())
{ {
currentServer.Authentications.Add(new Authentication() currentServer.Authentications.Add(new Authentication()
@@ -112,8 +112,8 @@ public class ServerConfigurationManager
public string? GetToken() public string? GetToken()
{ {
var charaName = _dalamudUtil.PlayerName; var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.WorldId; var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult();
var secretKey = GetSecretKey(); var secretKey = GetSecretKey();
if (secretKey == null) return null; if (secretKey == null) return null;
if (_tokenDictionary.TryGetValue(new JwtCache(CurrentApiUrl, charaName, worldId, secretKey), out var token)) if (_tokenDictionary.TryGetValue(new JwtCache(CurrentApiUrl, charaName, worldId, secretKey), out var token))
@@ -138,8 +138,8 @@ public class ServerConfigurationManager
public void SaveToken(string token) public void SaveToken(string token)
{ {
var charaName = _dalamudUtil.PlayerName; var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.WorldId; var worldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult();
var secretKey = GetSecretKey(); var secretKey = GetSecretKey();
if (string.IsNullOrEmpty(secretKey)) throw new InvalidOperationException("No secret key set"); if (string.IsNullOrEmpty(secretKey)) throw new InvalidOperationException("No secret key set");
_tokenDictionary[new JwtCache(CurrentApiUrl, charaName, worldId, secretKey)] = token; _tokenDictionary[new JwtCache(CurrentApiUrl, charaName, worldId, secretKey)] = token;
@@ -158,8 +158,8 @@ public class ServerConfigurationManager
var server = GetServerByIndex(serverSelectionIndex); var server = GetServerByIndex(serverSelectionIndex);
server.Authentications.Add(new Authentication() server.Authentications.Add(new Authentication()
{ {
CharacterName = _dalamudUtil.PlayerName, CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(),
WorldId = _dalamudUtil.WorldId, WorldId = _dalamudUtil.GetWorldIdAsync().GetAwaiter().GetResult(),
SecretKeyIdx = addLastSecretKey ? server.SecretKeys.Last().Key : -1, SecretKeyIdx = addLastSecretKey ? server.SecretKeys.Last().Key : -1,
}); });
Save(); Save();

View File

@@ -64,14 +64,12 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
private bool _heelsExists = false; private bool _heelsExists = false;
private bool _honorificExists = false;
private bool _isDirectoryWritable = false; private bool _isDirectoryWritable = false;
private bool _isPenumbraDirectory = false; private bool _isPenumbraDirectory = false;
private bool _palettePlusExists = false; private bool _palettePlusExists = false;
private bool _honorificExists = false;
private bool _penumbraExists = false; private bool _penumbraExists = false;
private int _serverSelectionIndex = -1; private int _serverSelectionIndex = -1;
@@ -119,7 +117,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public bool IsInGpose => _dalamudUtil.IsInCutscene; public bool IsInGpose => _dalamudUtil.IsInCutscene;
public string PlayerName => _dalamudUtil.PlayerName; public string PlayerName => _dalamudUtil.GetPlayerName();
public ImFontPtr UidFont { get; private set; } public ImFontPtr UidFont { get; private set; }
@@ -127,7 +125,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public Dictionary<ushort, string> WorldData => _dalamudUtil.WorldData.Value; public Dictionary<ushort, string> WorldData => _dalamudUtil.WorldData.Value;
public uint WorldId => _dalamudUtil.WorldId; public uint WorldId => _dalamudUtil.GetWorldId();
public static void AttachToolTip(string text) public static void AttachToolTip(string text)
{ {

View File

@@ -148,7 +148,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
var result = await httpClient.PostAsync(postUri, new FormUrlEncodedContent(new[] var result = await httpClient.PostAsync(postUri, new FormUrlEncodedContent(new[]
{ {
new KeyValuePair<string, string>("auth", auth), new KeyValuePair<string, string>("auth", auth),
new KeyValuePair<string, string>("charaIdent", _dalamudUtil.PlayerNameHashed), new KeyValuePair<string, string>("charaIdent", await _dalamudUtil.GetPlayerNameHashedAsync().ConfigureAwait(false)),
})).ConfigureAwait(false); })).ConfigureAwait(false);
AuthFailureMessage = await result.Content.ReadAsStringAsync().ConfigureAwait(false); AuthFailureMessage = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
result.EnsureSuccessStatusCode(); result.EnsureSuccessStatusCode();
@@ -156,7 +156,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
Logger.LogDebug("JWT Success"); 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"); Logger.LogDebug("Player not loaded in yet, waiting");
await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false); await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);