What it is
A fully client-side viewer for OpenTTD, the open-source transport simulation game. You load a .sav file in the browser and it decodes the savegame, reconstructs the world — terrain, roads, rails, trams, stations, towns, industries, and vehicles — and draws it as a navigable 3D map. Beyond static rendering, it re-runs OpenTTD's own vehicle movement and pathfinding logic so road and rail vehicles drive their routes in real time.
How it works
- Parses the OpenTTD savegame container directly in JavaScript: it walks the chunked binary format, reads both legacy array and modern table chunks, and supports JGR's Patchpack extensions via the SLXI chunk. Per-tile data is unpacked into typed arrays mirroring OpenTTD's internal
Tile/TileExtendedstructs. - Includes a from-scratch NewGRF parser that reads a
.grfpseudo-sprite stream and dispatches Actions (0, 1, 2, 3, 4, 7/9, 8, D, F, 14) to extract industry, cargo, house, and object definitions plus generated town names. - Renders with Three.js, with geometry built off the main thread in Web Workers — separate workers per layer (roads, rails, trams, stations, buildings, foundations, trees, objects) feeding matching tile-source renderers.
- Simulates vehicles with faithful ports of OpenTTD's C++ logic: the per-tick
IndividualRoadVehicleController, drive-data movement tables, and the YAPF pathfinder for both road and rail, running in dedicated sim workers. - Built as two esbuild targets (browser app plus workers); no server or database — everything runs locally from the loaded save.
Why it's interesting
The hard part isn't the 3D — it's reproducing OpenTTD's exact tile-bit encodings and porting its pathfinding and movement code closely enough that vehicles follow the same paths the game would, all in TypeScript in the browser. It reads OpenTTD's binary save and NewGRF formats with no upstream library, including the JGR Patchpack variants.
Status
Hobby project, work in progress — actively mid-refactor from an earlier live-server architecture toward this standalone savegame-parsing design. The live version is the old version.