ICommandBuilder
ICommandBuilder is the basic interface for server-side commands. On startup, Staxel will use the C# class loader to obtain a list of all classes which implement the ICommandBuilder interface. Therefore, no special code is necessary in order to register your command or commands: Simply ensure that each class implements ICommandBuilder, fill out the appropriate methods, and Staxel will handle the rest.
The Methods
-
Kind
is a public string getter which returns a string containing command itself. -
Usage
is a public string getter which returns a string containing translation key for an explanation on how to use the command. This will be displayed when invoking the/help
command. -
Public
is a public bool getter which returns if the command can be used by public users (true) or only administrators (false). -
Execute
is a public method which will execute the action of the command itself. It is passed the command string pre-broken into an array of tokens based on using space as a delimiter, the DataPacket data blob itself, the current ClientServerConnection, and the ICommandsApi interface. It is expected to return a string containing the translation key for the response text to print to the console, as well as to initialize an array of strings in the event that the localized response contains one or more parameters to fill in at run-time. In the event that no parameters are needed, this array should be initialized to a 0-length array of objects.
Example: Echo Command
One of the most basic things that one can do is implement a command which simply echoes back what was typed to the user who invoked the command. Here is the code to do exactly that:
using Plukit.Base; using Staxel.Commands; using Staxel.Server; namespace SampleCommands { internal class EchoCommand : ICommandBuilder { public string Kind => "echo"; public string Usage => "mods.sampleCommands.echo.description"; public bool Public => true; public string Execute(string[] bits, Blob blob, ClientServerConnection connection, ICommandsApi api, out object[] responseParams) { responseParams = new object[1]; string concatenatedBits = ""; for (int i = 1; i < bits.Length; i++) { concatenatedBits += bits[i]; if (i < (bits.Length - 1)) concatenatedBits += " "; } responseParams[0] = concatenatedBits; return "mods.sampleCommands.echo.response"; } } }
Likewise, here is the corresponding .lang file:
language.code=en-GB language=English mods.sampleCommands.echo.description=^c:F2E200;echo ^c:FFFFFF;(optional)parameters mods.sampleCommands.echo.response=You wrote: {0-bits}
As the code implies, the first token in the bits
array is always the command itself. Thus, the processing of command parameters should always begin with the second item in the array (index 1).
In this example, we simply concatenate each command parameter, inserting a space after each parameter except for the last one. Since the response has one string replacement, we initialize responseParams
to a string array of length 1, and store the concatenated string there. Lastly, since the command cannot fail, we always return the response translation key.
Here is a screenshot of the results of the above command:
Example: isOnline Command
One of the basic features of the ICommandsApi
API is the ability to look up an Entity by its ID. In this case, a player Entity is the player's username. This function is, aptly enough, called FindPlayerEntityId
. It accepts a string as its only parameter, and returns an Entity instance if successful, or Null if not.
Using this knowledge as well as the previous example, we can write a simple command to check if a player is online:
using Plukit.Base; using Staxel.Commands; using Staxel.Server; namespace SampleCommands { internal class EchoCommand : ICommandBuilder { public string Kind => "isOnline"; public string Usage => "mods.sampleCommands.isOnline.description"; public bool Public => true; public string Execute(string[] bits, Blob blob, ClientServerConnection connection, ICommandsApi api, out object[] responseParams) { // Perform basic validation of our parameters. if (bits.Length < 2 || bits.Length > 2) { responseParams = new object[0]; return "mods.sampleCommands.isOnline.description"; } responseParams = new object[1]; // We're going to have one replacement parameter in our translation key. responseParams[0] = bits[1]; // Copy the username into the replacement parameter. EntityId id = api.FindPlayerEntityId(bits[1]); // Attempt to find the player. if (id.IsNull()) { // If we were not able to look up an Entity by that ID, the player is not connected. return "mods.sampleCommands.isOnline.playerIsOffline"; } else { // Otherwise, the player is connected. return "mods.sampleCommands.isOnline.playerIsOnline"; } } } }
Here is the updated .lang file, containing the translation keys for both the "echo" command as well as our new "isOnline" command:
language.code=en-GB language=English mods.sampleCommands.echo.description=^c:F2E200;echo ^c:FFFFFF;(optional)parameters mods.sampleCommands.echo.response=You wrote: {0-bits} mods.sampleCommands.isOnline.description=^c:F2E200;isOnline ^c:FFFFFF;player mods.sampleCommands.isOnline.playerIsOnline={0-player} is connected. mods.sampleCommands.isOnline.playerIsOffline={0-player} is not connected.
Lastly, here is a screenshot of our new command in action - in particular, it demonstrates the ability to handle a username with spaces, as long as it is enclosed in quotes: