Commands
Details about basic command usage
Introduction
Commands allow administrators and players to invoke methods upon command by integrating with command-line and chat interfaces available in various games.
Writing commands
A simple command is a method annotated with a Command attribute that accepts at least two objects that implement the IPlayer and IArgs interfaces respectively.
[Command("test")]
private void TestCommand(IPlayer player, IArgs args)
{
player.Reply("Test successful!");
}
Input:
/test
Output:Test successful!
Named arguments
Add named arguments to define minimum input expectations and make command validation easier.
[Command("poke {player}")]
private void PokeCommand(IPlayer player, IArgs args, IPlayerManager players)
{
// Check if required parameter is specified
if (args.IsValid)
{
// Find a player matching that name or ID
IPlayer target = players.FindPlayer(args.GetString("player"), PlayerFilter.Connected);
if (target != null)
{
// Poke player
target.Message($"{player.Name} poked you!");
}
else
{
player.Reply("No player found.");
}
}
else
{
player.Reply("Invalid syntax: /poke {player}");
}
}
The last parameter players in the above example is optional in command signatures. But If specified, a game-specific player manager is provided at run-time by the service container. In this case, the IPlayerManager implementation
Named arguments may be specified as optional or with a default value
// Optional argument
[Command("poke {player?}")]
// Optional argument with default value
[Command("poke {player=Calytic}")]
Although a command that has only optional arguments will always be considered valid, the HasArgument method may be used to determine if the argument was provided.
if (args.HasArgument("player"))
{
// do something with the argument
}
Furthermore, if a default value is provided, this may checked with the IsDefault method...
if (args.IsDefault("player"))
{
// we have a default argument
}
Argument arrays
An argument array is an input parameter that takes a variable number of arguments much like the params keyword in C#.
[Command("message {player} {message*}")]
private void MessageCommand(IPlayer player, IArgs args, IPlayerManager players)
{
// Check if required parameter is specified
if (args.IsValid)
{
// Find a player matching that name or ID
IPlayer target = players.FindPlayer(args.GetString("player"), PlayerFilter.Connected);
if (target != null)
{
// Combine message parameters
string message = args.GetArgument<string>("message");
// Send message
target.Message($"{player.Name} messaged you: {message}");
}
else
{
player.Reply("No player found.");
}
}
else
{
player.Reply("Invalid syntax: /message {player} {message}");
}
}
Argument arrays may be specified as optional
// Optional argument array
[Command("message {player} {message?*}")]
Argument arrays may be obtained as an array of strings or as a combined string.
string message = args.GetArgument<string>("message");
string[] message = args.GetArgument<string[]>("message");
Permissions
The Permission attribute allows command usage to be easily restricted to players who are granted a particular permission.
[Command("test"), Permission("epicstuff.use")]
private void TestCommand(IPlayer player, IArgs args)
{
player.Reply("Test successful!");
}
Permission attributes will be registered and authorized with the plugin prefix automatically prepended if it is not explicitly specified.
Both of the following permission annotations are essentially identical, assuming the plugin is named EpicStuff.
Permission("epicstuff.use")
Permission("use")
Localization
Command names may be specified in English but it is recommended to localize a command by annotating the command method with the Locale or Lang attribute.
Consider the Localization documentation for general information regarding localization options.
Locale
Commands can be localized by annotating the command method with a [Locale] attribute and specifying the name of the locale property as the command name in the [Command] attribute.
[Localization]
interface IPluginLocale : ILocale
{
string PokeCommand { get; }
string PokeReply { get; }
}
[Locale] // English
class Default : IPluginLocale
{
public string PokeCommand { get; } = "poke";
public string PokeReply { get; } = "Poking {player}";
}
[Locale("it")] // Italian
class ITDefault : IPluginLocale
{
public string PokeCommand { get; } = "colpire";
public string PokeReply { get; } = "Frugando {player}";
}
[Command("PokeCommand {player}")]
[Locale(typeof(IPluginLocale))]
private void PokeCommand(IPlayer player, IArgs args)
{
if(args.IsValid)
{
player.Reply(
_<IPluginLocale>(player).PokeReply.Interpolate(("player", player.Name))
);
}
else
{
// Invalid syntax
}
}
Execute the above command method using either command:
/poke Calytic
/colpire Calytic
Nested Locale Object
Localization variables that are nested within a sub-class can be accessed using the . dot notation (e.g. [Command("MyCommand.Name")].
class MyCommandInfo
{
public string Name { get; set; }
}
[Localization]
interface IPluginLocale : ILocale
{
MyCommandInfo MyCommand { get; }
}
[Locale]
class Default : IPluginLocale
{
public MyCommandInfo MyCommand { get; } = new MyCommandInfo()
{
Name = "my_command"
};
}
[Locale("fr")]
class FRDefault : IPluginLocale
{
public MyCommandInfo MyCommand { get; } = new MyCommandInfo()
{
Name = "ma_commande"
};
}
[Command("MyCommand.Name")]
[Locale(typeof(IPluginLocale))]
private void TestCommand(IPlayer player, IArgs args)
{
player.Reply("Test successful!");
}
Lang
Commands can be localized by annotating the command method with a [Lang] attribute and specifying the key from the language dictionary as the command name in the [Command] attribute.
private new void LoadDefaultMessages()
{
Lang.RegisterMessages (new Dictionary<string, string>
{
{"MyCommand", "my_command"}
});
Lang.RegisterMessages (new Dictionary<string, string>
{
{"MyCommand", "ma_commande"}
}, "fr");
}
[Command("MyCommand")]
[Lang]
private void TestCommand(IPlayer player, IArgs args)
{
player.Reply("Test successful!");
}
Execute the above command method using either of the following commands:
/my_command
/ma_commande
The pattern requires that the command name matches the key of the Lang message, in this case MyCommand.
Description and Help
Command description and help information can localized by defining both as properties in the locale interface and annotating the command method with the [Description] and [Help] attributes.
[Localization]
interface IPluginLocale : ILocale
{
string MyCommand { get; }
string MyCommandDescription { get; }
string MyCommandHelp { get; }
}
[Locale]
class Default : IPluginLocale
{
public string MyCommand { get; } = "my_command";
public string MyCommandDescription { get; } = "My command description";
public string MyCommandHelp { get; } = "/my_command";
}
[Locale("fr")]
class FRDefault : IPluginLocale
{
public string MyCommand { get; } = "ma_commande";
public string MyCommandDescription { get; } = "Ma description de commande";
public string MyCommandHelp { get; } = "/ma_commande";
}
The command below is a naive example because it will never be invalid (because it does not have any arguments). However, if it were invalid, then the description and help information would be sent to the player.
[Command("MyCommand")]
[Locale(typeof(IPluginLocale))]
[Description("MyCommandDescription")]
[Help("MyCommandHelp")]
private void TestCommand(IPlayer player, IArgs args, ICommandInfo info)
{
if (args.IsValid)
{
player.Reply("Test successful!");
}
else
{
player.Reply(info.GetDescription(player.Language.TwoLetterISOLanguageName));
player.Reply(info.GetHelp(player.Language.TwoLetterISOLanguageName));
}
}