Skip to main content

Parameter Type

It's an interface that aims to define how the raw argument entered by the command-source/sender is parsed and converted into a value of specific type; That specific type is defined by the generic type parameter <T> , if the raw input entered doesn't match the logic you set , then an exception shall be thrown inside of the ParameterType#resolve

If you want to create your own exceptions you should check Throwables , Otherwise we will be using the built-in SourceException in our examples.

So if you want to add parameters to usages with custom types, you will need to create a value resolver for each custom type.

then want to add a parameter of type X , you must create and register your own value resolver that will be responsible of converting the (String) raw argument/input by the user , into a object instance (value) to be provided during execution.

Bukkit example:

we create a class(record) called Group that has a field called name as below:

public record Group(String name) {}

we create the value resolver for type Group as below:

public final class ParameterGroup extends BaseParameterType<TestSource, Group> {
private final GroupSuggestionResolver suggestionResolver = new GroupSuggestionResolver();
ParameterGroup() {
super(TypeWrap.of(Group.class));
//static plain suggestions
}

@Override
public @Nullable Group resolve(
ExecutionContext<TestSource> context,
@NotNull CommandInputStream<TestSource> commandInputStream
) throws ImperatException {
String raw = commandInputStream.currentRaw().orElse(null);
if (raw == null) {
return null;
}
return GroupRegistry.getInstance().getData(raw)
.orElseThrow(() -> new SourceException("Unknown group '%s'", raw));
}

//per type suggestion resolver
@Override
public SuggestionResolver<TestSource> getSuggestionResolver() {
return suggestionResolver;
}
}

Then we register the our value resolver as below: dispatcher.registerParamType(Group.class, new ParameterGroup());

Then we will be able to get the group value resolved from it's raw argument during execution of a CommandUsage as below :

Classic example:

Command<CommandSender> senderCommand = Command.createCommand("group");  
senderCommand.setDefaultUsageExecution((source, context)-> {
source.reply("/group <group>");
});

senderCommand.addUsage(
CommandUsage.<CommandSender>builder()
.parameters(CommandParameter.required("group", Group.class))
.execute((source, context)-> {
Group group = context.getArgument("group");
assert group != null;
source.reply("entered group name= " + group.name());
})
.build()
);

Annotations example:

@Command("group")  
public final class GroupCommand {

@Usage
public void defaultUsage(BukkitSource source) {
//default execution = no args
source.reply("/group <group>");
}

@Usage
public void mainUsage(
BukkitSource source,
@Named("group") Group group
){
//when he does "/group <group>"
source.reply("entered group name= " + group.name());
}
}

then we start registering our command, please refer to Introduction to know how to register your commands whether they were made using annotated or classic ways .