-
-
Notifications
You must be signed in to change notification settings - Fork 1
Create Commands
Create A single Command is simple:
create a command:
@Commander(
name = "test",
description = "test command",
alias = {"tes", "te"}
)
public class TestCommand implements CommandNode {
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("test!");
}
}
and register:
public class TesterRegistry implements ComponentsRegistry {
@Override
public void registerCommand(CommandRegistry<CommandSender> commandRegistry) {
commandRegistry.command(TestCommand.class);
}
@Override
public void registerListeners(ListenerRegistry<Listener> listenerRegistry) {
}
}
root command
@Commander(
name = "test",
description = "test command",
alias = {"tes", "te"}
)
public class TestCommand implements CommandNode {
@Override
public void execute(CommandSender commandSender) {
}
}
subcommand 1
@Commander(
name = "one",
description = "test one command"
)
public class TestOneCommand implements CommandNode {
// here is the command arguments, which we will talk later
@CommandArg(order = 0, labels = {"string"})
private String value;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("this is one command with value "+value);
}
}
subcommand 2
@Commander(
name = "two",
description = "two command"
)
public class TestTwoCommand implements CommandNode {
@CommandArg(order = 0)
private int number;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage("this is two command with number "+number);
}
}
and define their relationship:
public class TesterRegistry implements ComponentsRegistry {
@Override
public void registerCommand(CommandRegistry<CommandSender> commandRegistry) {
commandRegistry.command(TestCommand.class, c -> {
c.command(TestOneCommand.class);
c.command(TestTwoCommand.class);
});
}
@Override
public void registerListeners(ListenerRegistry<Listener> listenerRegistry) {
}
}
After that, the command will be registered as below:
/test one <string>
/test two <number>
The Commander Annotation Reference:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Commander {
String name();
String description();
boolean playerOnly() default false; // still need to cast yourself
String permission() default "";
String[] alias() default {};
}
Guess what? you can create multiple of them as you can!
public class TesterRegistry implements ComponentsRegistry {
// 本框架允許你無限創建分支指令。
@Override
public void registerCommand(CommandRegistry<CommandSender> commandRegistry) {
commandRegistry.command(TestCommand.class, c -> {
c.command(TestSayCommand.class);
c.command(TestCalculateCommand.class, cc -> {
cc.command(TestCalculateAddCommand.class);
cc.command(TestCalculateMinusCommand.class);
});
c.command(TestConfigCommand.class, cc -> {
cc.command(TestConfigCheckCommand.class);
cc.command(TestConfigEditCommand.class);
cc.command(TestConfigReloadCommand.class);
});
c.command(TestServiceCommand.class, cc -> {
cc.command(TestServiceByeCommand.class);
cc.command(TestServiceHelloCommand.class);
});
c.command(TestSchedulerCommand.class, cc ->{
cc.command(TestSchedulerOneCommand.class);
cc.command(TestSchedulerTwoCommand.class);
});
});
}
@Override
public void registerListeners(ListenerRegistry<Listener> listenerRegistry) {
}
}
Here are the calculation commands
@Commander(
name = "calculate",
description = "test calculate command",
alias = {"cal", "c"}
)
public class TestCalculateCommand implements CommandNode {
@Override
public void execute(CommandSender commandSender) {
}
}
@Commander(
name = "add",
description = "calculate add command",
alias = {"ad", "plus", "a"}
)
public class TestCalculateAddCommand implements CommandNode {
@CommandArg(order = 0)
private int one;
@CommandArg(order = 1)
private int two;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage(one+" + "+two+" = "+(one + two));
}
}
@Commander(
name = "minus",
description = "minus command",
alias = {"reduce", "m"}
)
public class TestCalculateMinusCommand implements CommandNode {
@CommandArg(order = 0)
private int one;
@CommandArg(order = 1)
private int two;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage(one+" - "+two+" = "+(one - two));
}
}
the usage is shown below:
/calculate add <one> <two>
/calculate minus <one> <two>
The command API has parsed your string argument into the type that you have declared from @CommandArg
automatically.
Now, let's do some changes for those two @CommandArg
@CommandArg(order = 0, labels = {"first value"})
private int one;
@CommandArg(order = 1, labels = {"second value"}, optional = true)
private int two = 22;
After that, the usage will become
/calculate add <first value> [second value]
/calculate minus <first value> [second value]
What's changed?
- after setting the label, the usage display label changed.
- the second argument becomes optional, if you don't input it, it will use the default value 22
Getting remain args is simple:
@Commander(
name = "add",
description = "calculate add command",
alias = {"ad", "plus", "a"}
)
public class TestCalculateAddCommand implements CommandNode {
@CommandArg(order = 0)
private int one;
@CommandArg(order = 1)
private int two;
@RemainArgs
private List<String> args;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage(one+" + "+two+" = "+(one + two));
commandSender.sendMessage("remainArgs: "+args.toString());
}
}
so when you execute /calculate add 1 1 a b c d e
the remaining args will be [a, b, c, d, e]
just go to the main class:
(For spigot)
@ELDBukkit(
registry = TesterRegistry.class,
lifeCycle = TesterLifeCycle.class
)
public class ELDTester extends ELDBukkitPlugin {
@Override
public void bindServices(ServiceCollection serviceCollection) {
}
@Override
protected void manageProvider(BukkitManagerProvider provider) {
var parser = provider.getArgumentManager(); //參數解析器
// 創建參數解析
parser.registerParser(Integer.class, (iterator, commandSender, argParser) -> {
try{
return Integer.parseInt(iterator.next());
}catch (NumberFormatException e){
throw new ArgumentParseException("not a valid integer.");
}
});
}
}
(For Bungee)
@ELDBungee(
registry = TesterRegistry.class,
lifeCycle = TesterLifeCycle.class
)
public class ELDTester extends ELDBungeePlugin {
@Override
public void bindServices(ServiceCollection serviceCollection) {
}
@Override
protected void manageProvider(BungeeManagerProvider provider) {
var parser = provider.getArgumentManager(); //get the argument manager
// create argument parser
parser.registerParser(Integer.class, (iterator, commandSender, argParser) -> {
try{
return Integer.parseInt(iterator.next());
}catch (NumberFormatException e){
throw new ArgumentParseException("not a valid integer.");
}
});
}
}
the example shows the command argument parsing from string to integer so that you can use like:
@Commander(
name = "add",
description = "calculate add command",
alias = {"ad", "plus", "a"}
)
public class TestCalculateAddCommand implements CommandNode {
@CommandArg(order = 0)
private int one;
@CommandArg(order = 1)
private int two;
@Override
public void execute(CommandSender commandSender) {
commandSender.sendMessage(one+" + "+two+" = "+(one + two));
}
}
It also supports register with identifier, for example:
var parser = provider.getArgumentManager();
// create parser with identifier 'message'
parser.registerParser(String.class, "message", (iterator, commandSender, p) -> {
StringBuilder builder = new StringBuilder();
iterator.forEachRemaining(s -> builder.append(s).append(" "));
return builder.toString();
});
so if you mark the identifier as message
in your @CommandArg
, it will do the above parsing instead of just passing one string argument.
Example usage:
@Commander(
name = "say",
description = "test say command",
alias = {"sa", "s"}
)
public class TestSayCommand implements CommandNode {
@CommandArg(order = 0, identifier = "message")
private String message;
@Override
public void execute(CommandSender commandSender) {
Bukkit.broadcastMessage(commandSender.getName()+" says: "+message);
}
}
you can also use the argument parser inside an argument parser:
argumentManager.registerParser(Location.class, (args, sender, parser) -> {
World world;
if (!(sender instanceof Player)) {
world = Bukkit.getWorld(args.next());
} else {
world = ((Player) sender).getWorld();
}
if (world == null) {
throw new ArgumentParseException("&cunknown world");
}
var x = parser.tryParse(Double.class, args, sender); //internal parsing
var y = parser.tryParse(Double.class, args, sender); //internal parsing
var z = parser.tryParse(Double.class, args, sender); //internal parsing
return new Location(world, x, y, z);
});
@Commander(
name = "sleep",
description = "sleep command"
)
public class TestSleepCommand implements CommandNode {
// this argument have long and string two types
// the type must be Object
@DynamicArg(order = 0, types = { Long.class, String.class })
private Object seconds;
@Inject
private ScheduleService scheduleService;
@Override
public void execute(CommandSender commandSender) {
if (seconds instanceof Long){
commandSender.sendMessage("sleeping...");
var time = (Long) seconds;
scheduleService.injectTask(new BukkitRunnable() {
@Override
public void run() {
commandSender.sendMessage("you wake up!");
commandSender.sendMessage("you just slept "+seconds+" seconds!");
}
}).timeout(time * 20L).run(ELDTester.getPlugin(ELDTester.class));
}else if (seconds instanceof String){
var time = (String) seconds;
switch (time.toLowerCase()){
case "never":
commandSender.sendMessage("you don't sleep ? okay you never sleep");
return;
case "forever":
commandSender.sendMessage("you sleep forever ? that's not good!");
return;
default:
commandSender.sendMessage("oh sorry what is "+time+" ? I don't understand.");
}
}
}
}