An extensible MUSH / MUD server written in Java.
Extensions can call plugins to implement plugin commands and listener attributes. First learn about how extensions work before getting into the reference details here about what plugins can do.
A plugin command is a Grounds command that is implemented with a plugin. It is defined by an extension attribute whose name starts with $
. The value of the attribute is a list with the following supported attributes.
Name | Type | Purpose |
---|---|---|
pluginPath | STRING | (required) Path to the plugin executable |
pluginMethod | STRING | (required) JSON RPC request method |
callerRoles | STRING | Comma-separated list of permitted roles for callers (default is all non-guest roles) |
commandHelp | ATTRLIST | Plugin command help |
The optional “commandHelp” attribute provides help text for the command. When this attribute is present, a player can run the HELP command to see the help text for the command.
The commandHelp attribute itself is an attribute list, and should contain the following three string attributes.
Name | Purpose | Example |
---|---|---|
syntax | Syntax definition | $COINFLIP |
summary | One-line summary of the command | Flips a coin |
description | Main help documentation; may be multiple paragraphs | The outcome of the flip is posed by the command in the caller's name. |
Grounds and plugins communicate using JSON RPC 2.0. Grounds calls a plugin by running it and supplying a JSON RPC request to it on standard input.
The request method is whatever was specified for the plugin command. A plugin may use this to support multiple plugin commands, one per method.
The request ID is a random value. The JSON RPC response emitted by the plugin must use the matching ID to be valid.
The request params sent by Grounds is a JSON object with the following fields.
Name | Type | Purpose |
---|---|---|
_extension_id | string | thing ID of the extension for the plugin command |
_plugin_call_arguments | array of strings | arguments to the command supplied by the player in their shell |
_plugin_call_id | string | Unique identifier for this call to the plugin |
Internally, Grounds keeps track of context about every call to a plugin, like who the executing actor and player are. When a plugin calls back to the Grounds API, it has to supply its plugin call ID so that Grounds can retrieve that context and satisfy the API call.
When a listener attribute responds to an event, it actually runs a plugin command. It’s worth noting here that the calling actor for the plugin is a built-in “internal” actor with no roles, and the calling player is the extension where the listener attribute resides.
Any arguments which a player supplies in their shell when executing a plugin command are passed along. Special arguments like “me” and “here” are resolved before being supplied to the plugin command.
The player executing a plugin command must have USE permission for the extension where the command resides. This check can be used to define commands that are only accessible to particular player roles.
Plugins themselves are free to implement their own additional permission checks, such as requiring particular player locations, a certain time of day, and so on.
When a plugin is finished, it must write a JSON RPC response on its standard output. The response is consumed by Grounds. In all cases, the response ID must match the request ID.
If the plugin’s execution is considered successful, then the response must provide a string result and no error. It’s fine for a plugin to return an empty string. If the string is non-empty, it is emitted to the calling player.
If the plugin’s execution is considered a failure, then the response must provide an error and no result. Any standard JSON RPC error code is acceptable. Grounds defines the following additional error codes.
Value | Meaning |
---|---|
-32004 | Not Found |
If an error message is provided, it is emitted to the calling player.
A plugin should use attributes in its extension to store its state. For example, an extension representing a switch to be flipped on and off may use an attribute to represent the current switch position. (This could also be an attribute on a proxy object representing the switch in game.) It may also keep a record of who last flipped the switch in a separate attribute.
The _extension_id
request param makes it easy to work with extension attributes.
While a simple plugin can work just from what it receives in requests, more complex plugins need to gather information about the universe and make changes to it. The Grounds API is a limited interface for doing just that.