Commands - noobmobile/GroovyBukkitAPI GitHub Wiki

Creating commands

Include the suffix Command on your class and the @Inject annotation. Every closure in the class will be considerated a command and it must have the first parameter as Context. The name of the variable will be registered in the main as the name of the command. You still need to register the command in the plugin.yml (maybe won't be necessary in the future)

@Inject
class TestCommand {

    Terminal main
    ItemService itemService // an example service, it'll automatically injected and registered on our main
    
    // our command will be registered as /give
    def give = { Context context ->
        // when we call the Context#player() method, an exception will be throwed if it's not a player that it's executing the command
        // but don't worry, the exception it's treated and a nice message it's sent to the Console saying it's only for players
        def player = context.player()
        if (!context.hasArgs(2)){ // if there's two or more arguments
            return "§cPlease, use /give <player> <item> <amount>" // we can also use context.returning(String... messages)
        }
        def target = context.parsePlayer(0) // parse the player on args[0]
        def material = context.parseEnum(1, Material) // parse an enum on args[1]
        def amount = context.hasArg(2) ? context.parseInt(2) : 1
        target.getInventory(new ItemComposer(material, amount).build())
        return "§aItem given with success to $target.name"
    }
    
}

Context

The Context class it's where happens all the command logic.

ContextException

It's throwed whenever a "good exception" happens. A good exception it's when it's a exception we expect it to happen, like players inputing numbers, something not being found etc. If it is a good exception, we just send a message to the player saying what's wrong ("you typed a String instead of a Number" or "the player you typed is not online"). Any other exceptions will just be throwed if you don't catch them.

Context return

At any place of your command code, you can just return a String, and it will be sent to the player

    def give = { Context context ->
        // handle some logic
        if (someBoolean){
            return "someBoolean is true"
        } 
        // rest of the logic
    }

You can also use Context.returning(String... messages) to return multiple messages

    def give = { Context context ->
        // handle some logic
        if (someBoolean){
            context.returning("I'm sorry but you don't have the permission to continue this code", "See you later!")
        } 
        // rest of the logic
    }

Context.sender()

Returns the CommandSender who executed the command

Context.player()

Cast the CommandSender to Player. If wasn't a player who executed the command (like the Console or Command Block), it'll be throwed a ContextException

Context.parseInt(int index), parseDouble(int index), parsePlayer(int index)

Accept as parameter the index of the argument (like args[0], args[1]). parsePlayer() uses Bukkit.getPlayer(). If there's a problem parsing or if no player is found, it'll be throwed a ContextException

Context.parseEnum(int index, Class clazzOfEnum)

Returns the passed index argument casted as the passed enum

def material = context.parseEnum(0, Material)
def sound = context.parseEnum(1, Sound)

Context.parseT(collection, predicate, filter, type)

Well, this is can be really tricky, but it's a powerful method.

collection - the collection to be searched
predicate - the function that extracts what we are searching for (for instance: we are searcing for machines by name, so extract Machine::name)
filter - our filter object, usually a String
type - the type name, just for our exception message if we don't find anything.
    MachineService machineService
    def give = { Context context ->
        // lets suppose that this MachineService has a getAllMachines() method, but there's not a findByName() method
        def machine = context.parseT(machineService.getAllMachines(), {machine -> machine.type.name}, context.getArg(0), "Machine")
        // we are searching for all machines inside the provided collection, by its type name, with our args[0]
        // if nothing is found, we throw a ContextException saying to the player "Machine (see why we pass the name of the type?) args[0] not found"
    }

Context.permission(String permission)

Returns if the CommandSender has the passed permission. If he doesn't have the permission, it'll be throwed a ContextException

Context.hasPermission(String permission)

Returns if the CommandSender has the passed permission. Doesn't throw any exception. What's the difference?

    def give = { Context context ->
        context.permission("give.permission")
        // dont execute the rest of the code, just says to the CommandSender that he doesn't have the permission
    }
    def give = { Context context ->
        def type = context.parseEnum(0, Material)
        if (type == Material.DIAMOND && !context.hasPermission("give.diamonds")){
            return "Sorry, only vips can give diamonds"
        }
        context.player().getInventory().addItem(new ItemStack(type))
    }

Context.validTypes(enumClass)

Returns a String joined with ", " of the enum

    def give = { Context context ->
        if (context.argsLenght() == 0){
            context.returning("Use /give <material type>", "Valid types: " + context.validTypes(Material))
            // prints "Valid types: STONE, DIRT, GRASS..."
        }
    }

Context.validTypes(collection, extractor)

Same for the enum, but it's passed a collection a function that extracts the names

    MachineService machineService
    def give = { Context context ->
        if (context.argsLenght() == 0){
            context.returning("Use /give <machine type>", "Valid types: " + context.validTypes(machineService.getAllMachines(), {machine -> machine.name}))
            // prints "Valid types: machinetype1, machinetype2, machinetype3..."
        }
    }

Context.getArg(int index)

Returns the argument in the passed index.

Context.hasArg(int index)

Returns if the passed arg exists

Context.hasArgs(int size)

Returns if there's at least the passed number of arguments.

Context.argsLenght()

Returns the size of the arguments array.

⚠️ **GitHub.com Fallback** ⚠️