Cross-Plugin communication and more

As a plugin developer, there are certain features which I feel plugins are lacking. One of these features is cross-plugin communication. The ability for plugins to talk to one another and expose methods for others to use. In this thread I will go into detail about how this could be implemented, as well as some other, quality-of-life features.

Plugin communication is useful for many things. Applications might include:

  • Searching a for a specific asset in the toolbox.
  • Registering custom selectors which building tools can use.

Firstly, I wish to identify the types of plugins that exist.

  • Standard: These are plugins which you install from the website.
  • BuiltIn: These are plugins which are automatically installed with Roblox Studio.
  • Local: These are plugins which exist within the Roblox installation folder.

Enum

PluginType

To distinguish between different types of plugin, we would add the PluginType enum. Its members refer to the descriptions I have given above.

  1. Standard
  2. BuiltIn
  3. Local

PluginService

A new service would be introduced to support these features. The service would allow plugins to interact with one another as well as perform other, plugin specific, actions. It would supersede PluginManager.

array<dictionary> GetInstalledPlugins()

This method would return a list of all installed plugins and their states. The format of each dictionary in the array would be the following.

bool Active: True if the plugin is enabled.
int PluginId: The ID of the plugin, or -1 if its PluginType is not Standard.
string PluginName: The name of the plugin if it is BuiltIn or Local, otherwise an empty string.
Enum.PluginType PluginType: The type of the plugin.

Tuple InvokePlugin(int pluginId, string methodName, … args)

Much like the invoke method found on the BindableFunction instance, this would invoke a method which a plugin has registered. This method is intentionally on PluginService in-case a plugin reloads or unloads at run-time (otherwise, plugins might hold onto references when they should not). If the method does not exist, this method will error.

Tuple InvokeBuiltInPlugin(string pluginName, string methodName, … args)

Does the exact same as InvokePlugin, except it is designed for the BuiltIn plugin type.

Tuple InvokeLocalPlugin(string pluginName, string methodName, … args)

Does the exact same as InvokePlugin, except it is designed for the Local plugin type.

Plugin

int PluginId

Knowing the ID of your plugin can actually be very useful. Right now we need to hard-code it into our source, but ideally it could just be a member of the plugin itself.

With this the following becomes much easier:

  • MarketplaceService can be used to retrieve information about the package. Developers might use the description for a changelog.
  • If a new version of the plugin is available, it can be updated automatically through InsertService.
  • The plugin can distinguish itself from other plugins when creating instances that will be saved to a place-file. A common example of this is per-place plugin settings.

Of course, there are cases where plugins may not have an ID, in which case the ID would be set to -1.

void OnInvoke(string methodName, function<… args> callback)

This would set the function which is invoked by InvokePlugin, InvokeBuiltInPlugin, and InvokeLocalPlugin.

18 Likes