Skip to main content

Commands

On this page: How to create commands

Adding Commands Support

Firstly, you need to create package that will store command's files. After that, you can create CommandManager and register commands.

MyPlugin#onEnable()
CommandManager commandManager = new CommandManager(wrapper, getFile(), wrapper.getTag());
commandManager.registerCommands(wrapper.getPackageUtil().get("PACKAGE WITH COMMANDS"));
note

Remeber to replace package with commands. Path to package is relative from Main class. I.e.

  • Main class of plugin -> pl.kpgtb.myplugin.Main
  • Package of Main class -> pl.kpgtb.myplugin
  • Package with commands -> pl.kpgtb.myplugin.command
  • Path to package -> command
commandManager.registerCommands(wrapper.getPackageUtil().get("command"));

Creating Command

Commands are register automatically. To create command, you need to create new class in commands package. Name of command is a lower case class name (Without Command text).

Example names of class

  • Example -> /example
  • ExampleCommand -> /example
  • ExampleCMD -> /examplecmd

Created class must extend KCommand

command/ExampleCommand.java
public class ExampleCommand extends KCommand {
private final ToolsObjectWrapper wrapper;
public ExampleCommand(ToolsObjectWrapper wrapper, String groupPath) {
super(wrapper, groupPath);
this.wrapper = wrapper;
}
}
tip

You can also create another package inside command i. e. admin. Then commands inside command/admin package will be in admin permissions group

Adding methods

You can create 3 types of functions

  • Main Command -> /example
  • Subcommand -> /example sth
  • Neasted subcommand -> /example sth add

Main Commands

To create Main Command, simply add new void with annotation @MainCommand. You also need to specify, if command is only for players or not. To make it, you need to set 1st parameter as:

  • CommandSender - If command can be executed by everyone
  • Player - If command can be executed only by players
command/ExampleCommand.java
@MainCommand
public void exampleForEveryone(CommandSender sender) {
sender.sendMessage("Command /example will be available for everyone.");
}

@MainCommand
public void exampleOnlyPlayers(Player player) {
player.sendMessage("Command /example will be now only for players");
}

Subcommands

Creating subcommands is very easy. Just add new void. Name of that method will be a name of subcommand.

command/ExampleCommand.java
public void sth(Player player) {
player.sendMessage("Only player will see that message after typing /example sth");
}

Neasted subcommands

In some cases, you need to make neasted subcommands. In that case, you can create new public class inside command class. Name of class will be a name of subcommand, but name of methods inside that class, will be name of another subcommands.

command/ExampleCommand.java
public class ExampleCommand extends KCommand {

// ...

public class Sth {
public void add(CommandSender sender) {
sender.sendMessage("Command for everyone after typing /example sth add");
}

public void remove(Player player) {
player.sendMessage("Command for players after typing /example sth remove");
}

public class Info {
public void player(Player player) {
player.sendMessage("Command for players after typing /example sth info player");
}

public void console(CommandSender sender) {
sender.sendMessage("Command for everyone after typing /example sth info console");
}
}
}
}

Description

You can add command description (visible in /help), by adding @Description annotation to class.

command/ExampleCommand.java
@Description("Example description of command")
public class ExampleCommand extends KCommand {
// ...
}

You can also add description of main command / subcommand visible in help message.

command/ExampleCommand.java
@MainCommand
@Description("This command is available for everyone")
public void exampleForEveryone(CommandSender sender) {
// ...
}

@Description("This command is available only for players")
public void sth(Player player) {
// ...
}

Permissions

Permissions are automatically generated for each subcommand.

