-
Notifications
You must be signed in to change notification settings - Fork 0
dev:Command Handling
Väinämö Łūmikērø edited this page Feb 2, 2017
·
6 revisions
There are three types of commands in Forestual 2 - primary commands, secondary commands and tertiary commands.
Type | Description | Example | Restrictions |
---|---|---|---|
Primary | Command without parameters. |
/version ,/shutdown
|
May only consist of letters (a-zA-Z), numbers (0-9) and - . |
Secondary | Command with optional parameters. |
/ping [account] ,/motd [content]
|
Same as for Primary applies. |
Tertiary | Command with required (and optional) parameters. |
/join <channel> ,/bann <account> <duration> [reason]
|
Same as for Secondary applies plus optional parameters must be at the end and may not be followed by required parameters. |
Try not to use more than 1 string parameter (with spaces allowed) at the moment. This will presumably crash the system.
However, we're working on a solution for this problem (Core/#2).
this
refers to the extension handling the commands.
// Creating the commands
var Shutdown = new Command("shutdown", this);
var Motd = new Command("motd", this);
var Bann = new Command("bann", this);
// Applying parameters
Motd.AddParameter<string>("content", 0, ParameterType.Optional);
Bann.AddParameter<string>("account", 0, ParameterType.Required);
Bann.AddParameter<int>("duration", 1, ParameterType.Required);
Bann.AddParameter<string>("reason", 2, ParameterType.Optional);
bool Valid;
// This may seem futile as the string equality operator (==) should work fine, but it's not. See "Why is this useful?" below.
Valid = Shutdown.Validate("/shutdown 5"); // false, because shutdown doesn't accept parameters.
Valid = Shutdown.Validate("/shutdown"); // true
Valid = Motd.Validate("/motd"); // true, because the content parameter is optional.
Valid = Motd.Validate("/motd Welcome"); // true
Valid = Bann.Validate("/bann vainamo"); // false, because bann requires a duration.
Valid = Bann.Validate("/bann vainamo foo"); // true, because Validate() does not check the parameter types.
Valid = Bann.Validate("/bann vainamo 7 <Some Reason Here>"); // true
string Content = "/bann vainamo 7 <Some Reason Here>"; // Demo purpose. Obviously you would not set the content yourself.
// Extra validation because Parse() does validate the command but returns the default value if the validation fails.
if (Bann.Validate(Content)) {
try {
var Target = Bann.Parse<string>(Content, "account");
var Duration = Bann.Parse<int>(Content, "duration");
var Reason = Bann.Parse<string>(Content, "reason");
// Do stuff
} catch {
/*
A FormatException is thrown, when the parameter value in content
does not match the type. For example a "foo" when an int is required.
An InvalidCastException is thrown, when the T type in Parse<T> does
not match the parameter type. For example Parse<string>(content, "duration").
*/
}
}
-
Fallback Mechanism
The system uses a fallback mechanism to solve what we call conflicts. Conflicts occur when two or more extensions use the same command, for example two games using/start
to begin a new match. To distinguish between conflicted commands, the command systems allows prefixing each command with the extension namespace it belongs to. So/race:start
is additionally valid inml.festival.race
but not inml.festival.quiz
(/quiz:start
).
This system even has a Fallback Fallback (...) Mechanism. In case the namespace of two extensions (using the same command) end in the same word (eg.ml.festival.quiz
andde.vainamo.quiz
), the commands could still be distinguished by addingfestival.
(orvainamo.
respectively) to the prefixquiz:
. In case this part is also the same, continue adding parts from the namespace until the conflict ends. Note that the order of the namespace parts has to be preserved./ml.quiz:start
is not the same as/ml.festival.quiz:start
! -
Strict Validation
Validating a secondary command usingstring.StartsWith("/command")
would also validate commands starting withcommand
(for example/commands
). Using Command.Validate() prevents this. -
Flexible Case Recognition
IfCommand.IgnoreCase
is set totrue
, commands with different cases (/cOMmand
,/Command
,/COMMAND
) would still be valid.