get fresh pointer on dispose

This commit is contained in:
Stanley Dimant
2023-03-15 12:44:46 +01:00
parent 4b4e7b5563
commit 40b3bd01b3
3 changed files with 33 additions and 10 deletions

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>0.8.5</Version> <Version>0.8.6</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>

View File

@@ -96,11 +96,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
{ {
return await _dalamudUtil.RunOnFrameworkThread(() => return await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var curPtr = _getAddress.Invoke(); nint curPtr = IntPtr.Zero;
try try
{ {
var drawObj = GetDrawObj(); curPtr = _getAddress.Invoke();
var drawObj = GetDrawObj(curPtr);
return IsBeingDrawn(drawObj, curPtr); return IsBeingDrawn(drawObj, curPtr);
} }
catch (Exception) 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) private unsafe bool IsBeingDrawn(IntPtr drawObj, IntPtr curPtr)

View File

@@ -155,17 +155,25 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
_downloadCancellationTokenSource?.Cancel(); _downloadCancellationTokenSource?.Cancel();
_downloadCancellationTokenSource?.Dispose(); _downloadCancellationTokenSource?.Dispose();
_downloadCancellationTokenSource = null; _downloadCancellationTokenSource = null;
nint ptr = PlayerCharacter;
_charaHandler?.Dispose(); _charaHandler?.Dispose();
_charaHandler = null; _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); Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name); _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData.FileReplacements) foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> 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; if (address == IntPtr.Zero) return;
var cancelToken = new CancellationTokenSource(); var cancelToken = new CancellationTokenSource();
@@ -484,14 +501,19 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (objectKind == ObjectKind.Player) if (objectKind == ObjectKind.Player)
{ {
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => address, false); 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); 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); 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); 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); 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); Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false); await _ipcManager.HeelsRestoreOffsetForPlayer(address).ConfigureAwait(false);
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.CustomizePlusRevert(address).ConfigureAwait(false);
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.PalettePlusRemovePalette(address).ConfigureAwait(false);
} }