You are viewing an older version of the site. Click here to view
the latest version of this page. (This may be a dead link, if so, try the root page of the docs
here.)
If you are wanting to do more dynamic things other than variables, CommandHelper allows you to do this through the
use of Turing complete language, MethodScript. If you aren't familiar with any type of programming, you may wish to
find resources on languages like Java and PHP. The language mirrors both languages in certain ways, as well as
introducing its own methodologies.
===Functions===
Functions allow for very dynamic scripts to be run. There are many defined functions, including functions that provide
control flow functionality. For the full list of functions, see the [[API]]. A function is identified
by a literal string, followed by parenthesis. So in
Copy Code
===Comments===
Comments are a useful way to mark up your code for humans to read later. (With one exception) comments are ignored
by the compiler, and you are free to put whatever information you wish in a comment. There are 4 ways to comment
code.
The
Copy Code
===Data Types===
In a script, there are several types of data. The language is currently loosely typed however, so the string '2' is
equivalent to the integer 2, is equivalent to the double 2.0, is equivalent to the boolean true. Values are cast just
before they are used. Note that sometimes data cannot be cast, for instance the string 'string' cannot be cast to a
number, so a runtime exception will be thrown if a function expects a number, and is given that. Also, arrays are not
able to be cast into other data types, but can contain values of any data type.
* boolean - Created with the "true" or "false" keywords: true
* int - Any number that doesn't have a decimal point: 2
* double - Any number that has a decimal point: 2.0
* string - Any set of characters surrounded by single quotes or double quotes: 'string', "also a string".
\u0000 inside a string will allow for arbitrary unicode characters to be inserted into a string, and \n is a newline.
\\ (double slash) inserts a literal slash, and \' will insert a literal quote.
* array - An array of any other datatypes, including other arrays. Created by using the function
Copy Code
the
Copy Code
In main.ms:
Copy Code
In aliases.msa:
Copy Code
Here, we have created 3 separate execution units. main.ms and aliases are implicitly created, simply by their existence,
but here we have also created an event handler, which will get run when some_event is triggered. main.ms is triggered
upon server startup (and /reloadaliases) and aliases are triggered when a command is run. When this script is compiled,
you can essentially visualize the execution units as ending up like this: (with some code removed to make things more
readable)
First execution unit, main.ms:
Copy Code
Second execution unit, the /test $alias alias:
Copy Code
Third execution unit, the event handler created in main.ms:
Copy Code
In this simple example, you can think of each execution path as a line through your code (in reality, it's a tree, but
if that doesn't make sense to you, ignore that for now). That line follows very specific rules based on code structure,
so how you lay out your code is important to be able to visualize.
=== recompile ===
The built in
Copy Code
===Symbol Table===
In your scripts, there are a few special symbols that are not treated as literals. In the event of a compiler error,
it may be helpful to know what each symbol is called. These are as follows:
{| class="wikitable" border="1"
|-
! width="15%" | Symbol
! width="30%" | Name
! width="55%" | Meaning
|-
| # or //
| comment
| Denotes that the rest of this line is a comment
|-
| /* ... */
| block comment
| Everything inside this (newlines included) is a comment. The only thing you can't have inside a block comment is a */
(because that ends the comment)
|-
| =
| opt_var_assign or alias_end
| If inside an optional variable [$opt='val'], it's an opt_var_assign. Otherwise, it's a alias_end
|-
| [ and ]
| lsquare_bracket and rsquare_bracket
| Denotes that this variable is optional, if included on the left side of an alias, or accesses an element in an array
if used on the right.
|-
| ,
| comma
| Separates arguments in a function
|-
| ( and )
| func_start and func_end
| The start and end of a function. If a literal proceeds the func_start symbol, it is called func_name
|-
| New Line
| newline
| An 'enter' in the file
|-
| >>> and <<<
| multiline_start and multiline_end
| Starts and stops a multiline construct
|-
| /
| command
| This symbol followed by a literal denotes a command
|-
| \
| separator
| Separates each macro command
|-
| $...
| variable
| When a single dollar sign, it is final_var, otherwise variable
|-
| @...
| ivariable
| This is a variable that can be defined and used on the right side of an alias
|-
| ...:
| label
| This is a label for commands
|-
| All other characters
| lit
| Anything not defined above is a lit
|}
{{TakeNote|text=
In general, autoconcatenation should not be relied on. It is better to use the
Copy Code
In the first run function, we see that '/run', 'this', and 'command' are all technically separate arguments, but because
they are not separated by commas, operators, or other symbols, they are automatically concatenated together, using the
{{function|sconcat}} function, essentially yeilding: '/run this command', as you would expect. This is also the
behavior exhibited by a simple alias that uses non-strict formatting:
Copy Code
auto_include.ms:
Copy Code
commands.msa:
Copy Code
We can make a slightly less accurate version of this code, which uses the defaults, which, while less correct,
provides a decent compromise between functionality and code terseness.
Copy Code
This example will still provide tab completions for the enum and player arguments, but the list of players will not
be filtered based on the value of the enum. The usage example will be less meaningful as well, but may be good enough
in most cases.
func()
, "func" is the name of the function, and "("
and ")" begin and end the function argument list (in this case, there are no arguments being passed in.) Functions
can have zero, one, or two or more arguments passed to them. In the case of two or more arguments, each argument
is separated by a comma. For instance:
funcWithNoArgs();
funcWithOneArg(1);
funcWithTwoArgs(1, 2);
funcWithThreeArgs(1, 2, 3);

1 {{function|funcWithNoArgs}}();
2 {{function|funcWithOneArg}}(1);
3 {{function|funcWithTwoArgs}}(1, 2);
4 {{function|funcWithThreeArgs}}(1, 2, 3);
#
and //
symbols are identical. They are line comments. When either is encountered,
the remainder of the line is ignored by the compiler. //
is preferred over #
, however
#
is not deprecated, nor will it ever be. The only exception to this preference is when using a
hashbang for cmdline code.
Block comments start with /*
and end with */
This causes the compiler to ignore everything
within the comment block, including newlines.
Smart comments are like block comments, but start with /**
(two asterisks) instead. See the article
on [[SmartComments]] for more details about the format in general, and below for information specific to aliases.
code(); # line comment
code(); // line comment
code();
/*
*
* block comment
*
*/
/**
* Smart comment. This would generally proceed a procedure or variable declaration,
* or similar structure. Note that the * at the beginning of this line is not necessary,
* however it serves to help the reader more easily see that this is also part of the comment block.
*/

01 {{function|code}}(); # line comment
02
03 {{function|code}}(); // line comment
04
05 {{function|code}}();
06 /*
07 *
08 * block comment
09 *
10 */
11
12
13 /** * Smart comment. This would generally proceed a procedure or variable declaration, * or similar structure. Note that the * at the beginning of this line is not necessary, * however it serves to help the reader more easily see that this is also part of the comment block. */
array
* null - Created with the "null" keyword: null
* void - Some functions return void, which is actually a datatype. When viewed as a string, it is equivalent to an
empty string. Cannot be created directly.
* ivariable - An ivariable (or simply a variable) is a variable that can be defined and used from within the script.
Constant variables ($var), are assigned by the user at command runtime, and are technically constants as far as the
rest of the script is concerned. IVariables can be defined by the script writer and assigned various values that can
change throughout the script running. To define and use an ivariable, use the assign() function, or the = operator.
If an ivariable is used without first being defined, the value of the variable will be 0, 0.0, '',
false, or null, depending on how it is used. Most functions use the value in the ivariable without caring that it is
an ivariable, but it is possible that a function requires that a certain argument be an ivariable, such as the for()
function.
===Exception Handling===
Sometimes a script may sometimes cause an error that could be anticipated. Instead of just having the script die, it is
possible to catch these errors, and perform alternate functionality. MethodScript mirrors the functionality of languages
like PHP and Java with exception handling. For more information about exception handling in MScript, see
[[Exceptions|this page]]. For a more general discussion on exception handling, see
[http://en.wikipedia.org/wiki/Exception_handling this page] on Wikipedia.
=== main.ms, auto_include.ms, and aliases.msa ===
Each of these files serve a separate purpose. main.ms is run at server startup, only once. Typically, you use this to
register bound events, using the bind() function, or anything else you want to run only once. Keep in mind, this is
re-run when you /reloadaliases, but bound events and intervals and such are stopped, so you won't have multiples of
anything. main.ms uses '''pure MethodScript''', that is, it has a slightly different syntax than aliases.msa. In aliases.msa,
each alias is defined, along with a snippet of MethodScript. For instance, in the alias,
/test [$command=''] = >>>
console($command);
<<<

1 /test [$command=''] = >>>
2 {{function|console}}($command);
3 <<<
/test [$command=''] = >>> <<<
part is the alias markup, and is not actual MethodScript,
that is, the symbols and characters follow different meanings than inside the alias definition. In this example,
console($command);
is pure MethodScript.
aliases.msa is where your aliases go, and each alias is a fully separate '''compilation unit''', in fact, even a compile
error in one alias will not usually interfere with the other aliases.
The auto_include.ms file is also a pure MethodScript file, and it is as if in each '''execution unit''', it is
automatically {{function|include}}ed for you. There are a few different ways to make an execution unit. The first way is
to create a new alias. Each alias is it's own execution unit, and uniquely to the aliases, each alias is also it's own
compilation unit. A bound event handler is another execution unit, and the entirety of main.ms is an execution unit.
set_interval and set_timeout are also separate execution unit, as well as execution queue elements, and others.
So, what is an execution unit? It is a unit of code that gets run, from top to bottom. You can think of it as an
'''insertion point''' to your code, or places that will start up your code. An execution unit is often times made up of
several parts, so let's create a multifile example, which demonstrates a few execution units.
In auto_include.ms:
proc(_my_proc){
console('In _my_proc');
}

1 {{keyword|proc}}(_my_proc){
2 {{function|console}}('In _my_proc');
3 }
bind(some_event, null, null, @event,
_my_proc();
console('In some_event');
)
console('Finished binding all events in main.ms');

1 {{keyword|bind}}(some_event, {{keyword|null}}, {{keyword|null}}, @event,
2 {{function|_my_proc}}();
3 {{function|console}}('In some_event');
4 )
5 {{function|console}}('Finished binding all events in main.ms');
/test $alias = >>>
_my_proc();
console('In /test $alias');
<<<

1 /test $alias = >>>
2 {{function|_my_proc}}();
3 {{function|console}}('In /test $alias');
4 <<<
proc(_my_proc, ...);
bind(some_event, null, null, @event, /*<CREATION OF EXECUTION UNIT>*/);
console('Finished binding all events in main.ms');

1 {{keyword|proc}}(_my_proc, ...);
2 {{keyword|bind}}(some_event, {{keyword|null}}, {{keyword|null}}, @event, /*<CREATION OF EXECUTION UNIT>*/
3 );
4 {{function|console}}('Finished binding all events in main.ms');
proc(_my_proc, ...);
_my_proc();
console('In /test $alias');

1 {{keyword|proc}}(_my_proc, ...);
2 {{function|_my_proc}}();
3 {{function|console}}('In /test $alias');
proc(_my_proc, ...);
_my_proc();
console('In some_event');

1 {{keyword|proc}}(_my_proc, ...);
2 {{function|_my_proc}}();
3 {{function|console}}('In some_event');
/recompile
command is used to reload just CommandHelper, though /reload
will
also reload CommandHelper. However, using the recompile command can allow for finer grained control of what all gets
reloaded. By default, the command reloads the following things about CommandHelper:
* Scripts - Any changes that you have made to any scripts will be reloaded and applied. Main files are re-run,
and any new commands are re-registered.
* Globals - Global values, set with {{function|export}} are cleared out.
* Tasks - Any tasks set with {{function|set_interval}} or {{function|set_timeout}} are cleared.
* Execution-Queue - Any tasks queued up with the queue_* family of functions is cleared.
* Persistence-Config - Any changes to the persistence.ini file are reloaded
* Profiler - The profiler.config file is reloaded
* Extensions - Extensions are reloaded
You can actually reload these sub-modules individually if you want, by passing parameters to the command. There are two
modes, whitelist, or by default, blacklist. In blacklist mode, all modules get reloaded except the modules that are
blacklisted, which aren't reloaded. In whitelist mode, only the specified modules are reloaded. You use the underlined
letter to refer to that specific module. For instance, if you want to reload everything but leave the exported variables
and execution queue alone, you can run /recompile -ge
. If you ONLY want to reload tasks, you can
run /recompile --whitelist -t
. Note that reloading individual modules isn't normally encouraged,
because it can put your server in an inconsistent and unreproducible state if you aren't careful. Running
/recompile
by itself (which reloads everything) is recommended. You can also run
/recompile -h
for the usage instructions and long options list.
/reloadaliases
is an alias to /recompile
===Scripting Examples===
Here are a few more complex examples to get you started on how to use the advanced features of CommandHelper. Because of
the Turing completeness of the plugin, it is possible to do far more advanced things.
/**
* Better tp. If "/tp name" is used, it implies "/tp thisplayer name"
* but if "/tp name1 name2" is used, it implies "/tp name1 name2"
*/
/tp $p1 [$p2=''] = >>>
@player = $p1;
if($p2 == ''){
@player = player();
}
@playerTo = $p2;
if($p2 == ''){
@playerTo = $p1;
}
run('/tp ' . @player . ' ' . @playerTo);
<<<
/**
* Sets the time on the server, and uses english words to set the time
* If the english word isn't "day" or "night", it uses the number
* Note that the equals operator returns a true value if the two
* parameters are the same, and the if/else if chain runs only
* one of the code branches, or none, depending on the true/false
* value of the arguments.
*/
/time $time = >>>
@time = $time;
if($time == 'day'){
@time = 1;
} else if($time == 'night'){
@time = 13500;
}
run('/time set '.@time);
<<<
/**
* Give the player 64 each of gold tools
* Note that the data_values function uses the enum values of
* the material, and we are taking advantage of the autoconcatenation
* principal in the first two runs, but not the third.
*/
/kit gold = >>>
run('/give' player() golden_pickaxe 64);
run('/give' player() golden_shovel 64);
run('/give ' . player() . ' golden_axe 64');
<<<
/**
* Shows help information
* This demonstrates how to use die() and msg(). They work basically the same, except
* die() kills the command if evaluated. They both send a message to the player.
*/
/help [$cmd=''] = >>>
if($cmd == ''){
die('Do you need help?');
} else if($cmd == 'commandhelper'){
msg('The best plugin ever!');
} else {
die('Invalid command specified!');
}
<<<
// Simple hello world scripts
/hello world console = console('Hello Console!');
/hello world player = msg('Hello Player!');

01 /**
02 * Better tp. If "/tp name" is used, it implies "/tp thisplayer name"
03 * but if "/tp name1 name2" is used, it implies "/tp name1 name2"
04 */
05
06 /tp $p1 [$p2=''] = >>>
07 @player = $p1;
08 {{keyword|if}}($p2 == ''){
09 @player = {{function|player}}();
10 }
11
12 @playerTo = $p2;
13 {{keyword|if}}($p2 == ''){
14 @playerTo = $p1;
15 }
16 {{function|run}}('/tp ' . @player . ' ' . @playerTo);
17 <<<
18
19 /**
20 * Sets the time on the server, and uses english words to set the time
21 * If the english word isn't "day" or "night", it uses the number
22 * Note that the equals operator returns a true value if the two
23 * parameters are the same, and the if/else if chain runs only
24 * one of the code branches, or none, depending on the true/false
25 * value of the arguments.
26 */
27
28 /time $time = >>>
29 @time = $time;
30 {{keyword|if}}($time == 'day'){
31 @time = 1;
32 } {{keyword|else}} {{keyword|if}}($time == 'night'){
33 @time = 13500;
34 }
35 {{function|run}}('/time set '.@time);
36 <<<
37
38 /**
39 * Give the player 64 each of gold tools
40 * Note that the data_values function uses the enum values of
41 * the material, and we are taking advantage of the autoconcatenation
42 * principal in the first two runs, but not the third.
43 */
44
45 /kit gold = >>>
46 {{function|run}}('/give' {{function|player}}() golden_pickaxe 64);
47 {{function|run}}('/give' {{function|player}}() golden_shovel 64);
48 {{function|run}}('/give ' . {{function|player}}() . ' golden_axe 64');
49 <<<
50
51 /**
52 * Shows help information
53 * This demonstrates how to use die() and msg(). They work basically the same, except
54 * die() kills the command if evaluated. They both send a message to the player.
55 */
56
57 /help [$cmd=''] = >>>
58 {{keyword|if}}($cmd == ''){
59 {{function|die}}('Do you need help?');
60 } {{keyword|else}} {{keyword|if}}($cmd == 'commandhelper'){
61 {{function|msg}}('The best plugin ever!');
62 } {{keyword|else}} {
63 {{function|die}}('Invalid command specified!');
64 }
65 <<<
66
67 // Simple hello world scripts
68
69
70 /hello world console = {{function|console}}('Hello Console!');
71 /hello world player = {{function|msg}}('Hello Player!');
.
operator to concatenate
things together.
}}
Note that a lit and string are treated the same, however special characters must be put in a string to be treated as
literal character. Technically all other special characters are treated as literals, but to make your script compatible
with future versions, you must put any non-word character inside a string.
Note that string concatenation happens automatically (known as autoconcatenation). Let's take the following example:
if(@i == 0){
run('/run' 'this' 'command');
die('The' 'command' 'has' 'been' 'run');
} else {
run('/run' 'another' 'command');
}

1 {{keyword|if}}(@i == 0){
2 {{function|run}}('/run' 'this' 'command');
3 {{function|die}}('The' 'command' 'has' 'been' 'run');
4 } {{keyword|else}} {
5 {{function|run}}('/run' 'another' 'command');
6 }
/cmd = /real command
.
'/real' and 'command' are automatically sconcatenated together, and then run.
=== Smart Comments and Aliases ===
A smart comment applied to an alias can be used both by the alias engine, and by your scripts. In general, you can
obtain the information in the currently running alias with the {{function|get_alias_comment}} function, and you can
use this however you like, but there are additional annotations, which the alias engine uses to provide additional
functionality.
@command - When this annotation is present, this alias is instead treated as a command. This registers the alias as
if you had used the {{function|register_command}} function. This comes with one drawback, which is that the name of the
command, that is, for instance "/cmd" must be unique within other @commands defined in CommandHelper. Additional
aliases can still provide additional functionality, but will not be used as part of the command system. One drawback
of using commands is that commands registered in this way cannot be fully removed from the server without a server
reboot, though functionality can generally be changed with a simple recompile anyways.
When an alias is part of the command system, there are a few things that are done automatically, and a few things that
can be further unlocked with additional annotations. First of all, the command is registered as part of the overall
command system. This means that it will appear in default /help and autocomplete lists. Secondly, the command help text
is automatically generated as part of the command, using the body of the smart comment. The usage parameter of the
command is simply the left hand side of the alias, though additional usage can be provided in another annotation.
Commands may have additional annotations, which correspond to the values in register_command:
@usage - Overrides the default usage example
@permission - The permission the user must have to run this command. Note that this permission is in *addition* to the
normal alias permission system, and so it's recommended to continue using the * label on the alias itself.
@noPermMsg - Overrides the no permission error message (unused as of Spigot 1.19)
@alias - Alias for this command. A command can have multiple aliases, and you can repeat this annotation to provide
more.
@tabcompleter - Provides the name of a proc that is called, which should return the tab complete closure for this
command. If the annotation is not provided, there are a set of default completions that will be provided
on a best-effort basis, first based on variable names in the alias and superceded by information provided in the @param
annotations in this comment. Variable names with "player" in them will autocomplete player names. Other variables will
simply disable autocompletion.
@param - This documents the variables in the alias, and generally follows the format
"@param $variableName type description". Description is optional, and is only used as a code comment. The $variableName
should match the parameter in the alias, and the type can be any valid MethodScript type, or a few special types,
"$Player" and "$OfflinePlayer", or an ad-hoc enum, which is a comma separated list contained within square brackets.
Depending on the MethodScript type, there will be different default autocomplete result, with special handling for
enums, which autocomplete to the list of enums, boolean, which autocompletes to the strings "true" and "false". All
other types disable auto completes for this variable. Another special type begins with $proc->
and should
be the name of a proc that is used to provide autocompletion. It is only called for the specified parameter, and accepts
the same arguments as general autocompleters. For instance, $proc->_myCompleter
would call _myCompleter, sending
it string @alias, string @sender, array @args, and would expect an array to be returned, which returns the list
of completions. This is useful for completers that handle generic parameter types, but still require custom code.
Note that these annotations will not be used if placed on an alias that isn't also a @command.
The executor of the command is simply the code in the alias itself. Actually, it's worth noting that nothing
about this changes the execution, it still uses the normal alias engine in the same way as every other alias,
it simply provides additional integrations on top of the alias system.
A full complex example, which provides a custom tabcompleter and overrides some existing parameters, might look
like this:
main.ms:
// Simulate some database of users
export('list', associative_array());

1 // Simulate some database of users
2
3 {{function|export}}('list', {{function|associative_array}}());
// Create modification procedures for the simulated database
proc _usersInList() {
return(import('list'));
}
proc _addUser(@user, @msg) {
import('list')[@user] = @msg; // push on the new user
}
proc _removeUser(@user) {
array_remove(import('list'), @user);
}
// NOTE! The procedure should take no arguments, and should return a closure. The closure may accept the
// @alias, @sender, @args arguments, just as in the tabcompleter value for register_command.
proc _myCommandTabComplete() {
return(get_tabcomplete_prototype(
array('add', 'remove'),
array(
'<add': closure(@alias, @sender, @args) { return(array_subtract(all_players(), array_keys(_usersInList()))); },
'<remove': closure(@alias, @sender, @args) { return(_usersInList()); },
),
'None'
));
}

01 // Create modification procedures for the simulated database
02
03 {{keyword|proc}} {{function|_usersInList}}() {
04 {{function|return}}({{function|import}}('list'));
05 }
06
07 {{keyword|proc}} {{function|_addUser}}(@user, @msg) {
08 {{function|import}}('list')[@user] = @msg; // push on the new user
09
10 }
11
12 {{keyword|proc}} {{function|_removeUser}}(@user) {
13 {{function|array_remove}}({{function|import}}('list'), @user);
14 }
15
16 // NOTE! The procedure should take no arguments, and should return a closure. The closure may accept the
17
18 // @alias, @sender, @args arguments, just as in the tabcompleter value for register_command.
19
20 {{keyword|proc}} {{function|_myCommandTabComplete}}() {
21 {{function|return}}({{function|get_tabcomplete_prototype}}(
22 {{function|array}}('add', 'remove'),
23 {{function|array}}(
24 '<add': {{keyword|closure}}(@alias, @sender, @args) { {{function|return}}({{function|array_subtract}}({{function|all_players}}(), {{function|array_keys}}({{function|_usersInList}}()))); },
25 '<remove': {{keyword|closure}}(@alias, @sender, @args) { {{function|return}}({{function|_usersInList}}()); },
26 ),
27 'None'
28 ));
29 }
/**
* This command adds or removes a user from a list, with a given message.
* @command
* @usage /myCommand add player [message], /myCommand remove player
* @tabcompleter _myCommandTabComplete
* @permission ch.testing
* @noPermMsg You don't have access to this command.
*/
*:/myCommand $enum $player [$] = >>>
// Error checking. Note that permission handling is already managed with the annotations. HOWEVER,
// it may be prudent to check again anyways, in case this code is used in older versions of CommandHelper.
if(!has_permission('ch.testing'), die());
if(!array_contains(array('add', 'remove'), $enum)) {
die(color('RED').'Enum must be add or remove. See /help /myCommand');
}
if($enum == 'remove' && $ != null) {
die(color('RED').'No message should be provided when removing a player');
}
if(!array_contains(all_players(), $player)) {
die(color('RED').'Player offline or unknown. See /help /myCommand');
}
switch($enum) {
case 'add':
_addUser($player, $);
case 'remove':
_removeUser($player);
}
msg(color('GREEN').'Action completed.');
<<<

01 /**
02 * This command adds or removes a user from a list, with a given message.
03 * @command
04 * @usage /myCommand add player [message], /myCommand remove player
05 * @tabcompleter _myCommandTabComplete
06 * @permission ch.testing
07 * @noPermMsg You don't have access to this command.
08 */
09
10 *:/myCommand $enum $player [$] = >>>
11 // Error checking. Note that permission handling is already managed with the annotations. HOWEVER,
12
13 // it may be prudent to check again anyways, in case this code is used in older versions of CommandHelper.
14
15 {{keyword|if}}(!{{function|has_permission}}('ch.testing'), {{function|die}}());
16
17 {{keyword|if}}(!{{function|array_contains}}({{function|array}}('add', 'remove'), $enum)) {
18 {{function|die}}({{function|color}}('RED').'Enum must be add or remove. See /help /myCommand');
19 }
20 {{keyword|if}}($enum == 'remove' && $ != {{keyword|null}}) {
21 {{function|die}}({{function|color}}('RED').'No message should be provided when removing a player');
22 }
23 {{keyword|if}}(!{{function|array_contains}}({{function|all_players}}(), $player)) {
24 {{function|die}}({{function|color}}('RED').'Player offline or unknown. See /help /myCommand');
25 }
26
27 {{function|switch}}($enum) {
28 {{keyword|case}} 'add':
29 {{function|_addUser}}($player, $);
30 {{keyword|case}} 'remove':
31 {{function|_removeUser}}($player);
32 }
33
34 {{function|msg}}({{function|color}}('GREEN').'Action completed.');
35 <<<
/**
* This command does things.
* @command
* @param $enum [add, remove]
* @param $player $Player
* @param $ $none
*/
*:/myCommand $enum $player [$] = ...

1 /**
2 * This command does things.
3 * @command
4 * @param $enum [add, remove]
5 * @param $player $Player
6 * @param $ $none
7 */
8
9 *:/myCommand $enum $player [$] = ...
Note: Note the drawbacks of using the @command system: Using /recompile is not good enough to change all the settings,
and requires a server reboot. It is recommended that during development, you use plain aliases, and then add the command
system on top once you have a stable API. Code changes to the aliases can be done easily, but changing the documentation
and permissions cannot.
=== Source File Encoding ===
MethodScript files, both ms and msa files should have UTF-8 encoding. A byte order mark (BOM) may or may not be present.
While other encodings may work, particularly ASCII and others, the source files will be parsed using UTF-8. In the future,
other encodings may be supported, but there is currently no plans to add this support in the near term.
===Continued Learning===
Many of the scripting concepts are addressed in greater depth in the Learning Trail, shown below. The MScript topics
are of great value to go through, and they build off what you have already learned in this tutorial. What is provided
in this lesson should be enough to get you started with basic script writing, so start trying to apply these concepts
to your own scripts, and continue going down the learning trail!
{{LearningTrail}}
Find a bug in this page? Edit this page yourself, then submit a pull request.