Skip to content

Custom Argument Types

Redempt edited this page Aug 18, 2022 · 3 revisions

Being able to take string arguments is nice and all, but often they're not specific enough, and passing everything in as a string means having to parse or convert them all in your code. This can get really repetitive, so it usually makes sense to make a custom argument type. Let's start by defining a type we want to convert to.

public static record Person(String name, int age) {}

private Map<String, Person> people = new HashMap<>();

With this type defined, we're ready to create an argument type for it. To do this, let's go back to where we created the command parser and add something to it:

ArgType<Person> personType = new ArgType<>("person", name -> people.get(name));
SpigotCommandManager.getInstance(this).getParser().setHookTargets(this).addArgTypes(personType).parse(input).register();

An ArgType only needs to be able to convert from a string to our type, and then we just register it by calling addArgTypes on the command parser. Now that we've done that, we can use the new person argument type in a command file:

people {
	age person:person {
		hook = getAge
		help = Show the age of a person
	}
}

And in a method hook:

@CommandHook("getAge")
public void getAge(CommandSender sender, Person person) {
	sender.sendMessage(person.getAge());
}

This is all great, but we still won't be able to see a list of people as tab completions in-game. We can change this by adding a completer to our ArgType:

ArgType<Person> personType = new ArgType<>("person", name -> people.get(name)).completer(ctx -> people.keySet());

By adding the completer call, we've told it how to retrieve completions - in this case, it just fetches the key set of the map. Now, if a player in-game starts typing the command, they will be able to see a list of people they can choose from.

But this can get even simpler. Since we have a Map<String, T> for our type, we can just use a handy utility method:

ArgType<Person> personType = ArgType.of("person", people);

Passing the map, this will automatically create an ArgType that parses by fetching from the map and completes using its key set. Easy!

Next up, learn about Context Providers.

Clone this wiki locally