Skip to Content
Hytale logoCommunity-built docsOpen source and updated by the community.

Commands

Create custom commands for your Hytale plugin using the server command system found in the decompiled sources.

Command Registration

Commands extend AbstractCommand (most commonly CommandBase for sync commands) and are registered in your plugin’s setup() method.

public class PingCommand extends CommandBase { public PingCommand() { // Second parameter is a description/translation key. super("ping", "myplugin.commands.ping.desc"); } @Override protected void executeSync(@Nonnull CommandContext context) { context.sendMessage(Message.raw("Pong!")); } } @Override protected void setup() { getCommandRegistry().registerCommand(new PingCommand()); }

getCommandRegistry().registerCommand(...) wires the command owner to your plugin. Use CommandManager.get().registerSystemCommand(...) only for system-level commands.

Arguments

Commands define arguments with withRequiredArg, withOptionalArg, withDefaultArg, and withFlagArg. Argument values are read from CommandContext.

public class EchoCommand extends CommandBase { private final RequiredArg<String> textArg = this.withRequiredArg("text", "myplugin.commands.echo.text", ArgTypes.STRING); private final DefaultArg<Integer> timesArg = this.withDefaultArg("times", "myplugin.commands.echo.times", ArgTypes.INTEGER, 1, "1"); public EchoCommand() { super("echo", "myplugin.commands.echo.desc"); } @Override protected void executeSync(@Nonnull CommandContext context) { String text = textArg.get(context); int times = timesArg.get(context); for (int i = 0; i < times; i++) { context.sendMessage(Message.raw(text)); } } }

Use ArgTypes to pick the built-in argument parsers (strings, numbers, players, worlds, assets, and more).

Sender Handling

CommandContext provides the sender and helper methods for sender checks.

if (!context.isPlayer()) { context.sendMessage(Message.raw("Players only.")); return; } Player player = context.senderAs(Player.class);

Sub-Commands

Use AbstractCommandCollection for subcommands.

public class WarpCommand extends AbstractCommandCollection { public WarpCommand() { super("warp", "myplugin.commands.warp.desc"); this.addSubCommand(new WarpSetCommand()); this.addSubCommand(new WarpGoCommand()); } } public class WarpSetCommand extends CommandBase { public WarpSetCommand() { super("set", "myplugin.commands.warp.set.desc"); } @Override protected void executeSync(@Nonnull CommandContext context) { context.sendMessage(Message.raw("Warp set.")); } }

Async Commands

For long-running work, extend AbstractAsyncCommand and return a CompletableFuture.

public class ExportCommand extends AbstractAsyncCommand { public ExportCommand() { super("export", "myplugin.commands.export.desc"); } @Override protected CompletableFuture<Void> executeAsync(@Nonnull CommandContext context) { return runAsync(context, () -> { // Heavy work (file I/O, DB, etc.) context.sendMessage(Message.raw("Export complete.")); }, MyPlugin.getExecutor()); } }

Built-in Commands

System commands are registered in CommandManager.registerCommands() and by builtin plugins via registerSystemCommand(...). Refer to the decompiled sources for the authoritative list in your build.

Common Issues

IssueSolution
Command not appearing in helpEnsure setup() registers the command with getCommandRegistry()
SenderTypeExceptionGuard with context.isPlayer() or catch the exception
Optional arg is nullUse withDefaultArg(...) or check for null
Suggestions not shownUse Argument.suggest(...) or a supported ArgTypes parser

Next Steps

Last updated on