using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using MareSynchronos.MareConfiguration; using MareSynchronos.PlayerData.Handlers; using MareSynchronos.Services; using MareSynchronos.Services.Mediator; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace MareSynchronos.Interop.Ipc; public class IpcProvider : IHostedService, IMediatorSubscriber { private readonly ILogger _logger; private readonly IDalamudPluginInterface _pi; private readonly CharaDataManager _charaDataManager; private ICallGateProvider? _loadFileProvider; private ICallGateProvider>? _loadFileAsyncProvider; private ICallGateProvider>? _handledGameAddresses; private readonly List _activeGameObjectHandlers = []; public MareMediator Mediator { get; init; } public IpcProvider(ILogger logger, IDalamudPluginInterface pi, MareConfigService mareConfig, CharaDataManager charaDataManager, MareMediator mareMediator) { _logger = logger; _pi = pi; _charaDataManager = charaDataManager; Mediator = mareMediator; Mediator.Subscribe(this, (msg) => { if (msg.OwnedObject) return; _activeGameObjectHandlers.Add(msg.GameObjectHandler); }); Mediator.Subscribe(this, (msg) => { if (msg.OwnedObject) return; _activeGameObjectHandlers.Remove(msg.GameObjectHandler); }); } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogDebug("Starting IpcProvider Service"); _loadFileProvider = _pi.GetIpcProvider("ClubPenguinSync.LoadMcdf"); _loadFileProvider.RegisterFunc(LoadMcdf); _loadFileAsyncProvider = _pi.GetIpcProvider>("ClubPenguinSync.LoadMcdfAsync"); _loadFileAsyncProvider.RegisterFunc(LoadMcdfAsync); _handledGameAddresses = _pi.GetIpcProvider>("ClubPenguinSync.GetHandledAddresses"); _handledGameAddresses.RegisterFunc(GetHandledAddresses); _logger.LogInformation("Started IpcProviderService"); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogDebug("Stopping IpcProvider Service"); _loadFileProvider?.UnregisterFunc(); _loadFileAsyncProvider?.UnregisterFunc(); _handledGameAddresses?.UnregisterFunc(); Mediator.UnsubscribeAll(this); return Task.CompletedTask; } private async Task 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 GetHandledAddresses() { return _activeGameObjectHandlers.Where(g => g.Address != nint.Zero).Select(g => g.Address).Distinct().ToList(); } }