Revert gpose actors on plugin unload or when NoSnap triggers
This commit is contained in:
@@ -13,18 +13,20 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly NoSnapService _noSnapService;
|
||||
private readonly Dictionary<string, HandledCharaDataEntry> _handledCharaData = new(StringComparer.Ordinal);
|
||||
|
||||
public IReadOnlyDictionary<string, HandledCharaDataEntry> HandledCharaData => _handledCharaData;
|
||||
|
||||
public CharaDataCharacterHandler(ILogger<CharaDataCharacterHandler> logger, MareMediator mediator,
|
||||
GameObjectHandlerFactory gameObjectHandlerFactory, DalamudUtilService dalamudUtilService,
|
||||
IpcManager ipcManager)
|
||||
IpcManager ipcManager, NoSnapService noSnapService)
|
||||
: base(logger, mediator)
|
||||
{
|
||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_ipcManager = ipcManager;
|
||||
_noSnapService = noSnapService;
|
||||
mediator.Subscribe<GposeEndMessage>(this, msg =>
|
||||
{
|
||||
foreach (var chara in _handledCharaData)
|
||||
@@ -90,13 +92,18 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
{
|
||||
if (handled == null) return false;
|
||||
_handledCharaData.Remove(handled.Name);
|
||||
await _dalamudUtilService.RunOnFrameworkThread(() => RevertChara(handled.Name, handled.CustomizePlus)).ConfigureAwait(false);
|
||||
await _dalamudUtilService.RunOnFrameworkThread(async () =>
|
||||
{
|
||||
RemoveGposer(handled);
|
||||
await RevertChara(handled.Name, handled.CustomizePlus).ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void AddHandledChara(HandledCharaDataEntry handledCharaDataEntry)
|
||||
{
|
||||
_handledCharaData.Add(handledCharaDataEntry.Name, handledCharaDataEntry);
|
||||
_ = _dalamudUtilService.RunOnFrameworkThread(() => AddGposer(handledCharaDataEntry));
|
||||
}
|
||||
|
||||
public void UpdateHandledData(Dictionary<string, CharaDataMetaInfoExtendedDto?> newData)
|
||||
@@ -127,4 +134,23 @@ public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
|
||||
if (handler.Address == nint.Zero) return null;
|
||||
return handler;
|
||||
}
|
||||
|
||||
private int GetGposerObjectIndex(string name)
|
||||
{
|
||||
return _dalamudUtilService.GetGposeCharacterFromObjectTableByName(name, _dalamudUtilService.IsInGpose)?.ObjectIndex ?? -1;
|
||||
}
|
||||
|
||||
private void AddGposer(HandledCharaDataEntry handled)
|
||||
{
|
||||
int objectIndex = GetGposerObjectIndex(handled.Name);
|
||||
if (objectIndex > 0)
|
||||
_noSnapService.AddGposer(objectIndex);
|
||||
}
|
||||
|
||||
private void RemoveGposer(HandledCharaDataEntry handled)
|
||||
{
|
||||
int objectIndex = GetGposerObjectIndex(handled.Name);
|
||||
if (objectIndex > 0)
|
||||
_noSnapService.RemoveGposer(objectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dalamud.Plugin;
|
||||
using MareSynchronos.Interop.Ipc;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -15,16 +16,23 @@ public class NoSnapService : IHostedService, IMediatorSubscriber
|
||||
["Snappy"] = false,
|
||||
["Meddle.Plugin"] = false
|
||||
};
|
||||
private static readonly HashSet<int> _gposers = new();
|
||||
private readonly IHostApplicationLifetime _hostApplicationLifetime;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly IpcManager _ipcManager;
|
||||
|
||||
public static bool AnyLoaded { get; private set; } = false;
|
||||
|
||||
public MareMediator Mediator { get; init; }
|
||||
|
||||
public NoSnapService(ILogger<NoSnapService> logger, IDalamudPluginInterface pi, MareMediator mediator)
|
||||
public NoSnapService(ILogger<NoSnapService> logger, IDalamudPluginInterface pi, MareMediator mediator,
|
||||
IHostApplicationLifetime hostApplicationLifetime, DalamudUtilService dalamudUtilService, IpcManager ipcManager)
|
||||
{
|
||||
_logger = logger;
|
||||
Mediator = mediator;
|
||||
|
||||
_hostApplicationLifetime = hostApplicationLifetime;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_ipcManager = ipcManager;
|
||||
foreach (var pluginName in _listOfPlugins.Keys)
|
||||
{
|
||||
var plugin = pi.InstalledPlugins.FirstOrDefault(p => p.InternalName.Equals(pluginName, StringComparison.Ordinal));
|
||||
@@ -38,9 +46,80 @@ public class NoSnapService : IHostedService, IMediatorSubscriber
|
||||
});
|
||||
}
|
||||
|
||||
Mediator.Subscribe<GposeEndMessage>(this, msg => ClearGposeList());
|
||||
Mediator.Subscribe<CutsceneEndMessage>(this, msg => ClearGposeList());
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
public void AddGposer(int objectIndex)
|
||||
{
|
||||
if (AnyLoaded || _hostApplicationLifetime.ApplicationStopping.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogInformation("Immediately reverting object index {id}", objectIndex);
|
||||
try
|
||||
{
|
||||
Guid applicationId = Guid.NewGuid();
|
||||
_ipcManager.Glamourer.RevertNow(_logger, applicationId, objectIndex);
|
||||
_ipcManager.Penumbra.RedrawNow(_logger, applicationId, objectIndex);
|
||||
}
|
||||
catch { }
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Registering gposer object index {id}", objectIndex);
|
||||
lock (_gposers)
|
||||
_gposers.Add(objectIndex);
|
||||
}
|
||||
|
||||
public void RemoveGposer(int objectIndex)
|
||||
{
|
||||
_logger.LogInformation("Un-registering gposer object index {id}", objectIndex);
|
||||
lock (_gposers)
|
||||
_gposers.Remove(objectIndex);
|
||||
}
|
||||
|
||||
private void ClearGposeList()
|
||||
{
|
||||
if (_gposers.Count > 0)
|
||||
_logger.LogInformation("Clearing gposer list");
|
||||
lock (_gposers)
|
||||
_gposers.Clear();
|
||||
}
|
||||
|
||||
private void RevertGposers()
|
||||
{
|
||||
List<int>? gposersList = null;
|
||||
|
||||
lock (_gposers)
|
||||
{
|
||||
if (_gposers.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Reverting gposers");
|
||||
gposersList = _gposers.ToList();
|
||||
_gposers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (gposersList == null)
|
||||
return;
|
||||
|
||||
_dalamudUtilService.RunOnFrameworkThread(() =>
|
||||
{
|
||||
Guid applicationId = Guid.NewGuid();
|
||||
|
||||
foreach (var gposer in gposersList)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ipcManager.Glamourer.RevertNow(_logger, applicationId, gposer);
|
||||
_ipcManager.Penumbra.RedrawNow(_logger, applicationId, gposer);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
@@ -48,6 +127,7 @@ public class NoSnapService : IHostedService, IMediatorSubscriber
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
RevertGposers();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -63,6 +143,7 @@ public class NoSnapService : IHostedService, IMediatorSubscriber
|
||||
|
||||
if (AnyLoaded)
|
||||
{
|
||||
RevertGposers();
|
||||
var pluginList = string.Join(", ", _listOfPlugins.Where(p => p.Value).Select(p => p.Key));
|
||||
Mediator.Publish(new NotificationMessage("Incompatible plugin loaded", $"Synced player appearances will not apply until incompatible plugins are disabled: {pluginList}.",
|
||||
NotificationType.Error));
|
||||
|
||||
@@ -75,6 +75,19 @@ public class PluginWatcherService : MediatorSubscriberBase
|
||||
Logger.LogError(e, "PluginWatcherService exception");
|
||||
}
|
||||
});
|
||||
|
||||
// Continue scanning plugins during gpose as well
|
||||
Mediator.Subscribe<CutsceneFrameworkUpdateMessage>(this, (_) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Update();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(e, "PluginWatcherService exception");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Update()
|
||||
|
||||
Reference in New Issue
Block a user