-
Notifications
You must be signed in to change notification settings - Fork 113
tutorial_roadmap
title: Tutorial Tech Tree description: The complete planned NeL tutorial dependency tree — branches per engine domain, playable mini-game capstones, conventions, and validation strategy published: true date: 2026-07-05T00:00:00.000Z tags: editor: markdown dateCreated: 2026-03-14T00:00:00.000Z
The NeL tutorials form a tech tree: a dependency graph rather than a single sequence. Each tutorial names exactly one starts-from parent — the tutorial whose finished code is your starting point — plus any assumes parents whose concepts are referenced but not built upon. Completed tutorials are linked from the tutorials index; this page is the master plan and status tracker.
Legend: ✅ written · 🔨 planned · ⚠ has an engine/tooling side-quest that must be resolved while writing it · 🧱 gated on the asset-tooling side-quests (cannot be built with what loads today).
Buildable today: everything not marked 🧱 runs on assets that already work — procedural content generated in code, loose files from a ryzomcore_graphics checkout (CPath search paths + extension remapping, the pattern the water demo uses), or prebuilt Snowballs/Ryzom game data (landscape zones, collision banks, sound banks). No asset build pipeline or new load management is required for that subset. The 🧱 set is exactly: A2, A3, A5 (TOML sidecar importer), X1 (through its A2 dependency), and W2 (web asset streaming).
Prebuilt data is a bootstrap, not the asset story. Tutorials must not normalize skipping the build pipeline — relying on shipped data sets a pipeline-avoidance precedent, and it hard-blocks anything whose source assets only exist as 3ds Max files. The way out is the headless .max export pipeline (side-quest 5 below): the existing partial .max parser, extended until the 3ds Max dependency is eliminated from the export route entirely. Until that lands, prebuilt data is acceptable scaffolding; every tutorial that uses it should treat the data as a placeholder for assets built from source.
- One or two new concepts per tutorial. Complete, compilable code at the end of every page.
- Every tutorial includes a screenshot of the final state, at minimum. Visual tutorials should also show intermediate states where a step visibly changes the output; console tutorials show the terminal output. The validation runs produce these automatically (headless capture), so they stay in sync with the code. Screenshots are cropped to the application render area only — capture the canvas element (or the client area of a native window), never the surrounding HTML page frame, padding, or window decorations.
- Header block on every page: Starts from · Assumes · Leads to.
-
Reference projects are zipped, not committed. Each tutorial's finished project is archived as a downloadable zip (produced by the validation runs). The mini-game capstones are the exception: they live in the repo under
tutorials/<gamename>/so they stay buildable and playable. - WebGL is first-class. Rendering tutorials are validated both native and as Emscripten builds (headless browser + SwiftShader harness). Full streamed-asset web builds are gated on the asset-loading work (see W2).
-
Assets: Ryzom assets (
ryzomcore_graphics), procedural geometry built in code, and OpenGameArt (license noted per asset). Mesh export via the existing 3ds Max plugin, and — to be built during the implementation rounds — a Blender/OBJ route with a TOML sidecar carrying NeL material/properties metadata, matched to objects by instance name (human-readable, replacing the XML habit for this use case). Ryzom's own.maxsource assets are reached through the headless.maxpipeline (side-quest 5) rather than by consuming prebuilt data. - Validation: the tree is designed to be walked by a fully autonomous agent session in topological order: unpack the parent zip → apply the tutorial's steps → compile → run → screenshot/assert → archive the zip → refresh the wiki page code. API drift, exporter gaps, and stale service setups get fixed as side-quests during the walk.
Everyone passes through here.
| Id | Tutorial | Starts from | Status |
|---|---|---|---|
| T1 | Compile NeL — Windows / Linux | — | ✅ |
| T2 | Set up a new personal project | T1 | ✅ |
| T3 | Write a main game loop | T2 | ✅ |
| T4 | Hello World — driver, window, text | T3 | ✅ |
Forks from the trunk before the 3D chain — these are windowless programs, and later branches assume them.
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| I1 | Config files & search paths — CConfigFile, CPath
|
T3 | 🔨 | |
| I2 | Logging & debugging — displayers, filters, asserts, reports | T3 | 🔨 | |
| I3 | Serialization — IStream, CIFile/COFile, versioning |
T3 | I2 | 🔨 |
| I4 | Console commands & variables — NLMISC_COMMAND, ICommand
|
T4 | I2 | 🔨 |
| I5 | Georges data sheets — .typ/.dfn/forms, UFormLoader
|
I1 | I3 | 🔨 |
| I6 | Packed sheets — compiling sheets for fast startup | I5 | 🔨 | |
| I7 | Localization — .uxt, CI18N
|
I1 | 🔨 | |
| I8 | Threads & async tasks — IThread, CTaskManager
|
T4 | I2 | 🔨 |
| I9 | BNP/SNP packaging & streamed packages | I1 | 🔨 ⚠ ties into the web asset story (W2) |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| D1 | Primitives & camera | T4 | ✅ | |
| D2 | Textures & alpha blending | D1 | ✅ | |
| D3 | Scene & shapes | D2 | ✅ | |
| D4 | Scene lighting | D3 | ✅ | |
| D5 | Animation playback | D4 | ✅ | |
| D6 | Particle systems | D5 | ✅ | |
| D7 | Render targets & post effects — RT, fullscreen passes | D2 | 🔨 ref: planar_reflection sample |
|
| D8 | Water surfaces — runtime CWaterShape, envmap water |
D3 | I1 | 🔨 ref: nl_sample_water procedural pools |
| D9 | Planar reflections & replicated render passes — pass API, IStereoDisplay loop |
D8 | D7 | 🔨 ref: nl_sample_water
|
| D10 | Instance groups & scenery — village/IG loading | D3 | I1 | 🔨 |
| D11 | Landscape rendering — .zonel, tile banks | D3 | I1 | 🔨 uses prebuilt Snowballs/Ryzom landscape data |
| D12 | Vegetation & micro-vegetation | D11 | 🔨 | |
| D13 | Clusters & portals — indoor culling | D10 | 🔨 | |
| D14 | Character crowds & CLod impostors | D5 | 🔨 optional | |
| D15 | Sky, weather & day-night cycle | D4 | D11 | 🔨 optional |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| A1 | Asset formats & data flow — .shape/.skel/.anim/.ps, search paths, BNP | D3 | I1 | 🔨 |
| A2 | Static mesh from Blender/OBJ — TOML sidecar for NeL material/properties, matched by instance name | A1 | 🔨 ⚠ 🧱 importer tooling to build | |
| A3 | NeL material properties in depth — specular, lightmaps, water flags, the sidecar schema | A2 | 🔨 ⚠ 🧱 sidecar schema grows here | |
| A4 | The .max export route |
A1 | 🔨 plugin docs exist; to be written against the headless .max pipeline (side-quest 5), with the 3ds Max plugin as the legacy reference |
|
| A5 | Skeletons & animation export | A2 | D5 | 🔨 ⚠ 🧱 sidecar extension |
| A6 | Authoring particle systems — Object Viewer / OVQT editor | D6 | 🔨 | |
| A7 | Sourcing assets — Ryzom data, OpenGameArt, licensing | A1 | 🔨 |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| S1 | Playing sounds — UAudioMixer, sample banks, USource
|
T4 | I1 | 🔨 uses existing packed sound data |
| S2 | 3D audio in the scene — positioning, listener | D3 | S1 | 🔨 |
| S3 | Music & ambience — groups, volume controllers | S1 | 🔨 | |
| S4 | Sound sheets & banks | S1 | I5, I6 | 🔨 |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| N1 | Messages & callbacks — two-program chat (layer 3) | T3 | 🔨 ref: nel/samples/net/chat
|
|
| N2 | Building a service — IService, naming service |
N1 | I1 | 🔨 |
| N3 | Unified services — layer 5, service-to-service | N2 | 🔨 | |
| N4 | Running a mini shard — naming/login/welcome + MySQL | N3 | 🔨 ⚠ nelns/Snowballs service setup vs Ryzom's shard unifier is out of sync; the Ryzom database setup is canonical — verify and upgrade nelns while writing this | |
| N5 | Networked scene — position sync between clients | D3 | N2 | 🔨 |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| P1 | PACS primitives — UMoveContainer, move & collide, headless |
T4 | 🔨 | |
| P2 | Collision in the scene — visualized primitives | D3 | P1 | 🔨 |
| P3 | Character controller — walking, sliding, follow camera | P2 | D5 | 🔨 |
| P4 | Landscape collision — .rbank/.gr, UGlobalRetriever, ground snap |
P3 | D11 | 🔨 uses prebuilt collision banks |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| G1 | Interface XML & action handlers | D2 | I1 | 🔨 |
| G2 | Lua-scripted UI | G1 | 🔨 | |
| G3 | Game HUD & menus | G1 | 🔨 |
| Id | Tutorial | Starts from | Assumes | Status |
|---|---|---|---|---|
| W1 | Building for the browser — toolchain, ports, preloaded data | D3 | 🔨 | |
| W2 | Streamed web assets — SNP over HTTP(S) | W1 | I9 | 🔨 ⚠ 🧱 blocked on engine work: SNP hash-list streaming is not integrated with the Emscripten build and isn't pipelined (slow for many small assets) — see the asset loading review |
| W3 | Publishing a browser demo — HTML shell, input caveats, control panels | W1 | 🔨 ref: the water demo's panel pattern |
Endpoints of the tree — real, playable games, committed in the repo under tutorials/<gamename>/. Each is also a validation vehicle for its branch joins.
| Id | Game | Starts from | Assumes | Notes |
|---|---|---|---|---|
| X0 | Paddle — breakout/pong-class micro-game, procedural assets | D2 | I1, T4 | Early payoff checkpoint: loop, input, text, 2D draw. Cheap to validate. |
| X1 | Rolling ball — MTP-Target / Monkey Ball class arcade game: ball on tilting course meshes, follow camera, checkpoints, timer | P2 | D4, S1, G3, A2, X0 | 🧱 Levels exported through the Blender/TOML sidecar route (exercises A2/A3); procedural + OpenGameArt assets. (Could start with fully procedural courses to decouple from A2 if the tooling lags.) Optional later round: multiplayer via N5, honoring the MTP-Target lineage. |
| X2 | Snowballs-class mini world — third-person character on a landscape, snowball combat, multiplayer shard | P4 | D10, D13, N4, N5, S2, G3, A7 | Ryzom/Snowballs assets. The nelns/shard-unifier/MySQL verification vehicle (see N4). WebGL target once W2 lands. |
Future candidate bucket (unscheduled): kart race on landscape, tower defense with particle weapons, fishing game on reflective water (D9 showcase).
Work items expected to surface while an autonomous session walks the tree, tracked here so they're scoped deliberately rather than discovered painfully:
-
TOML sidecar mesh import tooling (A2/A3/A5): Blender/OBJ → .shape with a human-readable
.tomlsidecar for NeL material/properties (water flags, specular, lightmap options, collision), matched by instance/object name. Preferred over growing more XML. - nelns / Snowballs service refresh (N4/X2): verify nelns against Ryzom's shard unifier MySQL handling; the Ryzom database setup is canonical; upgrade Snowballs' service usage where stale.
- Web asset streaming (W2): SNP hash-list downloads integrated with the Emscripten build, with proper pipelining over HTTP(S) — currently sequential-as-needed and slow for many small assets. Planned separately (asset loading review).
- Exporter patch-ups as tutorials exercise features the tools don't cover yet (the water material v15 additions set the precedent).
-
Headless
.maxexport pipeline — eliminate 3ds Max from the export route. Full codified design, invariants, known defects, and extension rules: Pipeline Max Design; gap analysis and pick-up map: pipeline_max coverage. Status 2026-07-17: the parser innel/tools/3d/pipeline_maxhandles the OLE compound container (own native backend), the chunk storage layer, the DLL/class directories, and typed scene classes across the builtin/update1/epoly/biped/nelpatch plugins — and the typed-graduation series (design §10j-bis..§10j-dix) moved every corpus-validated format decoder the export tools had accumulated into the library proper, each with a corpus-wide bit-exact re-encode proof. The export back half EXISTS: headlesspipeline_max_export_*tools cover everyNelExport*surface (shape, anim, skeleton, swt, ig+ligo, zone, collision/cmb, PACS primitives, vegetable, clod), plus the standalone lightmapper and the max2gltf route (max2gltf plan — whole-corpus byte-parity closed), all validated by the 24-gate ctest battery: byte-identical T1/T2 roundtrip over the ~8,700-file corpus plus per-format diffs against the prebuilt reference data (byte-exact tiers where the reference build allows, x87-float-eq tiers where it doesn't). Remaining for the tutorial goal: wiring the headless tools intobuild_gamedata's1_export.pysteps in place of 3ds Max, which is what retires the prebuilt-data scaffolding for good.
Branch-parallel, cheapest-payoff first: Infrastructure (I1–I4) and X0 → Sound S1/S3 and Network N1–N3 → Asset A1/A2 (tooling side-quest) → PACS P1–P3 → X1 → GUI G1/G3 → Landscape D10–D13 and P4 → N4 (nelns side-quest) → X2 → Water/RT D7–D9 and Web W1/W3 → W2 when the asset work lands.
The headless .max pipeline (side-quest 5) runs in parallel with the whole schedule — its roundtrip/snapshot test suite is independent of any tutorial and can start immediately; tutorials that bootstrapped on prebuilt data get their assets re-sourced through the pipeline as it matures.