Default permissions (Player needs to have at least one):

  • command.*
  • command.GROUP.* (Only if group exists.)
  • command.GROUP.COMMAND.* (If group doesn't exists, it will be removed from permission)
  • command.GROUP.COMMAND.MAIN_SUBCOMMANDS.* (If subcommand is neasted)
  • command.GROUP.COMMAND.MAIN_SUBCOMMANDS.SUBCOMMAND (If subcommand is a main command then subcommand is a name of method)

Example permissions for /example sth info player command without group:

  • command.*
  • command.example.*
  • command.example.sth.*
  • command.example.sth.info.*
  • command.example.sth.info.player

Example permissions for /example sth command inside admin group:

  • command.*
  • command.admin.*
  • command.admin.example.*
  • command.admin.example.sth
tip

You can also add your own, custom permission by adding @CustomPermission annotation to class (permission for entire command) or method (permission for method)

command/ExampleCommand.java
@CustomPermission("example.permission")
public class ExampleCommand extends KCommand {
// ...
}
tip

If you don't want permissions for command, just add @WithoutPermission annotationo class (for entire command) or method (for method)

command/ExampleCommand.java
@WithoutPermission
public class ExampleCommand extends KCommand {
// ...
}

Arguments

If you want add args to your command, just add new parameters to your method. I. e. if you want to create command /example tp <target> <world> <x> <y> <z>, create method like that

command/ExampleCommand.java
public void tp(CommandSender sender, Player target, World world, double x, double y, double z) {
target.teleport(new Location(world,x,y,z));
}
note

KTools will automatically create tab completer for arguments

caution

Parameters will be automatically converted into args names in help command and in tab completer, but not every compiler, by default, compile parameters names. To enable it, you need to add -parameters arg.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>{VERSION}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>

Supported args by default

  • From Java
    • String
    • Short
    • Long
    • Integer
    • Float
    • Double
    • Byre
    • Boolean
    • Enum
  • From Spigot
    • OfflinePlayer
    • Player
    • World
  • Custom
tip

To create arg that will return more than 1 word, the last parameter must be a String with annotation @LongString

command/ExampleCommand.java
// Usage: /example kick KPGTB Example very long reason
public void kick(CommandSender sender, Player target, @LongString String reason) {
target.kickPlayer(reason);
}

Adding support for own, custom objects

You can also create parser for your custom object. Firstly, you need to create your object.

ExampleObject.java
public class ExampleObject {
private final String name;
private final int nameSize;

public ExampleObject(String name, int nameSize) {
this.name = name;
this.nameSize = nameSize;
}

public String getName() {
return name;
}

public int getNameSize() {
return nameSize;
}
}

Then create a packge with parsers and create new class that implements IParamParser

parser/ExampleParser.java
public class ExampleParser implements IParamParser<ExampleObject> {
@Override
public ExampleObject convert(String param, ToolsObjectWrapper wrapper) {
return null;
}

@Override
public boolean canConvert(String param, ToolsObjectWrapper wrapper) {
return false;
}

@Override
public @NotNull List<String> complete(String arg, CommandSender sender, ToolsObjectWrapper wrapper) {
return null;
}
}

Now you can fill generated methods.

  • convert() -> Convert String into your object
  • canConvert() -> Check if String can be converted into your object
  • complete() -> Tab completer hints
parser/ExampleParser.java
public class ExampleParser implements IParamParser<ExampleObject> {
@Override
public ExampleObject convert(String param, ToolsObjectWrapper wrapper) {
return new ExampleObject(param, param.length());
}

@Override
public boolean canConvert(String param, ToolsObjectWrapper wrapper) {
return !param.isEmpty() && param.length() < 6;
}

@Override
public @NotNull List<String> complete(String arg, CommandSender sender, ToolsObjectWrapper wrapper) {
return Arrays.stream(Bukkit.getOfflinePlayers())
.filter(op -> op.getName().length() < 6)
.map(OfflinePlayer::getName)
.filter(s -> s.startsWith(arg))
.limit(30)
.collect(Collectors.toList());
}
}

Now you can register your parser.

Registering parsers package for entire plugin

First option is to register parsers package in onEnable(). You need to make it before registering commands.

MyPlugiN#onEnable()
ParamParserManager paramParserManager = wrapper.getParamParserManager();
paramParserManager.registerParsers(wrapper.getPackageUtil().get("PARSERS PACKAGE"), getFile());

Manually applying parsers for selected argument

You can also use @Parser annotation on method parameter.

command/ExampleCommand.java
public void sth(Player player, @Parser(ExampleParser.class) ExampleObject obj) {
// ...
}

Filters

Filters allows you to filter arguments. I. e. if you want add command /clan delete <clan> that can be only executed by clan owner, you can add filter to clan argument, that only pass clans, which owner is sender. You can also add filters to players i. e. command that can be only executed by player with specific item in hand.

Creating filter

To create filter, you need to create class that implements IFilter.

Example Filter for object from custom parser section

ExampleFilter.java
public class ExampleFilter implements IFilter<ExampleObject> {
@Override
public boolean filter(ExampleObject obj, ToolsObjectWrapper wrapper, CommandSender sender) {
return false;
}

@Override
public List<Component> notPassMessage(ExampleObject obj, ToolsObjectWrapper wrapper, CommandSender sender) {
return null;
}

@Override
public int weight() {
return 0;
}
}

Now you can fill generated methods.

  • filter() -> Return true if obj pass tests.
  • notPassMessage() -> Message that should be displayed on the chat, when obj doesn't pass tests.
  • weight() -> Priority of filter. If command won't pass multiple filters, sender will see message from filter with highest priority.
ExampleFilter.java
public class ExampleFilter implements IFilter<ExampleObject> {
@Override
public boolean filter(ExampleObject obj, ToolsObjectWrapper wrapper, CommandSender sender) {
return obj.getNameSize() == 5;
}

@Override
public List<Component> notPassMessage(ExampleObject obj, ToolsObjectWrapper wrapper, CommandSender sender) {
return Arrays.asList(Component.text("Wrong size of name"));
}

@Override
public int weight() {
return 0;
}
}

Adding filter to argument

Now you can add filter to any parameter with type ExampleObject using annotation @Filter. You can create 2 types of filters.

  • andFilters - Argument will pass test only if every filter is passed
  • orFilters - Argument will pass test when at least one filter is passed.
command/ExampleCommand.java
public void sth(Player player, @Filter(andFilters = {ExampleFilter.class}) ExampleObject obj) {
player.sendMessage("Player will see that message only if size got from obj is 5");
}

Additional annotations

  • @CommandAliases - List of command aliases. Apply to command class
  • @Hidden - Hide subcommand from tab completer and help. Appy to method with subcommand
  • @NoCommand - Specify that method is not a command. Apply to method that shouldn't be a part of command. I. e. utility method.

Help Command

KTools will automatically generate help that will be send when player wrong use a command.

note

By default, sender will see in help only commands that can be used. That means that player needs to:

  • Have permissions to use command
  • Pass filters from applied to sender (1st parameter) Also command can't be marked as @Hidden

Changing default help

You can override default help and create your own.

command/ExampleCommand.java
@Override
@NoCommand
public void sendHelp(CommandSender sender) {
// Your custom help
}

Creating help subcommand

You can create your own subcommand that will send help. I. e. /example help

command/ExampleCommand.java
@Description("Check usage of command")
@WithoutPermission
public void help(CommandSender sender) {
super.sendHelp(sender);
}

Commands.yml

Plugin will automatically generate file commands.yml that contain info about every command created by KTools. Path to file server_dir/plugins/PLUGIN_NAME/commands.yml