Appearance
Content format
Content is JSON in content/<kind>/*.json, validated against the kind's JSON Schema. Layers (last wins): core shipped content, each extension in load order, then worlds/<name>/content/ host overrides. Ids are <owner>:<file basename> unless the file sets "id".
Zones (content/zones/*.json)
json
{
"name": "Meadow",
"width": 48, "height": 36,
"start": true,
"music": "default",
"layers": [
{"kind": "terrain", "tileset": "tilesets/water_to_grass", "fill": "upper",
"cells": ["....", "..##", "...."], "cells_mark": "lower", "solid": "lower"},
{"kind": "terrain", "tileset": "tilesets/grass_to_dirt", "fill": "lower",
"cells": ["....", "####", "...."], "transparent_lower": true},
{"kind": "props", "items": [{"prop": "props/village#3", "x": 10, "y": 12, "solid": true, "footprint": [1, 1]}]}
],
"collision": ["#...", "", ""],
"spawns": [{"id": "default", "x": 15, "y": 21}],
"portals": [{"x": 47, "y": 20, "w": 1, "h": 2, "to_zone": "core:grove", "to_x": 1, "to_y": 9}]
}Terrain layers use the library's Wang-corner tilesets (tilesets/<lower>_to_<upper>). Each tileset blends a lower terrain into an upper one. A layer paints one tileset:
fill:lower(default) orupper, the terrain everywhere before cells are applied.cells:heightstrings ofwidthchars;#marks a cell. Every vertex touching a marked cell takescells_mark(upperdefault, orlower). Or givecornersdirectly:height+1strings ofwidth+1chars,#= upper.solid:upperorlower. A cell is solid when all four of its corners are that terrain, so shorelines stay walkable and open water does not.transparent_lower: true: skip drawing cells that are fully lower, so the layer under it shows through (use for a path or a patch on top of a base layer).
Props: prop is props/<set>#<index> from the library's index.json. Props are y-sorted with characters. solid: true blocks the cell at (x, y), or footprint: [w, h] cells up and to the right of it. flat: true draws under everything (rugs, floor marks).
Tiles layers (kind: "tiles") place explicit tiles: {"tileset": "...", "cells": [[x, y, "tile_id"], ...]}.
Collision: optional override rows; # solid, . open, space inherits from the layers.
Spawns: tile coordinates; default is used for new characters. Portals are tile rectangles that teleport a player to to_zone at (to_x, to_y).
Zones smaller than 48x48 skip the replication radius filter; everyone in the zone sees everyone.
Items (content/items/*.json)
json
{"name": "Iron Sword", "icon": "items/weapons_armor#0", "stack": 1, "kind": "weapon",
"description": "A plain blade.", "value": 25, "rarity": "common", "data": {"attack": 4}}icon is a library reference. data is free-form for extensions (equipment reads slot, attack; crafting reads nothing). stack defaults to 1.
Host overrides
Drop a file into worlds/<name>/content/<kind>/ with the same id to replace an entry, or a new file (id becomes host:<basename>) to add one. Validate with the launcher's Content tab or:
mmorun-server --validate ./worlds/<name>/content