HyCodeYourTale

Command Types

Command Types

Přehled typů příkazů v Hytale a kdy který použít.

---

Rozhodovací Tabulka

| Potřeba | Použij |
|---------|--------|
| Jednoduchý příkaz bez komponentů | CommandBase |
| Příkaz s přístupem ke komponentům | AbstractPlayerCommand |
| Těžké/blocking operace | AbstractAsyncCommand |
| Více sub-příkazů | AbstractCommandCollection |
| Jen konzole | CommandBase + !context.isPlayer() |

---

CommandBase

Základní synchronní příkaz. Nepoužívej pro přístup ke komponentům!

public class PingCommand extends CommandBase {

public PingCommand() {
super("ping", "myplugin.commands.ping.desc");
}

@Override
protected void executeSync(@Nonnull CommandContext context) {
context.sendMessage(Message.raw("Pong!"));
}
}

// Registrace
@Override
protected void setup() {
getCommandRegistry().registerCommand(new PingCommand());
}

Kdy použít


  • Jednoduché příkazy bez přístupu ke komponentům

  • Konzolové příkazy

  • Příkazy které jen posílají zprávy
  • Kdy NEPOUŽÍVAT


  • Když potřebuješ přístup ke komponentům hráče

  • Způsobí "Assert not in thread!" error
  • ---

    AbstractPlayerCommand

    Příkaz pro hráče s bezpečným přístupem ke komponentům. Doporučeno pro většinu příkazů.

    public class StatsCommand extends AbstractPlayerCommand {

    public StatsCommand() {
    super("stats", "myplugin.commands.stats.desc");
    this.requirePermission(HytalePermissions.fromCommand("stats.self"));
    }

    @Override
    protected void execute(
    @Nonnull CommandContext context,
    @Nonnull Store store,
    @Nonnull Ref ref,
    @Nonnull PlayerRef playerRef,
    @Nonnull World world
    ) {
    // BEZPEČNÉ - AbstractPlayerCommand zajišťuje správný thread
    Player player = store.getComponent(ref, Player.getComponentType());

    if (player != null) {
    // Přístup k vlastním komponentům
    CustomStatsComponent stats = store.getComponent(ref, CustomStatsComponent.getComponentType());

    if (stats != null) {
    context.sendMessage(Message.raw("Tvoje statistiky: " + stats.toString()));
    }
    }
    }
    }

    Parametry execute()

    | Parametr | Typ | Popis |
    |----------|-----|-------|
    | context | CommandContext | Kontext příkazu |
    | store | Store | ECS store pro komponenty |
    | ref | Ref | Reference na entitu hráče |
    | playerRef | PlayerRef | Reference na hráče |
    | world | World | Svět hráče |

    Kdy použít


  • Příkazy které čtou/zapisují komponenty hráče

  • Příkazy které potřebují pozici hráče

  • Většina gameplay příkazů

---

AbstractPlayerCommand s Targetem

Příkaz který operuje na jiném hráči (ne na odesílateli).

public class HealOtherCommand extends AbstractPlayerCommand {

@Nonnull
private final RequiredArg targetArg =
this.withRequiredArg("player", "myplugin.commands.heal.target", ArgTypes.PLAYER_REF);

public HealOtherCommand() {
super("heal", "myplugin.commands.heal.desc");
this.requirePermission(HytalePermissions.fromCommand("heal.other"));
}

@Override
protected void execute(
@Nonnull CommandContext context,
@Nonnull Store store,
@Nonnull Ref ref,
@Nonnull PlayerRef playerRef,
@Nonnull World world
) {
PlayerRef targetPlayerRef = this.targetArg.get(context);
Ref targetRef = targetPlayerRef.getReference();

if (targetRef != null && targetRef.isValid()) {
Store targetStore = targetRef.getStore();
World targetWorld = targetStore.getExternalData().getWorld();

// Spusť na world threadu targetu
targetWorld.execute(() -> {
Player targetPlayer = targetStore.getComponent(targetRef, Player.getComponentType());
if (targetPlayer != null) {
// Heal logic
context.sendMessage(Message.raw("Vyléčil jsi " + targetPlayerRef.getUsername()));
}
});
} else {
context.sendMessage(Message.raw("Hráč není online"));
}
}
}

---

AbstractAsyncCommand

Pro příkazy s těžkými operacemi (databáze, soubory, síť).

public class ExportCommand extends AbstractAsyncCommand {

public ExportCommand() {
super("export", "myplugin.commands.export.desc");
}

@Override
protected CompletableFuture executeAsync(@Nonnull CommandContext context) {
return CompletableFuture.runAsync(() -> {
context.sendMessage(Message.raw("Exportuji data..."));

// Těžká práce (soubory, databáze...)
try {
exportDataToFile();
context.sendMessage(Message.raw("Export dokončen!"));
} catch (Exception e) {
context.sendMessage(Message.raw("Chyba: " + e.getMessage()));
}
});
}
}

