Commands
SwiftlyS2 provides a comprehensive command system that allows you to register custom commands, handle player chat and commands, and manage command permissions. Commands can be registered using attributes or programmatically.
Registering Commands
Commands can be registered with various modes:
With Attributes
This is one of the simplest ways to register commands. You just attach the [Command] attribute to a function with a specific signature.
[Command("heal")]
public void OnHealCommand(ICommandContext context)
{
if (!context.IsSentByPlayer)
{
context.Reply("This command can only be used by players!");
return;
}
var player = context.Sender!;
// ...
}The command attribute has the following properties:
name(string): This attribute represents the command nameregisterRaw(boolean, optional): This attributes enables the registration of commands in raw mode. If this mode is enabled, thesw_prefix is not added to the command.permission(string, optional): This attribute sets a permission check which is done internally.
[Command("heal", false, "admins.commands.heal")]
// the command heal will be registered as `sw_heal` and have permission check for `admins.commands.heal`The methods need to follow the following signature:
void CommandListenerFunction( ICommandContext context );Programatically
You can also register commands programmatically using Core.Command service.
public override void Load()
{
var commandGUID = Core.Command.RegisterCommand("heal", OnHealCommand);
}The function RegisterCommand returns a unique GUID to keep track of the command and, later on in code, remove the command from being registered.
It has the same features as the attribute, and the function signature is the following:
/// <summary>
/// The listener for the command.
/// </summary>
/// <param name="context">The command context.</param>
public delegate void CommandListener( ICommandContext context );
/// <summary>
/// Registers a command.
/// </summary>
/// <param name="commandName">The command name.</param>
/// <param name="handler">The handler callback for the command.</param>
/// <param name="registerRaw">If set to true, the command will not starts with a `sw_` prefix.</param>
/// <param name="permission">The permission required to use the command.</param>
/// <returns>The guid of the command.</returns>
Guid RegisterCommand(string commandName, CommandListener handler, bool registerRaw = false, string permission = "");The function passed in the handler argument needs to have the signature of the CommandListener delegate.
Unregistering commands
Commands are automatically being unregistered when a plugin stops. This is to ensure that there will be no edge cases.
However, if you want to manually unregister a command, you need to call UnregisterCommand from Core.Command.
/// <summary>
/// Unregisters a command.
/// </summary>
/// <param name="guid">The guid of the command.</param>
public void UnregisterCommand( Guid guid );
/// <summary>
/// Unregisters all command listeners with the specified command name.
/// </summary>
/// <param name="commandName">The command name.</param>
public void UnregisterCommand( string commandName );Command Aliases
Command aliases are acting as a way to register the same handler for multiple command names.
With Attributes
For this to work, obviously, the command needs to be registered with Command attribute.
[Command("heal")]
[CommandAlias("hp")]
public void OnHealCommand(ICommandContext context)
{
// Can be called with: `sw_heal` and `sw_hp`
}Aliases attribute has the following properties:
alias(string): The alias nameregisterRaw(boolean, optional): This attributes enables the registration of commands in raw mode. If this mode is enabled, thesw_prefix is not added to the alias.
Programatically
You can also register asliases programmatically using Core.Command service.
public override void Load()
{
Core.Command.RegisterCommandAlias("heal", "hp");
}The function RegisterCommandAlias has the same features as the attribute:
/// <summary>
/// Registers a command alias.
/// </summary>
/// <param name="commandName">The command name.</param>
/// <param name="alias">The alias.</param>
/// <param name="registerRaw">If set to true, the alias will not starts with a `sw_` prefix.</param>
public void RegisterCommandAlias( string commandName, string alias, bool registerRaw = false );Client Command Hooks
Client commands are commands that are registered on server and executed by clients. Those are commands that can be executed via client console (~).
To have the knowledge that we need, let's learn about HookResult. HookResult in an enum created by us to control how the server handles the command.
See HookResult for more details.
With Attributes
To hook client commands via attribute, we need to attach [ClientCommandHookHandler] attribute to a function with a specific signature.
[ClientCommandHookHandler]
public HookResult OnClientCommand(int playerId, string commandLine)
{
if (commandLine.StartsWith("say"))
{
Console.WriteLine($"Player #{playerId} is using say command");
}
return HookResult.Continue;
}ClientCommandHookHandler attribute doesn't have any property to pass.
The methods needd to have the following signature:
HookResult ClientCommandHandlerFunction( int playerId, string commandLine );Programatically
You can also hook client commands using Core.Command service:
public override void Load()
{
var hookGUID = Core.Command.HookClientCommand(OnClientCommand);
}The function HookClientCommand returns a unique GUID to keep track of the hook and, later on in code, remove the hook from being registered.
It has the same features as the attribute, and the function signature is the following:
/// <summary>
/// The handler for the client command hook.
/// </summary>
/// <param name="playerId">The player id.</param>
/// <param name="commandLine">The command line.</param>
/// <returns>Whether the command should continue to be sent.</returns>
public delegate HookResult ClientCommandHandler( int playerId, string commandLine );
/// <summary>
/// Hooks client commands, will be fired when a player sends any command.
/// </summary>
/// <param name="handler">The handler callback for the client command.</param>
public Guid HookClientCommand( ClientCommandHandler handler );
/// <summary>
/// Unhooks a client command.
/// </summary>
/// <param name="guid">The guid of the client command.</param>
public void UnhookClientCommand( Guid guid );The function passed in the handler argument needs to have the signature of the ClientCommandHandler delegate.
Client Chat Hooks
Client chat hooks allows you to block messages from being sent to the player. This is very useful for systems such as words blacklisting, private chats and more.
With Attributes
To hook client chat via attribute, we need to attach [ClientChatHookHandler] attribute to a function with a specific signature.
[ClientChatHookHandler]
public HookResult OnClientChat(int playerId, string text, bool teamonly)
{
if (text.Contains("badword"))
{
Console.WriteLine($"Message blocked for player #{playerId} because it contains a bad word.");
return HookResult.Stop; // Block the message
}
if (teamonly)
{
Console.WriteLine($"Team message from player #{playerId}: {text}");
}
return HookResult.Continue;
}ClientChatHookHandler attribute doesn't have any property to pass.
The methods needd to have the following signature:
HookResult ClientChatHandlerFunction( int playerId, string commandLine );Programatically
You can also hook client commands using Core.Command service:
public override void Load()
{
var hookGUID = Core.Command.HookClientChat(OnClientCommand);
}The function HookClientChat returns a unique GUID to keep track of the hook and, later on in code, remove the hook from being registered.
It has the same features as the attribute, and the function signature is the following:
/// <summary>
/// The handler for the client chat hook.
/// </summary>
/// <param name="playerId">The player id.</param>
/// <param name="text">The text.</param>
/// <param name="teamonly">Whether the text is for team only.</param>
/// <returns>Whether the text should continue to be sent.</returns>
public delegate HookResult ClientChatHandler( int playerId, string text, bool teamonly );
/// <summary>
/// Hooks client chat, will be fired when a player sends any chat message.
/// </summary>
/// <param name="handler">The handler callback for the client chat.</param>
public Guid HookClientChat( ClientChatHandler handler );
/// <summary>
/// Unhooks a client chat.
/// </summary>
/// <param name="guid">The guid of the client chat.</param>
public void UnhookClientChat( Guid guid );The function passed in the handler argument needs to have the signature of the ClientChatHandler delegate.
Reference
See ICommandService and ICommandContext for more details.