Expose functionality to other plugins using IPC providers
CallGate providers allow your plugin to expose functions and send notifications to other plugins. This enables your plugin to become a platform that others can build upon.
public interface ICallGateProvider{ /// <summary> /// Number of subscribers listening for messages through this gate. /// </summary> int SubscriptionCount { get; }}
// Register an action (no return value)void RegisterAction(Action<T1, T2, ...> action);// Register a function (with return value)void RegisterFunc(Func<T1, T2, ..., TRet> func);// Send notification to all subscribersvoid SendMessage(T1 arg1, T2 arg2, ...);// Unregister the action or functionvoid UnregisterAction();void UnregisterFunc();// Get information about the calling pluginIpcContext? GetContext();
if (this.statusProvider.SubscriptionCount > 0){ // Only compute expensive data if someone is listening var data = ComputeExpensiveData(); this.statusProvider.SendMessage(data);}
public class IpcContext{ /// <summary> /// The plugin that initiated this IPC call. /// </summary> public IExposedPlugin? SourcePlugin { get; }}public interface IExposedPlugin{ string Name { get; } // Display name string InternalName { get; } // Unique identifier Version Version { get; } // Plugin version // ... other properties}
Exceptions thrown by providers are propagated to subscribers:
this.provider.RegisterFunc(input =>{ if (string.IsNullOrEmpty(input)) { throw new ArgumentException("Input cannot be empty"); } return ProcessInput(input);});
The subscriber will receive this exception when calling InvokeFunc.
/// <summary>/// IPC API: "MyPlugin.GetCharacterName"/// Gets the current player's character name./// </summary>/// <returns>Character name, or null if not logged in.</returns>public string? GetCharacterName() { ... }
// Old API (deprecated but still supported)var oldProvider = pluginInterface.GetIpcProvider<string>( "MyPlugin.GetData");// New API with different signaturevar newProvider = pluginInterface.GetIpcProvider<string, int>( "MyPlugin.GetData.v2");
// Good: Event notificationthis.eventProvider.SendMessage("ConfigChanged");// Bad: Using notifications for queriesthis.queryProvider.SendMessage("GetConfig"); // Use RegisterFunc instead!