Use this file to discover all available pages before exploring further.
The CommandRegistry is Essential’s central system for managing commands and custom argument parsers. It provides methods to register commands, add custom type parsers, and unregister commands.
interface CommandRegistry { /** * Add your command instance to the command registry, making it available for use. */ fun registerCommand(command: Command) /** * If one of your command handlers wishes to take a custom type, you must provide a way for the command engine * to turn an ArgumentQueue into your instance. This is done via an implementation of ArgumentParser. * * There is no need to create custom parsers for default types such as: strings, integers, doubles, and booleans. */ fun <T> registerParser(type: Class<T>, parser: ArgumentParser<T>) /** * Remove your command from the command registry. */ fun unregisterCommand(command: Command)}
import gg.essential.api.commands.ArgumentParserimport gg.essential.api.commands.ArgumentQueueimport java.lang.reflect.Parameterclass PlayerParser : ArgumentParser<Player> { /** * Parse arguments into a Player instance. * Return null or throw an exception if parsing fails. */ override fun parse(arguments: ArgumentQueue, param: Parameter): Player? { if (arguments.isEmpty()) { return null } val name = arguments.poll() val player = findPlayerByName(name) if (player == null) { throw IllegalArgumentException("Player '$name' not found") } return player } /** * Provide tab completion options. * This is optional - return emptyList() if not needed. */ override fun complete(arguments: ArgumentQueue, param: Parameter): List<String> { return getAllOnlinePlayerNames() } private fun findPlayerByName(name: String): Player? { // Your implementation return null } private fun getAllOnlinePlayerNames(): List<String> { // Your implementation return emptyList() }}
object TeleportCommand : Command("tp") { @DefaultHandler fun teleport(player: Player) { // Player is automatically parsed using PlayerParser println("Teleporting to ${player.name}") }}
interface ArgumentParser<T> { /** * Parses to a certain type based on the arguments provided by the user * and the parameter (for accessing annotations). * * If the arguments provided do not allow for your custom type to be created, throw an * Exception, or return null. */ @Throws(Exception::class) fun parse(arguments: ArgumentQueue, param: Parameter): T? /** * Allows this ArgumentParser to provide custom tab completion options. * * This does not need to be overridden: by default no tab completion options will be available. */ fun complete(arguments: ArgumentQueue, param: Parameter): List<String> = emptyList()}
data class Coordinate(val x: Int, val y: Int, val z: Int)class CoordinateParser : ArgumentParser<Coordinate> { override fun parse(arguments: ArgumentQueue, param: Parameter): Coordinate? { if (arguments.isEmpty()) return null val x = arguments.poll().toIntOrNull() ?: throw IllegalArgumentException("Invalid X coordinate") val y = arguments.poll().toIntOrNull() ?: throw IllegalArgumentException("Invalid Y coordinate") val z = arguments.poll().toIntOrNull() ?: throw IllegalArgumentException("Invalid Z coordinate") return Coordinate(x, y, z) } override fun complete(arguments: ArgumentQueue, param: Parameter): List<String> { return listOf("~", "0", "100", "-100") }}
@Target(AnnotationTarget.VALUE_PARAMETER)@Retention(AnnotationRetention.RUNTIME)annotation class Range(val min: Int, val max: Int)class RangedIntParser : ArgumentParser<Int> { override fun parse(arguments: ArgumentQueue, param: Parameter): Int? { if (arguments.isEmpty()) return null val value = arguments.poll().toIntOrNull() ?: throw IllegalArgumentException("Not a valid number") val range = param.getAnnotation(Range::class.java) if (range != null) { if (value < range.min || value > range.max) { throw IllegalArgumentException( "Value must be between ${range.min} and ${range.max}" ) } } return value }}
Usage:
@DefaultHandlerfun setVolume(@Range(min = 0, max = 100) volume: Int) { // Automatically validated to be 0-100 println("Volume set to $volume%")}
The ArgumentQueue interface provides methods to access command arguments:
interface ArgumentQueue { /** * Poll the argument queue, getting the next string in the queue, and removing it from the queue. * This method will throw an exception if there are no arguments left. */ fun poll(): String /** * Peek into the argument queue without removing it. If there are no arguments left, the result will be null. */ fun peek(): String? /** * Whether any more arguments have been passed. This is equivalent to [peek] returning null. * * @return true if no arguments are left */ fun isEmpty(): Boolean}
override fun parse(arguments: ArgumentQueue, param: Parameter): MyType? { // Check if arguments are available if (arguments.isEmpty()) { return null } // Peek at next argument without consuming val next = arguments.peek() if (next == "special") { arguments.poll() // Consume it return MyType.SPECIAL } // Poll multiple arguments val first = arguments.poll() val second = arguments.poll() val third = arguments.poll() return MyType(first, second, third)}
override fun parse(arguments: ArgumentQueue, param: Parameter): Player? { val name = arguments.poll() return findPlayerByName(name) ?: throw IllegalArgumentException("Player '$name' not found or offline")}