From 40b3bd01b33d72a44aee37f2d2f04699bdfdbbe6 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Wed, 15 Mar 2023 12:44:46 +0100 Subject: [PATCH] get fresh pointer on dispose --- MareSynchronos/MareSynchronos.csproj | 2 +- .../PlayerData/Handlers/GameObjectHandler.cs | 11 +++---- .../PlayerData/Pairs/CachedPlayer.cs | 30 ++++++++++++++++--- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/MareSynchronos/MareSynchronos.csproj b/MareSynchronos/MareSynchronos.csproj index 7db4f1b..74f4686 100644 --- a/MareSynchronos/MareSynchronos.csproj +++ b/MareSynchronos/MareSynchronos.csproj @@ -3,7 +3,7 @@ - 0.8.5 + 0.8.6 https://github.com/Penumbra-Sync/client diff --git a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs index 211ca85..4cf2fc0 100644 --- a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs +++ b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs @@ -96,11 +96,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase { return await _dalamudUtil.RunOnFrameworkThread(() => { - var curPtr = _getAddress.Invoke(); - + nint curPtr = IntPtr.Zero; try { - var drawObj = GetDrawObj(); + curPtr = _getAddress.Invoke(); + + var drawObj = GetDrawObj(curPtr); return IsBeingDrawn(drawObj, curPtr); } catch (Exception) @@ -258,9 +259,9 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase } } - private unsafe IntPtr GetDrawObj() + private unsafe IntPtr GetDrawObj(nint curPtr) { - return (IntPtr)((GameObject*)_getAddress.Invoke())->GetDrawObject(); + return (IntPtr)((GameObject*)curPtr)->GetDrawObject(); } private unsafe bool IsBeingDrawn(IntPtr drawObj, IntPtr curPtr) diff --git a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs index e71a75e..eb8dc7c 100644 --- a/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs +++ b/MareSynchronos/PlayerData/Pairs/CachedPlayer.cs @@ -155,17 +155,25 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase _downloadCancellationTokenSource?.Cancel(); _downloadCancellationTokenSource?.Dispose(); _downloadCancellationTokenSource = null; - nint ptr = PlayerCharacter; _charaHandler?.Dispose(); _charaHandler = null; - if (!_lifetime.ApplicationStopping.IsCancellationRequested && ptr != IntPtr.Zero && !_dalamudUtil.IsZoning) + + if (!_lifetime.ApplicationStopping.IsCancellationRequested && !_dalamudUtil.IsZoning) { Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser); _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name); foreach (KeyValuePair> item in _cachedData.FileReplacements) { - RevertCustomizationData(ptr, item.Key, name, applicationId).GetAwaiter().GetResult(); + try + { + RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult(); + } + catch (InvalidOperationException ex) + { + Logger.LogWarning("Failed disposing player (not present anymore?)", ex); + break; + } } } } @@ -472,8 +480,17 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase } } - private async Task RevertCustomizationData(IntPtr address, ObjectKind objectKind, string name, Guid applicationId) + private void CheckForNameAndThrow(GameObjectHandler handler, string name) { + if (!string.Equals(handler.Name, name, StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException("Player name not equal to requested name, pointer invalid"); + } + } + + private async Task RevertCustomizationData(ObjectKind objectKind, string name, Guid applicationId) + { + nint address = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(name)?.Address ?? IntPtr.Zero; if (address == IntPtr.Zero) return; var cancelToken = new CancellationTokenSource(); @@ -484,14 +501,19 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase if (objectKind == ObjectKind.Player) { using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => address, false); + CheckForNameAndThrow(tempHandler, name); Logger.LogDebug("[{applicationId}] Restoring Customization for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData); await _ipcManager.GlamourerApplyOnlyCustomization(Logger, tempHandler, _originalGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); + CheckForNameAndThrow(tempHandler, name); Logger.LogDebug("[{applicationId}] Restoring Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _lastGlamourerData); await _ipcManager.GlamourerApplyOnlyEquipment(Logger, tempHandler, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); + CheckForNameAndThrow(tempHandler, name); Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false); + CheckForNameAndThrow(tempHandler, name); Logger.LogDebug("[{applicationId}] Restoring C+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); await _ipcManager.CustomizePlusRevert(address).ConfigureAwait(false); + CheckForNameAndThrow(tempHandler, name); Logger.LogDebug("[{applicationId}] Restoring Palette+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); await _ipcManager.PalettePlusRemovePalette(address).ConfigureAwait(false); }