using System; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Services; namespace QuestionableCompanion.Services; public class MultiClientIPC : IDisposable { private readonly IDalamudPluginInterface pluginInterface; private readonly IPluginLog log; private readonly ICallGateProvider requestHelperProvider; private readonly ICallGateProvider dismissHelperProvider; private readonly ICallGateProvider helperAvailableProvider; private readonly ICallGateProvider chatMessageProvider; private readonly ICallGateProvider passengerMountedProvider; private readonly ICallGateSubscriber requestHelperSubscriber; private readonly ICallGateSubscriber dismissHelperSubscriber; private readonly ICallGateSubscriber helperAvailableSubscriber; private readonly ICallGateSubscriber chatMessageSubscriber; private readonly ICallGateSubscriber passengerMountedSubscriber; public event Action? OnHelperRequested; public event Action? OnHelperDismissed; public event Action? OnHelperAvailable; public event Action? OnChatMessageReceived; public event Action? OnPassengerMounted; public MultiClientIPC(IDalamudPluginInterface pluginInterface, IPluginLog log) { this.pluginInterface = pluginInterface; this.log = log; requestHelperProvider = pluginInterface.GetIpcProvider("QSTCompanion.RequestHelper"); dismissHelperProvider = pluginInterface.GetIpcProvider("QSTCompanion.DismissHelper"); helperAvailableProvider = pluginInterface.GetIpcProvider("QSTCompanion.HelperAvailable"); chatMessageProvider = pluginInterface.GetIpcProvider("QSTCompanion.ChatMessage"); passengerMountedProvider = pluginInterface.GetIpcProvider("QSTCompanion.PassengerMounted"); requestHelperSubscriber = pluginInterface.GetIpcSubscriber("QSTCompanion.RequestHelper"); dismissHelperSubscriber = pluginInterface.GetIpcSubscriber("QSTCompanion.DismissHelper"); helperAvailableSubscriber = pluginInterface.GetIpcSubscriber("QSTCompanion.HelperAvailable"); chatMessageSubscriber = pluginInterface.GetIpcSubscriber("QSTCompanion.ChatMessage"); passengerMountedSubscriber = pluginInterface.GetIpcSubscriber("QSTCompanion.PassengerMounted"); requestHelperProvider.RegisterFunc(delegate(string name, ushort worldId) { OnRequestHelperReceived(name, worldId); return (object?)null; }); dismissHelperProvider.RegisterFunc(delegate { OnDismissHelperReceived(); return (object?)null; }); helperAvailableProvider.RegisterFunc(delegate(string name, ushort worldId) { OnHelperAvailableReceived(name, worldId); return (object?)null; }); chatMessageProvider.RegisterFunc(delegate(string message) { OnChatMessageReceivedInternal(message); return (object?)null; }); passengerMountedProvider.RegisterFunc(delegate(string questerName, ushort questerWorld) { OnPassengerMountedReceived(questerName, questerWorld); return (object?)null; }); log.Information("[MultiClientIPC] ✅ IPC initialized successfully"); } public void RequestHelper(string characterName, ushort worldId) { try { log.Information($"[MultiClientIPC] Broadcasting helper request: {characterName}@{worldId}"); requestHelperSubscriber.InvokeFunc(characterName, worldId); } catch (Exception ex) { log.Error("[MultiClientIPC] Failed to send helper request: " + ex.Message); } } public void DismissHelper() { try { log.Information("[MultiClientIPC] Broadcasting helper dismiss"); dismissHelperSubscriber.InvokeFunc(); } catch (Exception ex) { log.Error("[MultiClientIPC] Failed to send helper dismiss: " + ex.Message); } } private void OnRequestHelperReceived(string characterName, ushort worldId) { try { log.Information($"[MultiClientIPC] Received helper request: {characterName}@{worldId}"); this.OnHelperRequested?.Invoke(characterName, worldId); } catch (Exception ex) { log.Error("[MultiClientIPC] Error handling helper request: " + ex.Message); } } private void OnDismissHelperReceived() { try { log.Information("[MultiClientIPC] Received helper dismiss"); this.OnHelperDismissed?.Invoke(); } catch (Exception ex) { log.Error("[MultiClientIPC] Error handling helper dismiss: " + ex.Message); } } public void AnnounceHelperAvailable(string characterName, ushort worldId) { try { log.Information($"[MultiClientIPC] Broadcasting helper availability: {characterName}@{worldId}"); helperAvailableSubscriber.InvokeFunc(characterName, worldId); } catch (Exception ex) { log.Error("[MultiClientIPC] Failed to announce helper: " + ex.Message); } } private void OnHelperAvailableReceived(string characterName, ushort worldId) { try { log.Information($"[MultiClientIPC] Received helper available: {characterName}@{worldId}"); this.OnHelperAvailable?.Invoke(characterName, worldId); } catch (Exception ex) { log.Error("[MultiClientIPC] Error handling helper available: " + ex.Message); } } public void SendChatMessage(string message) { try { log.Information("[MultiClientIPC] Broadcasting chat message: " + message); chatMessageSubscriber.InvokeFunc(message); } catch (Exception ex) { log.Error("[MultiClientIPC] Failed to send chat message: " + ex.Message); } } private void OnChatMessageReceivedInternal(string message) { try { log.Information("[MultiClientIPC] Received chat message: " + message); this.OnChatMessageReceived?.Invoke(message); } catch (Exception ex) { log.Error("[MultiClientIPC] Error handling chat message: " + ex.Message); } } public void SendPassengerMounted(string questerName, ushort questerWorld) { try { log.Information($"[MultiClientIPC] Broadcasting passenger mounted: {questerName}@{questerWorld}"); passengerMountedSubscriber.InvokeFunc(questerName, questerWorld); } catch (Exception ex) { log.Error("[MultiClientIPC] Failed to send passenger mounted: " + ex.Message); } } private void OnPassengerMountedReceived(string questerName, ushort questerWorld) { try { log.Information($"[MultiClientIPC] Received passenger mounted: {questerName}@{questerWorld}"); this.OnPassengerMounted?.Invoke(questerName, questerWorld); } catch (Exception ex) { log.Error("[MultiClientIPC] Error handling passenger mounted: " + ex.Message); } } public void Dispose() { try { requestHelperProvider.UnregisterFunc(); dismissHelperProvider.UnregisterFunc(); helperAvailableProvider.UnregisterFunc(); chatMessageProvider.UnregisterFunc(); } catch (Exception ex) { log.Error("[MultiClientIPC] Error during dispose: " + ex.Message); } } }