# `.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//…` | imported meshes with their MTL/textures/buffers (`MeshAsset.file` points here) | | `assets/pages/.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 ```json { "formatVersion": 1, "app": "LlamaMod level editor", "kind": "new", // "edit" | "new" "base": "t1l1m001", // base level (CD wads/.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": { "": value, … }, // changed LevelSettings props "regions": { "": value, … }, // changed Regions props "nodes": { "": { // 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", "": 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 `/levels/*.llamalevel` are listed as mods (`mods.levels.LevelProjectSource`, see `notes/mod-levels.md`). CLI: ``` llamamod --editor-import # edit project (diff to the CD original) llamamod --editor-new [base] [--name ] # empty new level llamamod --editor-build # build (prints statistics, warnings) llamamod --import-level # copy into /levels (all take --cd ; default: the installed original CD of the data folder) ``` Example: `examples/testwelt.llamalevel` (the Test World as 125 brushes + 55 objects, 7 KB).