Old School Ops

MMO World Format

The open, engine-neutral file format GoMMO Studio saves an MMO world in, and how to turn it into your own game's files with an exporter.

Every game · updated 2026-10-04
On this page

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. unitsPerMetre in world.json says 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.
  • rot is [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 } ]
}
FieldMeaning
format, versionAlways "mmo-world" and the version the file was written for. A reader refuses a version newer than it knows.
nameThe world's name.
unitsPerMetreWorld units in a metre. Optional; 100 when left out.
kindsObject kinds. Each one replaces the default kind of the same name or adds a new one. Optional.
mapSettingsThe settings every map carries. When present it replaces the default list. Optional.
creatures, npcs, itemsThe catalogue a spawn, NPC or field picks from. id is what a map stores; model is drawn in the editor; scale multiplies the model.
exportersLua 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 } ]
}
FieldMeaning
kindThe name a map's objects use.
label, layer, colorHow the editor names, groups and colours it. layer defaults to kind.
sideclient or server: which half of your game reads it. Defaults to server.
shapepoint, box (uses size), radius (uses radius) or path (uses points).
modelWhat an object's model names: model (a model file), creature, npc, or nothing.
pointstrue when the object carries a point list as well as its shape, such as a spawn's spawn points.
rotates, scalesWhether the editor offers rotation and scale.
fixedtrue stops the editor adding new objects of this kind.
fieldsThe 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.

KindShapeModelFields
proppointmodel filecollision
spawnradius, with pointscreaturecount, respawn (seconds), wander, level, path
npcpointNPCrole, dialogue
portalboxtarget_map, target_marker, min_level
markerpointstart, respawn
regionboxtype, music, min_level, max_level
pathpathloop, speed
resourcepointmodel fileitem, amount, respawn
soundradiussound, volume, loop
triggerboxevent, once
lightradiustype, 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": []
}
FieldMeaning
title, groupThe map's name, and the heading it is listed under.
sizeThe flat ground a map with no terrain is drawn on, centred on the origin.
terrainA 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.
settingsValues for the world's map settings, by key.
objectsEverything placed on the map.
gridsPainted 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: true on a prop that is drawn as part of the map's terrain.glb instead of as a model of its own, because its placement in the game cannot be written as rot and scale.

Rules for tools that write the format

  • Keep every props key you do not understand, with its value unchanged. GoMMO Studio does: a field your world.json does 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, size and radius default 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.

FunctionReturns 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.

Something here wrong?

Out of date, incomplete, or assuming something it should not. Documentation errors are bugs, and this one arrives tagged and pointed at this page.

Loading…
Open the full search page