Command Arguments
The argument system provides type-safe command parameter parsing with validation. See Command Syntax for how raw input is tokenized before arguments are parsed.
Argument Types
Section titled “Argument Types”RequiredArg<T>
Section titled “RequiredArg<T>”Mandatory positional arguments. Command fails if not provided.
public class GiveCommand extends CommandBase { private final RequiredArg<String> itemArg; private final RequiredArg<Integer> amountArg;
public GiveCommand() { super("give", "myplugin.commands.give.desc");
this.itemArg = this.withRequiredArg("item", "myplugin.commands.give.item.desc", ArgTypes.STRING); this.amountArg = this.withRequiredArg("amount", "myplugin.commands.give.amount.desc", ArgTypes.INTEGER); }
@Override protected void executeSync(@Nonnull CommandContext context) { String item = this.itemArg.get(context); int amount = this.amountArg.get(context); // ... }}Usage: /give diamond_sword 5
OptionalArg<T>
Section titled “OptionalArg<T>”Optional named arguments with --name=value syntax.
private final OptionalArg<Integer> countArg;
public MyCommand() { // ... this.countArg = this.withOptionalArg("count", "desc.key", ArgTypes.INTEGER, 1); // default: 1}
// in execute:int count = this.countArg.get(context); // returns 1 if not specifiedUsage: /mycommand --count=5 or /mycommand (uses default)
DefaultArg<T>
Section titled “DefaultArg<T>”Optional positional argument with a default value.
private final DefaultArg<String> targetArg;
public MyCommand() { // ... this.targetArg = this.withDefaultArg("target", "desc.key", ArgTypes.STRING, "self");}Usage: /mycommand target_name or /mycommand (uses “self”)
FlagArg
Section titled “FlagArg”Boolean flags. Present = true, absent = false.
private final FlagArg verboseFlag;private final FlagArg forceFlag;
public MyCommand() { // ... this.verboseFlag = this.withFlag("verbose", "desc.key"); this.forceFlag = this.withFlag("force", "desc.key");}
// in execute:boolean verbose = this.verboseFlag.get(context);boolean force = this.forceFlag.get(context);Usage: /mycommand --verbose --force
Built-in ArgTypes
Section titled “Built-in ArgTypes”Located in com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes:
Primitives
Section titled “Primitives”| Type | Description | Example Values |
|---|---|---|
ArgTypes.BOOLEAN | True/false | true, false |
ArgTypes.INTEGER | Integer numbers | 42, -10, 0 |
ArgTypes.FLOAT | Floating point | 3.14, -0.5 |
ArgTypes.DOUBLE | Double precision | 3.14159265 |
ArgTypes.STRING | Text string | hello, "hello world" |
Game Objects
Section titled “Game Objects”| Type | Description | Example Values |
|---|---|---|
ArgTypes.PLAYER_REF | Online player | Player name or selector |
ArgTypes.WORLD | World reference | World name |
ArgTypes.BLOCK_TYPE_ASSET | Block type | stone, dirt |
ArgTypes.ITEM_ASSET | Item type | diamond_sword |
ArgTypes.PARTICLE_SYSTEM | Particle effect | Particle system ID |
ArgTypes.SOUND_EVENT_ASSET | Sound event | Sound event ID |
ArgTypes.SOUND_CATEGORY | Sound category | SFX, Music, Ambient, UI |
ArgTypes.NPC_ROLE | NPC role | Role ID |
Positions
Section titled “Positions”| Type | Description | Example Values |
|---|---|---|
ArgTypes.RELATIVE_BLOCK_POSITION | Block position (supports ~) | 100 64 200, ~ ~5 ~ |
ArgTypes.RELATIVE_POSITION | Double position | 100.5 64.0 200.5 |
ArgTypes.VECTOR3I | Integer vector | 10 20 30 |
ArgTypes.VECTOR3F | Float vector | 1.0 2.0 3.0 |
Position types support relative coordinate prefixes: ~ (relative to player), _ (surface height), c (chunk scale).
Use ArgTypes.forEnum() to restrict an argument to a fixed set of values. This is the recommended approach for string-choice parameters — don’t parse strings manually.
// for any enum typeArgTypes.forEnum("mode", GameMode.class)
// built-in enum typesArgTypes.GAME_MODE // gameMode enumCustom enums work the same way. Define your enum and pass it to forEnum():
public enum TimeOfDay { DAWN, NOON, DUSK, MIDNIGHT}
// in your command constructor:this.timeArg = this.withRequiredArg("time", "myplugin.commands.settime.time.desc", ArgTypes.forEnum("time", TimeOfDay.class));
// in execute:TimeOfDay time = this.timeArg.get(context); // TimeOfDay.DAWN, etc.Enum arguments provide:
- Case-insensitive parsing —
dawn,DAWN, andDawnall matchTimeOfDay.DAWN - Fuzzy “did you mean?” errors — typing
duskksuggestsdusk
Validators
Section titled “Validators”Add validators to arguments for input validation:
this.withRequiredArg("amount", "desc.key", ArgTypes.INTEGER) .addValidator(Validators.greaterThan(0)) .addValidator(Validators.max(100));
this.withRequiredArg("name", "desc.key", ArgTypes.STRING) .addValidator(Validators.minLength(3)) .addValidator(Validators.maxLength(16));Built-in Validators
Section titled “Built-in Validators”| Validator | Description |
|---|---|
Validators.greaterThan(n) | Value > n |
Validators.greaterThanOrEqual(n) | Value >= n |
Validators.lessThan(n) | Value < n |
Validators.lessThanOrEqual(n) | Value <= n |
Validators.min(n) | Alias for greaterThanOrEqual |
Validators.max(n) | Alias for lessThanOrEqual |
Validators.range(min, max) | min <= value <= max |
Validators.minLength(n) | String length >= n |
Validators.maxLength(n) | String length <= n |
Validators.pattern(regex) | Matches regex pattern |
Validators.notEmpty() | String not empty |
Tab Completion
Section titled “Tab Completion”The suggestion system has two layers: argument types can provide built-in suggestions, and individual argument instances can add custom suggestions on top.
Built-in Suggestions
Section titled “Built-in Suggestions”Most argument types do not provide suggestions by default. The types that do:
| Type | Suggestions |
|---|---|
ArgTypes.BOOLEAN | true, false (ordered by prefix match) |
ArgTypes.TICK_RATE | 30tps, 60tps, 20tps, 33ms, 16ms, 50ms |
Types like PLAYER_REF, WORLD, BLOCK_TYPE_ASSET, and ITEM_ASSET resolve names during parsing but do not provide proactive tab suggestions. Enums provide fuzzy “did you mean?” on parse failure but not proactive suggestions either.
Per-Argument Custom Suggestions
Section titled “Per-Argument Custom Suggestions”Use Argument.suggest() to attach a SuggestionProvider to any argument instance:
this.withRequiredArg("target", "desc.key", ArgTypes.STRING) .suggest((sender, textAlreadyEntered, numParametersTyped, result) -> { for (PlayerRef player : Universe.get().getPlayers()) { if (player.getUsername().toLowerCase() .startsWith(textAlreadyEntered.toLowerCase())) { result.suggest(player.getUsername()); } } });The SuggestionProvider functional interface:
@FunctionalInterfacepublic interface SuggestionProvider { void suggest(@Nonnull CommandSender sender, @Nonnull String textAlreadyEntered, int numParametersTyped, @Nonnull SuggestionResult result);}Parameters:
sender— the player requesting suggestions (enables sender-aware filtering)textAlreadyEntered— what the user has typed so far for this argumentnumParametersTyped— how many tokens have been entered (for multi-token types)result— accumulator to add suggestions into
SuggestionResult
Section titled “SuggestionResult”The SuggestionResult accumulator provides several ways to add suggestions:
result.suggest("option1"); // raw stringresult.suggest(Object::toString, myObject); // via toString functionresult.suggest(myObject); // via Object.toString()result.fuzzySuggest(input, candidates, Item::name); // fuzzy-match top 5fuzzySuggest() ranks candidates by fuzzy distance against the input and keeps only the top 5 matches — useful for large candidate sets like asset IDs.
Suggestion Layering
Section titled “Suggestion Layering”When suggestions are requested, both sources contribute additively:
- The per-argument
SuggestionProvider(set via.suggest()) runs first - The argument type’s built-in
suggest()method runs second
Results from both are combined into a single list.
Custom Argument Types
Section titled “Custom Argument Types”Create custom types by extending SingleArgumentType<T>:
public static final SingleArgumentType<MyObject> MY_TYPE = new SingleArgumentType<MyObject>( "myplugin.argtype.myobject.name", "myplugin.argtype.myobject.usage") { @Override public MyObject parse(@Nonnull String input, @Nonnull ParseResult parseResult) { MyObject obj = MyObject.fromString(input); if (obj == null) { parseResult.error("myplugin.argtype.myobject.invalid"); return null; } return obj; }
@Override public void suggest(@Nonnull CommandSender sender, @Nonnull String textAlreadyEntered, int numParametersTyped, @Nonnull SuggestionResult result) { // provide suggestions for this argument type for (String option : MyRegistry.getNames()) { if (option.toLowerCase().startsWith(textAlreadyEntered.toLowerCase())) { result.suggest(option); } } }};
// usage:this.withRequiredArg("myarg", "desc.key", MY_TYPE);Override suggest() on your argument type to provide built-in suggestions whenever this type is used. This is the pattern used by built-in types like NPC_ROLE in the NPC plugin.
Accessing Arguments
Section titled “Accessing Arguments”Always access arguments through the CommandContext:
@Overrideprotected void executeSync(@Nonnull CommandContext context) { // required - always has value String name = this.nameArg.get(context);
// optional - returns default if not specified int count = this.countArg.get(context);
// flag - returns true/false boolean verbose = this.verboseFlag.get(context);
// check if optional was explicitly provided if (this.countArg.isPresent(context)) { // user explicitly specified --count }}Code Location
Section titled “Code Location”Package: com.hypixel.hytale.server.core.command.system.arguments