Install: download simutrans_blender_kit.zip below, then in Blender go to Edit → Preferences → Add-ons → Install…, pick the zip, and enable "Simutrans Blender Kit".
0.7 could take a finished model and produce a .pak. It could not help you start one, and it could not help you build the second, the fifth, or the train they run in. This release is those three things — 0.8.0, 0.9.0 and 0.10.0 land together.
The research that shaped it
can_follow (vehicle_desc.h:219) decides all coupling in Simutrans, and everything falls out of one line: prev_veh == NULL means "nothing in front of me" — the head of the train.
| Written | can_follow(NULL) — at the head |
can_follow(X) — behind X |
|---|---|---|
| (nothing) | true | true |
none |
true (NULL == NULL) | false |
any |
false (the prev_veh != NULL guard) |
true |
So any is how you say "middle only" — the reverse of how the word reads. vehicle_writer.cc:271 makes none a NULL child; pakset_manager.cc:238 makes any a real sentinel, and without that reassignment none would behave as any — the exact inversion of its meaning. The full table is in docs/constraints-in-simutrans.md.
This kit had that wrong in two places, and they contradicted each other. The panel told you Prev: none made a vehicle "run alone"; it means only at the head. datgen called any "anything at all", omitting that it forbids the head. The wrong one was the tooltip the artist reads.
What you get
Start a scene. Create Template builds the collections, the names, the orientation and the scale that every module in core/ already read but nothing ever wrote. The artist stopped typing internal names out of three lines of prose. Guides are Empties, never meshes — so they cannot land in the render or move the bounds.
Describe the train; the rules fall out. The Consist Manager takes the formation you intend — head-only, middle-only, optional cars, repeatable sections, reversible sets — and derives the constraint_prev / constraint_next pairs. The union is the point: a vehicle in two formations must accept every neighbour either gives it. Miss one and the game does not complain. It just refuses to let you build that train in the depot, and never says why.
Show Constraints prints a diff and writes nothing. A tool that silently rewrites the coupling of every vehicle in a project is one nobody should press.
Two liveries are two objects. There are no liveries in Simutrans — not "unsupported here"; the concept does not exist in the engine (grep -rlnw livery src/ finds nothing). Variants say so, and make the two objects.
See all eight headings. Not a preview of the render — it is the render, of eight headings, assembled onto one page afterwards from the finished frames. Same camera, same sun, because it calls the same two functions the final render is made of. Laid out in the engine's own order (s w sw se n e ne nw), so the page is labelled rather than reordered.
A real component catalogue — wheelset, two-axle bogie, pantograph, headlight, coupler. Built, not committed as art: tools/build_components.py defines each from primitives, so the provenance is the source and the licence is unambiguous. Real numbers: 0.92 m wheels, 1.435 m gauge, UIC coupler height. No third-party art.
Package it. A zip with the .dats, the sprites, your licence, and a manifest naming every file, its checksum, and whether it is generated or authored. It refuses to build if something is missing, and it uploads nothing. It makes a file. Sending it is your decision.
Also in this release: the example assets
Three commits had landed on main and never got a version. The 9000's payload split was wrong and every check passed — the spec guarded the totals, nothing guarded the arithmetic under them, and six literals in the module summed to 186 against the unit's own measured 178. A whole car's worth of seats. The splits moved into spec.json; car_totals names the fact each column must sum to, and a spec whose columns do not add up does not load. A number you cannot type twice cannot drift.
And the Metro 7000 source is here and licensed CC BY 4.0 — it had been on the forum for a day while its source lived on one disk with no licence, so nobody could rebuild the .pak they had downloaded.
Grounded and verified
Every coupling rule is derived from the engine's own can_follow, not from convention. The model reproduces the shipped Civia constraint for constraint. All eight preview headings are asserted byte-identical to the final render. The v1 → v2 document migration is tested against a literal phase-2 document, not one this code produced; a document from the future is handed back untouched rather than guessed at.
Each main function was deliberately broken in an isolated copy to prove its tests fail: reuse a dead key → 4 and 7 failures; accept an impossible formation → 1; lose a neighbour past an optional car → 2; write none where middle only needs any → 4; lose repeatable self-coupling → 3; invent a total → 1; accept a future document → 4.
45 suites green: core, the Blender pipeline, makeobj compilation, and headless loads in the real pak128.
Not measured, honestly:
- Blender 4.x is untested. Everything here ran on Blender 5.1.2, the only version on the build machine.
bl_infodeclares 4.2 as the minimum and the README says "4.x/5.x" — that is a declared target, not an executed one. - Linux and macOS are untested. The build machine is Windows. Paths go through
os.path, which is an argument, not a result. - One break produced no failures and the test was not weak: changing the preview camera's distance is a no-op for an orthographic camera, exactly as documented.
- The Civia's per-car splits remain unguarded — it declares no
formation, so only the field checks apply to it.