127 lines
4.1 KiB
C#
127 lines
4.1 KiB
C#
using System;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.Ipc;
|
|
using LightlessSync.PlayerData.Handlers;
|
|
using LightlessSync.Services;
|
|
using LightlessSync.Services.Mediator;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace LightlessSync.Interop.Ipc;
|
|
|
|
public class IpcProvider : IHostedService, IMediatorSubscriber
|
|
{
|
|
private readonly ILogger<IpcProvider> _logger;
|
|
private readonly IDalamudPluginInterface _pi;
|
|
private readonly CharaDataManager _charaDataManager;
|
|
private readonly List<IpcRegister> _ipcRegisters = [];
|
|
private readonly List<GameObjectHandler> _activeGameObjectHandlers = [];
|
|
|
|
public LightlessMediator Mediator { get; init; }
|
|
|
|
public IpcProvider(ILogger<IpcProvider> logger, IDalamudPluginInterface pi,
|
|
CharaDataManager charaDataManager, LightlessMediator lightlessMediator)
|
|
{
|
|
_logger = logger;
|
|
_pi = pi;
|
|
_charaDataManager = charaDataManager;
|
|
Mediator = lightlessMediator;
|
|
|
|
Mediator.Subscribe<GameObjectHandlerCreatedMessage>(this, (msg) =>
|
|
{
|
|
if (msg.OwnedObject) return;
|
|
_activeGameObjectHandlers.Add(msg.GameObjectHandler);
|
|
});
|
|
Mediator.Subscribe<GameObjectHandlerDestroyedMessage>(this, (msg) =>
|
|
{
|
|
if (msg.OwnedObject) return;
|
|
_activeGameObjectHandlers.Remove(msg.GameObjectHandler);
|
|
});
|
|
}
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger.LogInformation("Starting IpcProviderService");
|
|
_ipcRegisters.Add(RegisterFunc<string, IGameObject, bool>("LightlessSync.LoadMcdf", LoadMcdf));
|
|
_ipcRegisters.Add(RegisterFunc<string, IGameObject, Task<bool>>("LightlessSync.LoadMcdfAsync", LoadMcdfAsync));
|
|
_ipcRegisters.Add(RegisterFunc("LightlessSync.GetHandledAddresses", GetHandledAddresses));
|
|
_logger.LogInformation("Started IpcProviderService");
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger.LogDebug("Stopping IpcProvider Service");
|
|
foreach (var register in _ipcRegisters)
|
|
{
|
|
register.Dispose();
|
|
}
|
|
_ipcRegisters.Clear();
|
|
Mediator.UnsubscribeAll(this);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task<bool> LoadMcdfAsync(string path, IGameObject target)
|
|
{
|
|
await ApplyFileAsync(path, target).ConfigureAwait(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool LoadMcdf(string path, IGameObject target)
|
|
{
|
|
_ = Task.Run(async () => await ApplyFileAsync(path, target).ConfigureAwait(false)).ConfigureAwait(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
private async Task ApplyFileAsync(string path, IGameObject target)
|
|
{
|
|
_charaDataManager.LoadMcdf(path);
|
|
await (_charaDataManager.LoadedMcdfHeader ?? Task.CompletedTask).ConfigureAwait(false);
|
|
_charaDataManager.McdfApplyToTarget(target.Name.TextValue);
|
|
}
|
|
|
|
private List<nint> GetHandledAddresses()
|
|
{
|
|
return _activeGameObjectHandlers.Where(g => g.Address != nint.Zero).Select(g => g.Address).Distinct().ToList();
|
|
}
|
|
|
|
private IpcRegister RegisterFunc(string label, Func<List<nint>> handler)
|
|
{
|
|
var provider = _pi.GetIpcProvider<List<nint>>(label);
|
|
provider.RegisterFunc(handler);
|
|
return new IpcRegister(provider.UnregisterFunc);
|
|
}
|
|
|
|
private IpcRegister RegisterFunc<T1, T2, TRet>(string label, Func<T1, T2, TRet> handler)
|
|
{
|
|
var provider = _pi.GetIpcProvider<T1, T2, TRet>(label);
|
|
provider.RegisterFunc(handler);
|
|
return new IpcRegister(provider.UnregisterFunc);
|
|
}
|
|
|
|
private sealed class IpcRegister : IDisposable
|
|
{
|
|
private readonly Action _unregister;
|
|
private bool _disposed;
|
|
|
|
public IpcRegister(Action unregister)
|
|
{
|
|
_unregister = unregister;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_unregister();
|
|
_disposed = true;
|
|
}
|
|
}
|
|
}
|