An MMO World is a folder. It holds one world.json, one folder per map, and your own models. Every file is plain JSON or a standard 3D format, so any tool or game can read it without GoMMO Studio. This page is the full specification, version 1.
The folder
my-world/
world.json the world: its unit, object kinds, map settings and catalogue
maps/
start/
map.json one map: its settings, objects and painted grids
terrain.glb optional ground model for this map
darkwood/
map.json
models/ your glTF, GLB, OBJ and FBX files, in any folders you like
exporters/
example.lua scripts that write your game's own files
A map's key is its folder name: lower case letters, digits, _ and -, at most 64 characters. Paths inside the files use forward slashes and are relative: a model path to the world folder, a terrain path to its map's folder.
Units and axes
- Positions are in world units.
unitsPerMetreinworld.jsonsays how many make a metre; it defaults to 100, so a world unit is a centimetre unless you say otherwise. - Z is up. X and Y lie on the ground.
- Models are read in metres, the glTF convention, and scaled by
unitsPerMetre. glTF, OBJ and FBX files are all converted to Z up as they load. rotis[yaw, pitch, roll]in degrees. Yaw turns about +Z, counter-clockwise seen from above, with 0 facing +X. A positive pitch tips the object's +X axis down. Roll turns about the tipped X axis. Written as the object's axes in world space:
X = ( cos(yaw)cos(pitch), sin(yaw)cos(pitch), -sin(pitch) )
Y = ( cos(yaw)sin(pitch)sin(roll) - sin(yaw)cos(roll),
sin(yaw)sin(pitch)sin(roll) + cos(yaw)cos(roll), cos(pitch)sin(roll) )
Z = ( cos(yaw)sin(pitch)cos(roll) + sin(yaw)sin(roll),
sin(yaw)sin(pitch)cos(roll) - cos(yaw)sin(roll), cos(pitch)cos(roll) )
A model-space point p lands at pos + X*p.x*scale.x + Y*p.y*scale.y + Z*p.z*scale.z.
world.json
{
"format": "mmo-world",
"version": 1,
"name": "My World",
"unitsPerMetre": 100,
"kinds": [],
"mapSettings": [],
"creatures": [ { "id": "wolf", "name": "Grey Wolf", "model": "models/wolf.glb", "level": 3, "group": "Beasts" } ],
"npcs": [ { "id": "smith", "name": "Blacksmith", "model": "models/smith.glb", "group": "Town" } ],
"items": [ { "id": "copper_ore", "name": "Copper Ore", "group": "Ore" } ],
"exporters": [ { "name": "My server", "script": "exporters/server.lua", "output": "../server/data", "onSave": true } ]
}
| Field | Meaning |
|---|---|
format, version | Always "mmo-world" and the version the file was written for. A reader refuses a version newer than it knows. |
name | The world's name. |
unitsPerMetre | World units in a metre. Optional; 100 when left out. |
kinds | Object kinds. Each one replaces the default kind of the same name or adds a new one. Optional. |
mapSettings | The settings every map carries. When present it replaces the default list. Optional. |
creatures, npcs, items | The catalogue a spawn, NPC or field picks from. id is what a map stores; model is drawn in the editor; scale multiplies the model. |
exporters | Lua scripts that write your game's files. See Exporters. |
Object kinds
A kind says what an object is, how the editor shapes it, and which fields it carries.
{
"kind": "chest", "label": "Treasure chest", "layer": "chests", "side": "server",
"shape": "point", "model": "model", "color": "#c08040", "rotates": true,
"fields": [ { "key": "gold", "label": "Gold", "type": "int", "default": 10 } ]
}
| Field | Meaning |
|---|---|
kind | The name a map's objects use. |
label, layer, color | How the editor names, groups and colours it. layer defaults to kind. |
side | client or server: which half of your game reads it. Defaults to server. |
shape | point, box (uses size), radius (uses radius) or path (uses points). |
model | What an object's model names: model (a model file), creature, npc, or nothing. |
points | true when the object carries a point list as well as its shape, such as a spawn's spawn points. |
rotates, scales | Whether the editor offers rotation and scale. |
fixed | true stops the editor adding new objects of this kind. |
fields | The kind's typed values. |
A field has a key, a label, a type, an optional default, and help text. Types are text, int, float, bool, color (#rrggbb), enum (with options, each a value and a label), and the references creature, npc, item and map, which the editor fills from the catalogue or the world's map list.
The default kinds
A world that lists no kinds gets these. A new world writes them into its world.json so you can change them.
| Kind | Shape | Model | Fields |
|---|---|---|---|
prop | point | model file | collision |
spawn | radius, with points | creature | count, respawn (seconds), wander, level, path |
npc | point | NPC | role, dialogue |
portal | box | target_map, target_marker, min_level | |
marker | point | start, respawn | |
region | box | type, music, min_level, max_level | |
path | path | loop, speed | |
resource | point | model file | item, amount, respawn |
sound | radius | sound, volume, loop | |
trigger | box | event, once | |
light | radius | type, color, intensity |
The default map settings are type, min_level, max_level, music, sky, fog_color, fog_start and fog_end.
map.json
{
"format": "mmo-world-map",
"version": 1,
"title": "Willow Vale",
"group": "Starter Zones",
"size": [20000, 20000],
"terrain": "terrain.glb",
"settings": { "music": "vale_day", "min_level": 1 },
"objects": [
{ "id": "spawn-1", "kind": "spawn", "name": "Grey Wolf", "model": "wolf",
"pos": [4500, 3500, 0], "radius": 900,
"points": [[4200, 3300, 0], [4800, 3700, 0]],
"props": { "count": 4, "respawn": 45 } }
],
"grids": []
}
| Field | Meaning |
|---|---|
title, group | The map's name, and the heading it is listed under. |
size | The flat ground a map with no terrain is drawn on, centred on the origin. |
terrain | A model file in the map's folder, drawn as the map's ground and used for ground snapping. GoMMO Studio can build one from a greyscale heightmap image. Optional. |
settings | Values for the world's map settings, by key. |
objects | Everything placed on the map. |
grids | Painted per-cell layers, such as a walkable grid. |
An object has an id unique on its map, a kind, an optional name and model, a pos, and as its kind needs: rot, scale, size (a box's half extents), radius and points. Its fields go in props, keyed by field key. A value that equals its field's default may be left out; a reader uses the default.
A grid has a key, a label, w and h in cells, an origin (the corner of cell 0,0), a cell edge in world units, and cells, a base64 string of w * h bytes where cell (x, y) is byte y * w + x. A palette names what each byte value means.
The walkable grid
A grid with the key walk is the map's walkable area for a server's pathing: a cell holding 0 is walkable and 1 is blocked. GoMMO Studio generates it from the map's geometry (the Map tab's Walkable area) by sampling the top surface at each cell's centre and blocking a cell with no ground, or whose rise to a neighbour is steeper than the slope and higher than the step you set.
How the maps connect
A field whose type is map names another map. With the default kinds that is a portal's target_map, and its target_marker names an object on the target map by its name. A marker whose start is true makes its map a start map. GoMMO Studio's World graph reads these to show every map, the portals between them, the maps no start reaches, the maps with no portal out, and portals into a level range much higher than the map they leave.
Maps exported from a game
A map GoMMO Studio exports from a game client keeps the game's own kinds and fields, so a spawn from RF Online carries RF's fields. Two props may appear on its objects:
game_model: the game's own model key, on a prop whose model was not exported.in_terrain:trueon a prop that is drawn as part of the map'sterrain.glbinstead of as a model of its own, because its placement in the game cannot be written asrotandscale.
Rules for tools that write the format
- Keep every
propskey you do not understand, with its value unchanged. GoMMO Studio does: a field yourworld.jsondoes not define stays in the file through every save. - Keep object ids stable. Other files may refer to them.
- Leave out what you would write as zero:
rot,scale,sizeandradiusdefault to nothing turned, scaled or sized.
Exporters
An exporter is a Lua script in the world folder that turns the world into your game's own files. GoMMO Studio runs it from the World tab, and after every save when onSave is true. The script runs in a sandbox: it cannot open files or run programs. It reads the world through these functions and hands back what it wants written.
| Function | Returns or does |
|---|---|
world() | world.json as a table, with the kinds and map settings filled in from the defaults. |
maps() | Every map as a table, with its key added. Lists start at 1 in Lua, so o.pos[1] is X. |
write(path, text) | Writes text to path under the exporter's output folder. A path that leaves that folder is refused. |
json(value) | Turns a table into indented JSON text. |
log(text) | Shows a line in the editor after the run. |
output is relative to the world folder and may lie outside it, so an exporter can write straight into a server's data folder. It may not be the world folder itself or its maps folder. A file whose bytes have not changed is left untouched. A script that runs for more than a minute, or loops without end, is stopped.
local lines = { "map,id,creature,x,y,z,count" }
for _, m in ipairs(maps()) do
for _, o in ipairs(m.objects) do
if o.kind == "spawn" then
local p = o.props or {}
lines[#lines + 1] = string.format("%s,%s,%s,%g,%g,%g,%d",
m.key, o.id, o.model or "", o.pos[1], o.pos[2], o.pos[3], p.count or 1)
end
end
end
write("spawns.csv", table.concat(lines, "\n") .. "\n")
A new world comes with exporters/example.lua, which writes a spawn table and one JSON file per map. Copy it and change what it writes.