Merge branch 'main' of https://github.com/Penumbra-Sync/client
This commit is contained in:
@@ -581,7 +581,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
private void OnPalettePlusPaletteChange(Character character, string palette)
|
private void OnPalettePlusPaletteChange(Character character, string palette)
|
||||||
{
|
{
|
||||||
Mediator.Publish(new PalettePlusMessage());
|
Mediator.Publish(new PalettePlusMessage(character));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PenumbraDispose()
|
private void PenumbraDispose()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors></Authors>
|
<Authors></Authors>
|
||||||
<Company></Company>
|
<Company></Company>
|
||||||
<Version>0.8.3</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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
|
|||||||
private readonly PlayerDataFactory _characterDataFactory;
|
private readonly PlayerDataFactory _characterDataFactory;
|
||||||
private readonly CancellationTokenSource _cts = new();
|
private readonly CancellationTokenSource _cts = new();
|
||||||
private readonly CharacterData _playerData = new();
|
private readonly CharacterData _playerData = new();
|
||||||
private readonly List<GameObjectHandler> _playerRelatedObjects = new();
|
private readonly Dictionary<ObjectKind, GameObjectHandler> _playerRelatedObjects = new();
|
||||||
private Task? _cacheCreationTask;
|
private Task? _cacheCreationTask;
|
||||||
private CancellationTokenSource _palettePlusCts = new();
|
private CancellationTokenSource _palettePlusCts = new();
|
||||||
|
|
||||||
@@ -26,19 +26,12 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
Mediator.Subscribe<CreateCacheForObjectMessage>(this, (msg) =>
|
Mediator.Subscribe<CreateCacheForObjectMessage>(this, (msg) =>
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug("Received CreateCacheForObject for {handler}, updating player", msg.ObjectToCreateFor);
|
||||||
_cacheCreateLock.Wait();
|
_cacheCreateLock.Wait();
|
||||||
_cachesToCreate[msg.ObjectToCreateFor.ObjectKind] = msg.ObjectToCreateFor;
|
_cachesToCreate[msg.ObjectToCreateFor.ObjectKind] = msg.ObjectToCreateFor;
|
||||||
_cacheCreateLock.Release();
|
_cacheCreateLock.Release();
|
||||||
});
|
});
|
||||||
|
|
||||||
_playerRelatedObjects.AddRange(new List<GameObjectHandler>()
|
|
||||||
{
|
|
||||||
gameObjectHandlerFactory(ObjectKind.Player, () => dalamudUtil.PlayerPointer, true),
|
|
||||||
gameObjectHandlerFactory(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount(), true),
|
|
||||||
gameObjectHandlerFactory(ObjectKind.Pet, () => dalamudUtil.GetPet(), true),
|
|
||||||
gameObjectHandlerFactory(ObjectKind.Companion, () => dalamudUtil.GetCompanion(), true),
|
|
||||||
});
|
|
||||||
|
|
||||||
Mediator.Subscribe<ClearCacheForObjectMessage>(this, (msg) =>
|
Mediator.Subscribe<ClearCacheForObjectMessage>(this, (msg) =>
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
@@ -50,24 +43,52 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
|
|||||||
});
|
});
|
||||||
|
|
||||||
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (msg) => ProcessCacheCreation());
|
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (msg) => ProcessCacheCreation());
|
||||||
Mediator.Subscribe<CustomizePlusMessage>(this, async (_) => await AddPlayerCacheToCreate().ConfigureAwait(false));
|
Mediator.Subscribe<CustomizePlusMessage>(this, async (_) =>
|
||||||
Mediator.Subscribe<HeelsOffsetMessage>(this, async (_) => await AddPlayerCacheToCreate().ConfigureAwait(false));
|
{
|
||||||
Mediator.Subscribe<PalettePlusMessage>(this, (_) => PalettePlusChanged());
|
Logger.LogDebug("Received CustomizePlus change, updating player");
|
||||||
Mediator.Subscribe<PenumbraModSettingChangedMessage>(this, async (msg) => await AddPlayerCacheToCreate().ConfigureAwait(false));
|
await AddPlayerCacheToCreate().ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
Mediator.Subscribe<HeelsOffsetMessage>(this, async (_) =>
|
||||||
|
{
|
||||||
|
Logger.LogDebug("Received Heels Offset change, updating player");
|
||||||
|
await AddPlayerCacheToCreate().ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
Mediator.Subscribe<PalettePlusMessage>(this, (msg) =>
|
||||||
|
{
|
||||||
|
if (msg.Character.Address == _playerRelatedObjects[ObjectKind.Player].Address)
|
||||||
|
{
|
||||||
|
Logger.LogDebug("Received PalettePlus change, updating player");
|
||||||
|
PalettePlusChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Mediator.Subscribe<PenumbraModSettingChangedMessage>(this, async (msg) =>
|
||||||
|
{
|
||||||
|
Logger.LogDebug("Received Penumbra Mod settings change, updating player");
|
||||||
|
await AddPlayerCacheToCreate().ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
_playerRelatedObjects[ObjectKind.Player] =
|
||||||
|
gameObjectHandlerFactory(ObjectKind.Player, () => dalamudUtil.PlayerPointer, true);
|
||||||
|
_playerRelatedObjects[ObjectKind.MinionOrMount] =
|
||||||
|
gameObjectHandlerFactory(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount(), true);
|
||||||
|
_playerRelatedObjects[ObjectKind.Pet] =
|
||||||
|
gameObjectHandlerFactory(ObjectKind.Pet, () => dalamudUtil.GetPet(), true);
|
||||||
|
_playerRelatedObjects[ObjectKind.Companion] =
|
||||||
|
gameObjectHandlerFactory(ObjectKind.Companion, () => dalamudUtil.GetCompanion(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
||||||
_playerRelatedObjects.ForEach(p => p.Dispose());
|
_playerRelatedObjects.Values.ToList().ForEach(p => p.Dispose());
|
||||||
_cts.Dispose();
|
_cts.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddPlayerCacheToCreate()
|
private async Task AddPlayerCacheToCreate()
|
||||||
{
|
{
|
||||||
await _cacheCreateLock.WaitAsync().ConfigureAwait(false);
|
await _cacheCreateLock.WaitAsync().ConfigureAwait(false);
|
||||||
_cachesToCreate[ObjectKind.Player] = _playerRelatedObjects.First(p => p.ObjectKind == ObjectKind.Player);
|
_cachesToCreate[ObjectKind.Player] = _playerRelatedObjects[ObjectKind.Player];
|
||||||
_cacheCreateLock.Release();
|
_cacheCreateLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,14 +157,20 @@ public class DalamudUtilService : IHostedService
|
|||||||
|
|
||||||
public async Task RunOnFrameworkThread(Action act)
|
public async Task RunOnFrameworkThread(Action act)
|
||||||
{
|
{
|
||||||
_logger.LogTrace("Running Action on framework thread: {act}", act);
|
_logger.LogTrace("Running Action on framework thread (FrameworkContext: {ctx}): {act}", _framework.IsInFrameworkUpdateThread, act);
|
||||||
await _framework.RunOnFrameworkThread(act).ConfigureAwait(false);
|
if (!_framework.IsInFrameworkUpdateThread)
|
||||||
|
await _framework.RunOnFrameworkThread(act).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
act();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T> RunOnFrameworkThread<T>(Func<T> func)
|
public async Task<T> RunOnFrameworkThread<T>(Func<T> func)
|
||||||
{
|
{
|
||||||
_logger.LogTrace("Running Func on framework thread: {func}", func);
|
_logger.LogTrace("Running Func on framework thread (FrameworkContext: {ctx}): {act}", _framework.IsInFrameworkUpdateThread, func);
|
||||||
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
|
if (!_framework.IsInFrameworkUpdateThread)
|
||||||
|
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
return func.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using MareSynchronos.API.Dto;
|
using MareSynchronos.API.Dto;
|
||||||
using MareSynchronos.PlayerData.Handlers;
|
using MareSynchronos.PlayerData.Handlers;
|
||||||
using MareSynchronos.WebAPI.Files.Models;
|
using MareSynchronos.WebAPI.Files.Models;
|
||||||
@@ -30,7 +31,7 @@ public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx, bool WasReque
|
|||||||
public record HeelsOffsetMessage : IMessage;
|
public record HeelsOffsetMessage : IMessage;
|
||||||
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : IMessage;
|
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : IMessage;
|
||||||
public record CustomizePlusMessage : IMessage;
|
public record CustomizePlusMessage : IMessage;
|
||||||
public record PalettePlusMessage : IMessage;
|
public record PalettePlusMessage(Character Character) : IMessage;
|
||||||
public record PlayerChangedMessage(API.Data.CharacterData Data) : IMessage;
|
public record PlayerChangedMessage(API.Data.CharacterData Data) : IMessage;
|
||||||
public record CharacterChangedMessage(GameObjectHandler GameObjectHandler) : IMessage;
|
public record CharacterChangedMessage(GameObjectHandler GameObjectHandler) : IMessage;
|
||||||
public record TransientResourceChangedMessage(IntPtr Address) : IMessage;
|
public record TransientResourceChangedMessage(IntPtr Address) : IMessage;
|
||||||
|
|||||||
Reference in New Issue
Block a user