Skip to main content

Script the world

Game scripts are ES modules evaluated by GraalJS. AtlasEngine injects a focused minestom bridge and resolves modules from ae2/stdlib/*. Scripts do not receive Node.js filesystem or network access.

A minimal entrypoint

import { on, onServerStart } from "ae2/stdlib/events";

onServerStart(() => {
minestom.world.setTime(1000);
minestom.world.setWeather("clear");
console.log("game ready");
});

on("playerJoin", ({ uuid, username }) => {
minestom.players.teleport(uuid, { x: 0, y: 42, z: 0 });
minestom.players.showTitle(uuid, "Welcome", username);
});

If a script is loaded after the server has already started, onServerStart runs its callback immediately.

Events

Use on(name, handler) for game-wide orchestration. The runtime exposes player, entity, block, item, projectile, region, quest, UI, tag, and world-time events.

EventTypical payload
playerJoin{ uuid, username }
playerMove{ player, from, pos }
itemUse{ player, item, itemModel }
blockInteract{ player, pos, block, face }
mobDeath{ mobId, id }
regionEnter{ player, region, world }
uiClick{ ui, widget, player, slot, clickType }

Resource behavior modules use on from ae2/stdlib/behavior. Those handlers are automatically scoped to the behavior's item, block, mob, region, quest, or UI.

Scheduling

AtlasEngine schedules in server ticks. Twenty ticks is one second.

import { everyTicks } from "ae2/stdlib/events";

minestom.schedule(40).then(() => {
minestom.broadcast("Two seconds later");
});

everyTicks(20, () => {
// once per second
});

Reloading a game clears scheduled callbacks so code from a closed script context cannot fire later.

Runtime surfaces

SurfaceUse it for
playersTeleport, inventory, health, game mode, titles
worldBlocks, time, weather, positions
mobs and entitiesSpawn, inspect, damage, remove
navigationPathfinding targets and profiles
projectilesShoot and control projectiles
questsPlayer quest state, rewards, visibility
uiOpen schema-defined inventory interfaces
board and bossbarPersistent HUD elements
droptablesRoll typed drop definitions
cmdRegister reload-safe game commands

The web editor gets completion and signatures from the same bridge contract the server registers.

State

Use module variables for state owned by one script context. Use the shared tag store for small scalar values that need to cross between the main script and behavior contexts.

const store = minestom.store();
store.set("round", "active");
const round = store.get("round");
store.delete("round");

Keep domain logic in ordinary modules when possible. Pure state machines and geometry functions can run in Node tests without booting Minecraft.

Keep callbacks bounded

The game loop runs at 20 TPS. Prefer engine facades and scheduled work over large per-tick scans, blocking operations, or unbounded loops.