-
Notifications
You must be signed in to change notification settings - Fork 0
Command DSL
The command DSL is more or less a wrapper around Sponge's command builder.
There are some significant changes that make creating commands much simpler!
First, there are two ways to write commands.
If you only need to make a single command, you can create it this way.
ScriptCommandManager.command("simple") {}
For multiple commands and better control over scope you can use a closure.
ScriptCommandManager {
command("dynamic") {}
command("command2") {}
}
Now in order to create a full command, you'll need an executes
block.
ScriptCommandManager {
command("foo") {
/*
This is the simplest command possible, but it doesn't do anything
other than prevent an error message.
*/
executes {
/*
* Commands are required to return a CommandResult
* the api provides two convenience methods
* success() and error(Component)
*/
success()
}
}
}
In this section we will go over how commands are constructed in the DSL syntax. It's important to note that much of this api wraps around Sponge's CommandBuilder. This brings us the major advantage of having command completion support for your commands!
Now because we wrap Sponge's command API, we do also copy a lot of the methods, but they are constructed in a more script-like syntax. With a notable exception being subcommands.
Our first command will have no additional args. So this example will not explain how to add them! Keeping in mind the above example was the bare minimum for a valid command, so everything else seen can be considered optional.
ScriptCommandManager {
command("bar") {
//We can add as many aliases as we like
aliases += "bbar"
aliases += "cbar"
//You can even use a list if you provide many
aliases += listOf("dbar", "ebar", "fbar")
//Registering a permission is simple
//Command closures also provide the command name to context : $it = "bar"
permission = "plugin.command.$it"
//For advanced requirements you may consider using an executionRequirement
//Predicate<CommandCause>
executionRequirement = Predicate { true }
//Provide a description!
description = "This command has an example for how it works"
executes {
//Anything wanted to be run during the command happens here!
//You have full access to CommandContext from SpongeAPI
sendMessage(Identity.nil(), Component.text("Bar has been executed"))
success()
}
}
}
Alright we've covered most of what makes up a command. Let's get into the good stuff now!
Since we know how commands work this guide will omit the command manager from here on out!
Additionally, I will be using a method #sendMessageToCause
that I will provide at the
end of this guide. It's just a wrapper to handle strings and send a message.
Sponge's list of Common Parameters can be found here
This command will have the syntax /razz <true/false>
command("razz") {
//Commands also need to take argument sometimes!
//We can do that by using a UnaryPlus "+"
//This command will take a boolean
+CommonParameters.BOOLEAN
executes {
//Like regular sponge commands, you need to handle parameters
val param = requireOne(CommonParameters.BOOLEAN)
sendMessageToCause("Razz command selected : $param")
success()
}
}
It's also important to be able to add your own parameters of course! There's a few ways to add your own parameters and even flags!
command("rizz") {
//Simple param -- The string is the key
val customParam = "secret" withType Parameter.string()
//Simple flag -- This will build a flag with `-f`
val customFlag = "f" buildFlag "plugin.flag.force"
//Here we use SpongeAPI directly to build a parameter
val optionalParam = Parameter.world().key("world").optional().build()
val anotherFlag = ("s" asFlag "plugin.flag.s").aliases("sour", "crank").build()
executes {
val param = one(optionalParam)
if (!param.isPresent) {
sendMessageToCause("No world!")
} else {
sendMessageToCause("World! ${param.get().key().formatted()}")
}
if (hasFlag(customFlag) && hasFlag(anotherFlag)) {
sendMessageToCause("Double flag mode!")
} else {
sendMessageToCause("No flags!")
}
success()
}
//Remember to use the "+"!
+customParam
+customFlag
executes {
val param = requireOne(customParam)
if (hasFlag(customFlag)) {
sendMessageToCause("You've forced our hand! -- Now you'll get it: ", param)
} else {
Logger.info("$param wasn't sent!")
sendMessageToCause("We weren't forced into this, nothing to report!")
}
success()
}
}
Finally, what would a command be without subcommands?
Now despite what the guide suggests previously the executes
block actually isn't necessary!
You may, however find that you want to handle your command errors instead!
Otherwise, you'll receive errors such as Unknown or incomplete command, see below for error at position ...
if the command is run.
command("baz") {
//Commands may have subcommands too!
subcommand("buzz") {
//So can sub-commands
subcommand("braz") {
//sub-sub-sub-commands!?
subcommand("broz") {
executes {
sendMessageToCause("Listen we could do this all day...")
success()
}
}
executes {
sendMessageToCause("Sub-sub-commands!")
success()
}
}
//Commented out here because it's not strictly necessary!
/*executes {
sendMessageToCause("Buzz subcommand")
success()
}*/
}
executes {
sendMessageToCause("Baz Command")
success()
}
}
This isn't necessary for your scripts. This is provided only to explain examples above.
Additional examples, as well as a script with most of the examples above can be found here
fun CommandContext.sendMessageToCause(vararg msg: String) {
val firstToken = msg.first()
val remainingTokens = msg.filterNot { it.contentEquals(firstToken) }
var finalMessage: TextComponent = Component.text(firstToken)
remainingTokens.forEach { finalMessage = finalMessage.append(Component.text(it)) }
cause().sendMessage(Identity.nil(), finalMessage)
}