Files
llamamod/notes/editor-format.md
T

5.6 KiB
Raw Blame History

.llamalevel – level project format (version 1)

A zip file (deterministic: fixed entry times, level.json first, then thumbnail.png, then the assets sorted by path). Code: editor.io.ProjectIO, SceneDiff, NodeCodec.

Entry Content
level.json header + the changes against the reference scene (below)
thumbnail.png optional preview (also used for the TestLevel loading picture)
assets/<name>/… imported meshes with their MTL/textures/buffers (MeshAsset.file points here)
assets/pages/<id>.png pixels of added texture pages (lossless: ABGR1555 ↔ RGBA with alpha 0/128/255)

No original game data. A project is stored as the difference to a reference scene that is rebuilt from the user's own CD when the project is loaded:

  • kind: "edit" – reference = the original level base imported unchanged (Templates.original).
  • kind: "new" – reference = base with all tiles, tile models, objects and waypoints removed and visibility regions off (Templates.newLevel). The base contributes object code (STPC), textures, zones (fog/music), lights and sound. Default base t1l1m001 (village). A newly created project (Project.create) additionally removes, as ordinary edits stored in the diff, everything bound to the base's positions (Templates.clearBaseLeftovers, since 0.2.0): all zones except the start zone (flag 8), all non-directional lights, waypoints, and sets every region mask to "all". The reference stays unchanged, so projects saved before keep their zones and lights. Textures stay (STPC object models index them).

Building the same project with the same CD gives a byte-identical WAD (WadBuilder is deterministic; brushes use the stored seed).

level.json

{
  "formatVersion": 1,
  "app": "LlamaMod level editor",
  "kind": "new",                         // "edit" | "new"
  "base": "t1l1m001",                    // base level (CD wads/<base>.wad)
  "baseSha256": "9cff…",                 // of the base WAD; a mismatch gives a load warning
  "name": "Testwelt",                    // copies of settings for listing without the CD
  "targetChapter": 2,                    // TestLevel chapter for new levels (0 = none)
  "nextId": 264,                         // counter for new node ids ("kind:nN")
  "settings": { "<prop>": value, … },    // changed LevelSettings props
  "regions":  { "<prop>": value, … },    // changed Regions props
  "nodes": {
    "<kind prefix>": {                   // chunk, page, tex, anim, model, tile, wp, strat, zone, light, mesh, brush
      "removed": ["tile:12", …],         // reference nodes deleted
      "changed": { "strat:11": { "x": 120716, … } },   // changed props of reference nodes
      "added":   [ { "id": "strat:n1", "<prop>": value, … } ],   // all persistent props (+ "brushKind")
      "order":   ["tile:0", …]           // only if the list order differs from reference order + added
    }
  },
  "…": …                                 // unknown top-level keys are kept when saving
}

Node kinds, ids and properties: notes/editor-api.md (every persistent, settable Prop). Values by PropType: numbers (INT/FIXED/ANGLE/FLAGS/COLOR as integers, DOUBLE), booleans, strings, REF = node id (or null). Arrays: up to 64 elements as JSON lists, longer ones as {"i32": base64} (int32 LE), {"f64": base64} (float64 LE) or {"bytes": base64}; a short double array containing -0.0 is written as f64 too (JSON numbers drop the sign; since 2026-11-07). A changed array of unchanged length is stored as runs of the changed elements only: {"runs": [[start, values], …]} (values encoded as above) – e.g. editing a few vertices or pixels of an original page stores just those values. Runs apply to the reference value read before any property of the node is set (setting a model's vertices clears its header; until 2026-11-07 header runs after a vertex change failed with "project file is damaged: NullPointerException", e.g. on llamamod --editor-import of a levelbuild WAD).

Loading: reference scene → removals → create all added nodes (all kinds, so references across kinds resolve) → set values of added/changed nodes and settings → apply order. Problems (reference to a missing node, a removed id that does not exist) become load warnings, not errors. Unknown properties of nodes are kept and written back (forward compatibility); a file with a higher formatVersion loads with a warning.

Ids are positions in the original WAD

Reference node ids are kind:index of the original WAD, so a project stays valid as long as the base level is the same file (checked through baseSha256). Deleting reference nodes keeps the ids of the others (they are not renumbered in the project), but it does change the indices written to the WAD: strat scripts that address tiles by index (stMapreplace / stMapadd) may then hit other tiles – prefer moving or hiding original tiles over deleting them.

Mods

<data>/levels/*.llamalevel are listed as mods (mods.levels.LevelProjectSource, see notes/mod-levels.md). CLI:

llamamod --editor-import <level.wad|t1l1m001> <project>   # edit project (diff to the CD original)
llamamod --editor-new <project> [base] [--name <name>]    # empty new level
llamamod --editor-build <project> <out.wad>               # build (prints statistics, warnings)
llamamod --import-level <project>                         # copy into <data>/levels
(all take --cd <CD folder>; default: the installed original CD of the data folder)

Example: examples/testwelt.llamalevel (the Test World as 125 brushes + 55 objects, 7 KB).