Silent Creating Custom Commands

From MyGamingTalk

What Are Custom Commands

Custom commands are shrubbot like commands that are not implemented by the silEnT mod, but instead by server admins. There are three ways to create custom commands. One is to simply use the [command] blocks in the shrubbot.cfg. Second one is to combine [command] block with a Lua script that will do more complicated work than what just the rcon can do. And the third method is to implement everything with Lua. The following sections describe each of these methods.

Shrubbot.cfg Method

The shrubbot.cfg file on your server can include following blocks:

   [command]
   command  = The name of the command.
   exec     = The executed command. These must be commands available to /rcon and these will be executed with rcon privileges.
   desc     = The help description of the command.
   syntax   = List of parameters if the command uses them. This is used with !help and it is optional.
   levels   = Space separated list of levels that are allowed to use the command.

These commands appear in the !help output just as if they were implemented by the silEnT mod itself. Also, !help <command name> can be used to see detailed help about the commands. The exec line defines the commands that will be executed by the mod. The exec field supports the following:

  • The commands can be anything that can be executed with /rcon.
  • The commands can use all shortcuts that players can use with their chat messages.
  • Additional shortcut [i] is available. This will be replaced with the client slot number of the player who called the command. If the command was called from the server console, or /rcon, this shortcut will not be replaced.
  • The shrubbot custom commands support parameter place holders. These are [1] - [9], where the number is the n:th parameter given to the custom command. When these are used, the server will substitute the placeholder with the n:th parameter given to the command.
  • There is also the possibility to add ? to the parameter placeholders. If the question mark is added, the parameter is substituted with a player name if only one name matches the pattern. If there are no matches or there are several matches, the command will fail and reports an informative error. All placeholders can have the question mark if that is needed for the command.

Example

   [command]
   command  = crybaby
   exec     = playsound path/to/sound.wav; chat ^7[1?]^7 is crying like a little baby!
   desc     = Make someone cry like a baby
   syntax   = [name]
   levels   = 0 1 2 3 4 5
   [command]
   command  = takess
   exec     = pb_sv_getss [1]
   desc     = Send pb SS of player to server. Use /pb_plist & type !takess PB slot number.
   syntax   = 
   levels   = 5
   [command]
   command  = omnifix
   exec     = bot kickall
   desc     = To kick all bots if their are more then 5 vs 5 players playing.
   syntax   = 
   levels   = 21 

Note:

If the command breaks because the name that substitutes a placeholder has spaces, use " characters to surround the placeholder. Like this "[1?]". It will ensure that the full name is parsed as one parameter instead of getting interpreted as separate parameters.

Combining shrubbot.cfg and Lua Scripts

One method to extend what the commands can do, is to use a Lua script to implement the actual command operation. To do this, create a custom command to the shrubbot.cfg, which executes a command, that is not recognized by the silEnT mod. Such commands will pass through to the et_ConsoleCommand Lua callback. Where it can be intercepted and proper actions can be taken. The advantage of this method is that the command privileges and the help are handled by the silEnT mod. This includes the Admin Level Protection. In other words, it is easy to ensure that the command is not used by unwanted persons.

Example

For the purposes of this example, the command is mycommand. It will be executed when the user enters !mycommand to the console, assuming that player has been assigned level 2 or higher shrubbot level.

1. Create your command in the shrubbot file. Open your shrubbot.cfg file (in silent\database directory) and add the following block:

   [command]
   command  = mycommand
   exec     = mycommand_lua [i]
   desc     = Does something cool for people over level 2
   syntax   = 
   levels   = 2 3 4 5

Note: Be careful with the called command. If the command that is directed to Lua, and the custom command in shrubbot.cfg have the same name, an infinite loop can form if the Lua script does not return 1. This can happen because if the command is not handled by the Lua script, it will again get handled as a shrubbot custom command.

2. Create a LUA file in your silent directory on the server. Call it mycommand.lua (or whatever name you want to give it). Begin with the following stub:

   function et_ConsoleCommand(command)

        -- if the user types !mycommand in the console

        if et.trap_Argv(0) == "mycommand_lua" then

            -- Do your custom processing here

            local clientNum = et.trap_Argv(1)
            et.trap_SendServerCommand(clientNum, "chat \"Your command "..et.trap_Argv(0).." has been received\"")

            return 1 -- Tells silEnT that this script handled this command
        end

        return 0  -- Tells silEnT that this script did not handle this command
    end

3. Update your server config to load the LUA file. Add or modify the following server var (lua_modules):

   set lua_modules "mycommand.lua"

4. Restart your server. Assuming you are on a shrubbot level 2 or higher, !mycommand will execute and do cool stuff.

Only With Lua

Some servers use quite large and complicated additional command implementations that are implemented entirely by Lua scripting. This is not the recommended method to do admin systems, unless you have a pressing need for this.

Example

   
function SplitToArguments(line)
    local array = {}
    local aindex = 0
    for i in string.gmatch(line, "%S+") do
        array[aindex] = string.lower(i)
	aindex = aindex + 1
    end

    return array
end

function CheckCommand(clientNum, arguments)
    if( arguments[0] == "!mycommand" ) then
	et.trap_SendServerCommand(clientNum, "chat \"Your command "..arguments[0].." has been received\"")
	return 1
    end

    return 0
end

function et_ClientCommand(clientNum, command)
    local level = et.G_shrubbot_level(clientNum)
    local flood = et.ClientIsFlooding(clientNum)

    -- we're not interested if the level is too low or if the client is flooding
    if (level < 1) or (flood == 1) then
        return 0
    end
	
    local arg0 = string.lower(et.trap_Argv(0))
    local arguments

    -- check to see if the command was given through any of the chat methods or as sparse text from the console
    if arg0 == "say" or arg0 == "say_team" or arg0 == "say_buddy" or arg0 == "say_teamnl" then
	arguments = SplitToArguments(et.trap_Argv(1))
    else
	arguments = SplitToArguments(et.ConcatArgs(0))
    end

    -- actual command handling
    return CheckCommand(clientNum, arguments)
end

This example shows the same functionality as the combined example above. Do note, that if the full admin system is made manually, handling the command arguments require special care. In the above example it shows how the arguments are handled differently depending if the script is handling player chatting, or if the commands are read from sparse texts that players write to console. For safety, ConcatArgs could be used for both, just in case there are bugs in the silEnT implementation, but splitting the single argument should work equally well in all cases.