-
Notifications
You must be signed in to change notification settings - Fork 20
Command DSL
In this section we will learn how to make commands much IZI using KotlinBukkitAPI. You can see all the code here
fun Plugin.simpleCommand(
name: String,
vararg aliases: String = arrayOf(),
description: String = "",
block: ExecutorBlock
)
Simple, but, what is ExecutorBlock? is simples too, is a lambda with a Receiver.
typealias ExecutorBlock = suspend Executor<CommandSender>.() -> Unit
class Executor<E : CommandSender>(
val sender: E,
val label: String,
val args: Array<out String>,
val command: CommandDSL
)
Example
myPlugin.simpleCommand("hello") {
sender.msg("world")
}
Note: ExecutorBlock is a suspend block, this that you can use Coroutines inside of it, by default, it use the Bukkit Main Thread, this means, do not do block operation or heavy tasks without change the your context, like using: withContext(Dispatchers.IO) {}
.
IMPORTANT: The commands are auto registered by KotlinBukkitAPI.
myPlugin.simpleCommand("warp") {
val player = sender as? Player ?: fail("Please, use this command just in game")
val arg0 = args.getOrNull(0) ?: fail("Please add the warp name")
val warp = warpManager.findWarp(arg0) ?: fail("This warp was not found")
warp.teleport(player)
}
myPlugin.simpleCommand("tp") {
val player = sender as? Player ?: fail("Please, use this command just in game")
val target = player(
0,
"Is missing the Player argument".color(ChatColor.RED),
"This player is not online".color(ChatColor.RED)
)
player.teleport(target)
}
Simple Commmand DSL vs Command DSL: Command DSL has sub commands, support for permission, permission message, tab complete and much more.
typealias CommandBuilderBlock = CommandDSL.() -> Unit
fun command(
name: String,
vararg aliases: String = arrayOf(),
plugin: Plugin,
block: CommandBuilderBlock
): CommandDSL
First I will show how to use it, before we jump into the structure from CommandDSL class.
fun executor(block: ExecutorBlock)
is the same lambda from simpleCommand, with this in mind, you can use fail
and arguments
.
Example
myPlugin.command("playersonline") {
aliases = listOf("online")
permission = "myplugin.cmd.playersonline"
permissionMessage = "You don't have permission to use this command"
executor {
val onlinePlayerNames = onlinePlayers().map { it.name }.joinToString()
sender.msg("&aPlayers online: &e$onlinePlayerNames".translateColor())
}
}
typealias ExecutorPlayerBlock = Executor<Player>.() -> Unit
fun executorPlayer(block: ExecutorPlayerBlock)
Example
myPlugin.command("spawn") {
permission = "myplugin.cmd.spawn"
permissionMessage = "You don't have permission to use this command"
onlyInGameMessage = "This command can be run just in game"
executorPlayer {
sender.teleport(spawnLocation)
sender.msg("Teleported to the server spawn")
}
}
onlyInGameMessage
: When a command just have executorPlayer
this message will be sent to the console when try to use the command.
If the command has executorPlayer
and executor
, the executorPlayer
will be usage to Player and executor
when is not a Player (console)
Important: executorPlayer
like the normal executor
, it is suspend, but, the main difference is that the Coroutine of the executor player in canceled on the player disconnection, preventing Coroutines Job Leaks. If you don't use with attention, you could find some bugs when using it. Because by default it runs in the Main Thread, if you are not using any Coroutines calls, like delay()
or others, your task will ALWAYS complete, don't be afraid.
myPlugin.command("myplugin") {
permission = "myplugin.cmd"
permissionMessage = "You don't have permission to use this command"
onlyInGameMessage = "This command can be run just in game"
executor {
sender.msg("use: /myplugin help")
}
command("help") {
executor {
sender.msg("""
/myplugin help
/myplugin version
/myplugin reload config
/myplugin reload messages
""")
}
}
command("version") {
executor {
sender.msg("Version 1.0.0")
}
}
command("reload") {
command("config") {
executor {
MyConfig.reloadConfig()
sender.msg("Config reloaded")
}
}
command("messages") {
executor {
MyConfig.reloadMessages()
sender.msg("Messages reloaded")
}
}
}
}
- The KotlinBukkitAPI auto generate Tab complete for you based on sub commands
- All sub command has the same Permission message and Only in game message from the root command.