Docs Enter the town

Docs · Games on your plot

Games on your plot

Your plot can have its own game: a few lines of JavaScript that make lanterns to collect, a race to a goal or a puzzle for friends. Visitors walk through your plot's game portal into the game's own space and choose Play.

The game runs in a sandbox in each player's browser. It cannot see their account, their wallet, their files or other plots, and the server never runs it. Code stays paused until a visitor chooses Play.

Make a game

  1. Open your plot in the editor, then Code & interactions › Plot game.
  2. Start from Starter game or Lantern Collect (two or more players), or write your own.
  3. Save game. It is stored in your plot, and a portal to it is placed in the cell you are editing. Move the portal where you like.
  4. Test on my plot runs it alone, in your browser, on your plot. Walk onto the plot to play.
  5. Publish the plot as usual (Share › Publish). Your wallet signs the plot with its game. A game that breaks a rule is refused before your wallet signs, with what to fix.

With an AI agent, the same tools are open through the MCP server and the SDK: describe_game_api, set_game (your code, or "starter" / "lantern-collect"), get_game and remove_game. Then give the owner preview_link and publish with their wallet, as with any draft (For AI agents).

The game API

PLOT GAMES (teztopia-plot-game/1)
A plot may hold one game: plain JavaScript that runs in a sandbox only after a visitor walks through the plot's game portal and chooses Play. The game cannot reach the page, the network, storage, wallets or other plots; it talks to the town only through `game`. Positions are metres from the plot's north-west corner (x east, z south, y up); the playable box is the plot's square, 16 m high.

Events (register once each at startup):
  game.on('start',   ({ me, players, bounds }) => {})   bounds: { width, depth, height }
  game.on('tick',    ({ dt, time, input }) => {})       about 20 times a second (10 on slow phones); input: { position: [x,y,z], inside, action }
  game.on('message', ({ from, data }) => {})            JSON another player sent with game.send
  game.on('join',    ({ player }) => {})                player: { id: 'p3', nick: 'Ana' }; never a wallet
  game.on('leave',   ({ player }) => {})
  game.on('button',  ({ index, label }) => {})          a button of your panel was pressed

Commands:
  game.spawn(id, { shape: 'box'|'sphere'|'cylinder', color: '#rrggbb', position: [x,y,z], scale })
  game.move(id, [x,y,z])   game.color(id, '#rrggbb')   game.remove(id)
  game.panel({ title, lines: [...], buttons: [...] })   plain text in the town's own labelled panel
  game.sound('pickup'|'score'|'win'|'lose'|'tick'|'buzz')
  game.send(value)          JSON to the other players in the same game (up to 512 bytes, 10 a second)
  game.me, game.players     copies; room ids and nicknames only

Limits: 64 KB of code, 16 MB of memory, 1000 ms to start, 40 ms per event, 96 commands per event, 64 objects of up to 4 m each inside the plot, a panel of one title (40 characters), 6 lines (80) and 3 buttons, up to 16 players. Breaking any limit stops the game with a message saying which.
House rules: no money of any kind (no payments, tips, bets or prizes); panels may not mention wallets, links, web addresses or the town's own name; the host can switch a plot's game off. Multiplayer messages come out of the plot's own daily allowance (750 requests for a 16 m plot, more for bigger plots); when it is spent the game closes until 00:00 UTC.
Publishing: the code is saved in the plot and published with the rest of the plot by the owner's wallet signature. Add a portal to the game on the plot so visitors can reach it.

What a game costs your plot

Safety and house rules