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.
CommandManager commandManager = new CommandManager(wrapper, getFile(), wrapper.getTag());
commandManager.registerCommands(wrapper.getPackageUtil().get("PACKAGE WITH COMMANDS"));
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
public class ExampleCommand extends KCommand {
private final ToolsObjectWrapper wrapper;
public ExampleCommand(ToolsObjectWrapper wrapper, String groupPath) {
super(wrapper, groupPath);
this.wrapper = wrapper;
}
}
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
@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.
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.
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.
@Description("Example description of command")
public class ExampleCommand extends KCommand {
// ...
}
You can also add description of main command / subcommand visible in help message.
@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
You can also add your own, custom permission by adding @CustomPermission
annotation to class (permission for entire command) or method (permission for method)
- Global
- Method
@CustomPermission("example.permission")
public class ExampleCommand extends KCommand {
// ...
}
@CustomPermission("example.permission")
public void sth(Player player) {
// ...
}
If you don't want permissions for command, just add @WithoutPermission
annotationo class (for entire command) or method (for method)
- Global
- Method
@WithoutPermission
public class ExampleCommand extends KCommand {
// ...
}
@WithoutPermission
public void sth(Player player) {
// ...
}
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
public void tp(CommandSender sender, Player target, World world, double x, double y, double z) {
target.teleport(new Location(world,x,y,z));
}
KTools will automatically create tab completer for arguments
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.
- Maven
- Gradle
<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>
compileJava {
options.compilerArgs << '-parameters'
}
Supported args by default
- From Java
- String
- Short
- Long
- Integer
- Float
- Double
- Byre
- Boolean
- Enum
- From Spigot
- OfflinePlayer
- Player
- World
- Custom
To create arg that will return more than 1 word, the last parameter must be a String
with annotation @LongString
// 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.
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
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()
-> ConvertString
into your objectcanConvert()
-> Check ifString
can be converted into your objectcomplete()
-> Tab completer hints
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.
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.
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
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()
-> Returntrue
ifobj
pass tests.notPassMessage()
-> Message that should be displayed on the chat, whenobj
doesn't pass tests.weight()
-> Priority of filter. If command won't pass multiple filters, sender will see message from filter with highest priority.
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 passedorFilters
- Argument will pass test when at least one filter is passed.
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.
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.
@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
@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