HytaleJS
Guides

Commands

Register custom server commands

Create custom commands that players can run in-game.

Basic Command

commands.register("hello", "Say hello", (ctx) => {
  ctx.sendMessage("Hello, " + ctx.getSenderName() + "!");
});

With Permission

commands.register("heal", "Heal yourself", "admin.heal", (ctx) => {
  ctx.sendMessage("You have been healed!");
});

Players need the admin.heal permission to use this command.

World-Thread Commands

Some operations (like large block edits) are significantly faster when they run on the world thread. Use commands.registerWorld(...) to execute a command on the world executor.

commands.registerWorld("sphere", "Build a sphere on the world thread", (ctx) => {
  // Heavy block edits here
});

Why This Exists

Hytale's world state is updated on its own thread. When commands run off-thread, each setBlock can incur extra scheduling and synchronization overhead. registerWorld runs the JS callback on the world executor, which avoids per-block re-queueing and matches the fastest native command path.

Caveats

  • Blocks the world thread: long loops will pause world ticks while the command runs.
  • Use sparingly: prefer batching (ServerSetBlocks) for very large edits and keep world-thread commands short where possible.

Parsing Arguments

Access the full command input and parse arguments:

commands.register("give", "Give items", (ctx) => {
  const input = ctx.getInput();
  const parts = input.split(" ");

  if (parts.length < 2) {
    ctx.sendMessage("Usage: /give <item_id> [quantity]");
    return;
  }

  const itemId = parts[1];
  const quantity = parts.length >= 3 ? parseInt(parts[2], 10) : 1;

  if (isNaN(quantity) || quantity < 1) {
    ctx.sendMessage("Invalid quantity");
    return;
  }

  ctx.sendMessage("Giving " + quantity + "x " + itemId);
});

Finding the Player

Get the player entity from the command sender:

commands.register("pos", "Show your position", (ctx) => {
  const senderName = ctx.getSenderName();
  const world = Universe.get().getDefaultWorld();
  const players = world.getPlayers();

  let player = null;
  for (let i = 0; i < players.length; i++) {
    if (players[i].getDisplayName() === senderName) {
      player = players[i];
      break;
    }
  }

  if (!player) {
    ctx.sendMessage("Could not find player");
    return;
  }

  const ref = player.getPlayerRef();
  const transform = ref.getTransform();
  const pos = transform.getPosition();

  ctx.sendMessage("Position: " + pos.getX() + ", " + pos.getY() + ", " + pos.getZ());
});

Full Example

commands.register("serverinfo", "Show server info", (ctx) => {
  ctx.sendMessage("Server: " + HytaleServer.get().getServerName());
  ctx.sendMessage("Players: " + Universe.get().getPlayerCount());
  ctx.sendMessage("World: " + Universe.get().getDefaultWorld().getName());
});

commands.register("items", "List items", (ctx) => {
  const input = ctx.getInput();
  const parts = input.split(" ");
  const filter = parts.length >= 2 ? parts[1].toLowerCase() : "";

  const map = Item.getAssetStore().getAssetMap().getAssetMap();
  const keys = map.keySet();
  const iterator = keys.iterator();

  let count = 0;
  while (iterator.hasNext() && count < 20) {
    const key = iterator.next() as string;
    if (!filter || key.toLowerCase().includes(filter)) {
      ctx.sendMessage(key);
      count++;
    }
  }
});

On this page