-
Notifications
You must be signed in to change notification settings - Fork 31
Custom Argument Types
Sometimes the basic data types don't cut it. Sometimes you need to take a more complex type, like World
, or even your own data type. Command Manager makes that easy.
To start with, you have to create an ArgType
, which tells the command manager how to convert from a String (the command argument) to another data type. Defining this is simple. Here's an example of how to create one for World
:
ArgType<World> worldType = new ArgType<>("world", Bukkit::getWorld);
world
is now the name of this ArgType
, and Bukkit::getWorld
is a lambda for a Function<String, World>
that will convert from String
to World
. You can also create an ArgType
by passing a BiFunction<CommandSender, String, T>
where T
is the argument type.
Optionally, you can also give your argument type tab completion. For World
, it would look like this:
ArgType<World> worldType = new ArgType<>("world", Bukkit::getWorld)
.tabStream(c -> Bukkit.getWorlds().stream().map(World::getName));
Alternatively, if you want a command (not an argument type) to not be tab-completable, you can add the notab
tag to it in the command file.
Calling tabStream
, you must pass a Function<CommandSender, Stream<String>>
which will provide tab completions for this type. In this case, it gets the list of worlds, and maps the Stream
to be of their names, which are Strings.
Now that you've finished your ArgType
, a whopping 2 lines of code, you're ready to register it and start using it in your commands. First, you have to add it to the CommandParser:
new CommandParser(this.getResource("command.rdcml"))
.setArgTypes(worldType)
.parse().register("prefix", this);
setArgTypes
takes a vararg of ArgType
, so you can pass as many as you need into it. Once you've done that, you can start using it in your command file:
worldspawn world:target {
help Teleports you to the spawn of the given world
user player
permission worldspawn.use
hook worldspawn
}
Since we created our ArgType
with the name world
, that's what we give as the argument type in our command file now.
Now your command hook method would look like this:
@CommandHook("worldspawn")
public void worldSpawn(Player player, World world) {
player.teleport(world.getSpawnLocation());
}
This saves you from having to convert from String to other types every time you write another command.
Additionally, if your custom type is an enum or you have a Map<String, T>
for your type, you can do it even more simply:
ArgType<Material> materialType = ArgType.of("material", Material.class);
Using this will create an ArgType named material
for the Material
enum, and it will automatically tab-complete for all the elements of the enum. Likewise, you can call the same method with a Map<String, T>
with T
being the type returned by your ArgType, and it will automatically be able to tab-complete all keys in the map.
Map<String, Team> teamMap = new HashMap<>(); //Assume values are already populated in this map
ArgType<Team> teamType = ArgType.of("team", teamMap);