---
title: Creating Commands
type: docs
weight: 1
---

Commands in Hytale are created by extending the `AbstractCommand` class. This page covers the basics of creating and registering commands.

## Basic Command Structure

```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;

public class HelloCommand extends AbstractCommand {

    public HelloCommand() {
        super("hello", "Sends a greeting message");
    }

    @Override
    protected CompletableFuture<Void> execute(CommandContext context) {
        context.sendMessage(Message.raw("Hello, World!"));
        return null;
    }
}
```

## Constructors

`AbstractCommand` provides several constructors:

```java
// Name and description
protected AbstractCommand(String name, String description)

// Name, description, and requires confirmation flag
protected AbstractCommand(String name, String description, boolean requiresConfirmation)

// Description only (for variant commands)
protected AbstractCommand(String description)
```

## Registering Commands

Register commands in your plugin's `start()` method:

```java
@Override
public void start() {
    getCommandRegistry().registerCommand(new HelloCommand());
}
```

## Adding Aliases

Commands can have multiple names:

```java
public class TeleportCommand extends AbstractCommand {

    public TeleportCommand() {
        super("teleport", "Teleport to a location");
        addAliases("tp", "warp");
    }

    // ...
}
```

Players can now use `/teleport`, `/tp`, or `/warp`.

## Command with Arguments

Add required arguments using `withRequiredArg`:

```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
// For ECS operations: import com.hypixel.hytale.component.Ref;
// For ECS operations: import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;

public class GiveCommand extends AbstractCommand {

    private final RequiredArg<PlayerRef> targetArg;
    private final RequiredArg<Item> itemArg;

    public GiveCommand() {
        super("give", "Give an item to a player");

        targetArg = withRequiredArg("player", "Target player", ArgTypes.PLAYER_REF);
        itemArg = withRequiredArg("item", "Item to give", ArgTypes.ITEM_ASSET);
    }

    @Override
    protected CompletableFuture<Void> execute(CommandContext context) {
        PlayerRef targetRef = context.get(targetArg);
        Item item = context.get(itemArg);

        // PlayerRef provides direct access to player info
        String username = targetRef.getUsername();

        // For ECS operations, use getReference() to access the EntityStore
        // Ref<EntityStore> entityRef = targetRef.getReference();

        // Give item to player...
        context.sendMessage(Message.raw("Gave item to " + username));

        return null;
    }
}
```

## Optional Arguments

Add optional arguments that don't need to be specified:

```java
private final OptionalArg<Integer> countArg;

public GiveCommand() {
    super("give", "Give items to a player");

    targetArg = withRequiredArg("player", "Target player", ArgTypes.PLAYER_REF);
    itemArg = withRequiredArg("item", "Item to give", ArgTypes.ITEM_ASSET);
    countArg = withOptionalArg("count", "Number of items", ArgTypes.INTEGER);
}

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    PlayerRef targetRef = context.get(targetArg);
    Item item = context.get(itemArg);
    Integer count = context.get(countArg);  // May be null

    int amount = count != null ? count : 1;
    // Give items to player...

    return null;
}
```

Usage: `/give player123 iron_sword` or `/give player123 iron_sword --count 5`

## Default Arguments

Arguments with default values:

```java
private final DefaultArg<Integer> countArg;

public GiveCommand() {
    super("give", "Give items to a player");

    countArg = withDefaultArg("count", "Number of items",
        ArgTypes.INTEGER, 1, "defaults to 1");
}

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    int count = context.get(countArg); // Never null, uses default
    // ...
}
```

## Flag Arguments

Boolean flags that can be toggled:

```java
private final FlagArg silentFlag;

public BroadcastCommand() {
    super("broadcast", "Send a message to all players");

    silentFlag = withFlagArg("silent", "Don't show sender name");
}

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    boolean silent = context.provided(silentFlag);
    // ...
}
```

Usage: `/broadcast Hello everyone! --silent`

## List Arguments

For arguments that accept multiple values:

```java
private final RequiredArg<List<String>> playersArg;

public KickAllCommand() {
    super("kickall", "Kick multiple players");

    playersArg = withListRequiredArg("players", "Players to kick", ArgTypes.STRING);
}

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    List<String> players = context.get(playersArg);
    for (String player : players) {
        // Kick each player
    }
    return null;
}
```

Usage: `/kickall player1 player2 player3`

Available list argument methods:
- `withListRequiredArg(name, description, argType)` - Required list
- `withListOptionalArg(name, description, argType)` - Optional list
- `withListDefaultArg(name, description, argType, defaultValue, defaultDesc)` - List with default

## Requiring Confirmation

For dangerous commands, require explicit confirmation:

```java
public class ResetCommand extends AbstractCommand {

    public ResetCommand() {
        super("reset", "Reset all player data", true); // requiresConfirmation = true
    }

    @Override
    protected CompletableFuture<Void> execute(CommandContext context) {
        // This only runs if --confirm was provided
        resetAllData();
        return null;
    }
}
```

Usage: `/reset --confirm`

## Permissions

Commands automatically generate permissions based on your plugin name:

```
{group}.{plugin}.command.{commandname}
```

For example: `com.example.myplugin.command.give`

You can also set a custom permission:

```java
public GiveCommand() {
    super("give", "Give items");
    requirePermission("myplugin.admin.give");
}
```