S přístupem ke komponentům

public class SaveStatsCommand extends AbstractAsyncCommand {

@Override
protected CompletableFuture executeAsync(@Nonnull CommandContext context) {
Player player = context.senderAs(Player.class);
World world = player.getWorld();

return CompletableFuture.runAsync(() -> {
// Nejprve získej data na world threadu
final StatsData[] dataHolder = new StatsData[1];

world.execute(() -> {
Ref ref = player.getRef();
Store store = ref.getStore();
CustomStatsComponent stats = store.getComponent(ref, CustomStatsComponent.getComponentType());
dataHolder[0] = stats != null ? stats.toData() : null;
});

// Počkej na world.execute()
// (V praxi bys měl použít CompletableFuture chain)

// Async uložení
if (dataHolder[0] != null) {
database.saveStats(player.getUuid(), dataHolder[0]);
context.sendMessage(Message.raw("Statistiky uloženy!"));
}
});
}
}

---

AbstractCommandCollection

Pro příkazy s více sub-příkazy.

public class WarpCommand extends AbstractCommandCollection {

public WarpCommand() {
super("warp", "myplugin.commands.warp.desc");

// Přidej sub-příkazy
this.addSubCommand(new WarpSetCommand());
this.addSubCommand(new WarpGoCommand());
this.addSubCommand(new WarpListCommand());
this.addSubCommand(new WarpDeleteCommand());
}
}

// Sub-příkaz: /warp set
public class WarpSetCommand extends AbstractPlayerCommand {

@Nonnull
private final RequiredArg nameArg =
this.withRequiredArg("name", "myplugin.commands.warp.set.name", ArgTypes.STRING);

public WarpSetCommand() {
super("set", "myplugin.commands.warp.set.desc");
this.requirePermission(HytalePermissions.fromCommand("warp.set"));
}

@Override
protected void execute(
@Nonnull CommandContext context,
@Nonnull Store store,
@Nonnull Ref ref,
@Nonnull PlayerRef playerRef,
@Nonnull World world
) {
String warpName = nameArg.get(context);

TransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
if (transform != null) {
Vector3d position = transform.getPosition();
// Uložení warpu...
context.sendMessage(Message.raw("Warp '" + warpName + "' vytvořen!"));
}
}
}

// Sub-příkaz: /warp go
public class WarpGoCommand extends AbstractPlayerCommand {

@Nonnull
private final RequiredArg nameArg =
this.withRequiredArg("name", "myplugin.commands.warp.go.name", ArgTypes.STRING);

public WarpGoCommand() {
super("go", "myplugin.commands.warp.go.desc");
}

@Override
protected void execute(
@Nonnull CommandContext context,
@Nonnull Store store,
@Nonnull Ref ref,
@Nonnull PlayerRef playerRef,
@Nonnull World world
) {
String warpName = nameArg.get(context);
// Teleport logic...
}
}

Použití

/warp set home
/warp go home
/warp list
/warp delete home

---

Usage Variants

Pro příkazy s různými variantami použití.

public class SpawnCommand extends AbstractPlayerCommand {

@Nonnull
private final OptionalArg spawnIndexArg =
this.withOptionalArg("spawnIndex", "myplugin.commands.spawn.index", ArgTypes.INTEGER);

public SpawnCommand() {
super("spawn", "myplugin.commands.spawn.desc");
this.requirePermission(HytalePermissions.fromCommand("spawn.self"));

// Přidej variantu pro teleport jiného hráče
this.addUsageVariant(new SpawnOtherCommand());
}

@Override
protected void execute(...) {
// /spawn [index] - teleport sebe
}

// Varianta: /spawn [index]
private static class SpawnOtherCommand extends CommandBase {

@Nonnull
private final RequiredArg playerArg =
this.withRequiredArg("player", "myplugin.commands.spawn.player", ArgTypes.PLAYER_REF);

SpawnOtherCommand() {
super("myplugin.commands.spawn.other.desc");
this.requirePermission(HytalePermissions.fromCommand("spawn.other"));
}

@Override
protected void executeSync(@Nonnull CommandContext context) {
// /spawn [index] - teleport jiného hráče
}
}
}

---

Shrnutí

| Třída | Thread-safe komponenty | Async | Sub-příkazy |
|-------|------------------------|-------|-------------|
| CommandBase | Ne | Ne | Ne |
| AbstractPlayerCommand | Ano | Ne | Ne |
| AbstractAsyncCommand | S world.execute() | Ano | Ne |
| AbstractCommandCollection | - | - | Ano |

Last updated: 20. ledna 2026