Skip to content

Custom items, Nadeo records, game rotation order, clip caps - #19

Open
zenril wants to merge 26 commits into
mainfrom
feature/custom-geometry-records-clips
Open

zenril wants to merge 26 commits into
mainfrom
feature/custom-geometry-records-clips

Conversation

@zenril

@zenril zenril commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Custom geometry embedded in maps: items rotate about the game's PivotPosition (carried through dump → placement → renderer), embedded meshes use the library's short material names, unreadable embedded items are salvaged from their raw bytes, and the bundled converter always runs before an external gbxdump.
  • Driving lines: the Replays dialog lists the map's validation ghost, TMX replays, and Nadeo world records (server-account auth, names read from the record files). One line per layer, Hide.
  • Rotation order: yaw/pitch/roll is applied yaw → roll → pitch (GAME_EULER_ORDER), verified against record ghosts driving over tilted free blocks. Renderer, transform operator and exporter share the one constant.
  • Clip caps: each clip is its own OBJ part and index.json carries units + clips with the game's clip groups; the renderer hides caps joined to a neighbour so platforms and effect blocks tile like in-game. Requires a fresh meshdump blocks extraction.
  • TMX search accepts a map id or link.
  • meshdump: embedzip, ghostname, richer iteminfo; the block dump merges into the live index.

Test plan

  • npx tsc --noEmit, npx vitest run (109 tests)
  • icecomp (TMX #84337): flipped custom items sit under the ghost line; club items textured
  • TMX #84440: tilted wall curves seat under the record ghost after the YZX fix
  • TMX #84442: three cruise platforms tile with turbines only at the run ends
  • Nadeo records list + record ghost load on Simple 25 (#353760)

🤖 Generated with Claude Code

https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY

zenril and others added 26 commits September 14, 2026 18:03
Custom geometry embedded in maps
- Items rotate about the game's PivotPosition: carried through the dump
  (pivotPos), the placement (pivot) and the renderer (pos + R * pivot).
- Embedded meshes name materials by game path; canonicalise to the
  library's short names (crystal exports and CPlugMaterialUserInst Link).
- Bundled converter runs first; an external gbxdump is only a fallback.
- Salvage embedded items GBX.NET cannot parse from their raw bytes.
- meshdump: embedzip, ghostname, richer iteminfo; block dump merges into
  the live index instead of overwriting entries added meanwhile.

Driving lines
- Replay dialog: TMX replays plus the map's validation ghost, one line per
  layer, Hide.
- Nadeo records (in-game leaderboard) via a dedicated server account:
  world top with names read from the record files; load a record's ghost.
- Map uid stored on the document; older maps resolve it through TMX.

Placement rotation
- Yaw/pitch/roll is applied yaw, then roll, then pitch (YZX), verified
  against record ghosts driving over tilted free blocks. One constant in
  core/math drives renderer, transform operator and exporter.

Clip caps
- Each clip is its own OBJ part; index.json lists units and clips per
  variant with the game's clip groups. The renderer hides caps joined to a
  neighbour (render/clipAdjacency), so special platforms and platform
  trims tile like in-game.

TMX search accepts a map id or link as well as a name.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
- Drawer pages with seam tabs: Track bits and TM Exchange (greyed out
  unless the map came from TMX).
- TMX card: name, TMX link, Play in game (Openplanet URL handler),
  uploader/authors with profile links, medal times, Nadeo finish count,
  awards, replays, downloads, upload date, ghost blocks, tags.
- Layers hold any number of lines (ghosts, keyed map / tmx:<replay> /
  nadeo:<account>); rows toggle lines on and off, each line in its own hue.
  Replaces the Replays dialog. Older records with a single ghost migrate.
- Bridge: /api/tmx/info, /api/nadeo/finishes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
Crystal items whose lightmap chunk or trailing modifier layers derail the
reader are repaired on an uncompressed image: remove the lightmap chunk
(then chunk 7, then drop modifier layers last-first) until the file
parses, and export the geometry layer as usual. Minimal repair first.
Adds `meshdump decompress`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
Layer rows expand to the layer's unique blocks, and each block to its
placements. Group eyes hide/show every placement of a block (hiddenBlocks
on the layer); placement eyes override individually (visible on the
placement). Click selects, double-click frames the placement. Renderer
honours both alongside isolation, near and far.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
Panel headers can carry action buttons; the Layers header gets "find
group" and "find block", which expand the tree to the viewport selection
and highlight the group (selecting all its placements) or the placement.
Rows show the selection state; click selects one, Shift-click adds.
Placement rows sit a level deeper with a guide line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…data

A painted block's colour is table[palette][slot]: the map picks a palette
(chunk 0x0304306C, read from the raw body; Classic when absent) and each
material names a colour target table. `meshdump colortables` exports the
game's tables and tags materials.json; the client resolves paint per
material, with the Default table's row for palettes a material table does
not restyle. An all-orange RPG map now renders orange instead of Classic
red/blue/green.

Also: framing/finding builds far placements on demand (big maps), and the
debug inspect shows paint resolution per material.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
- meshdump build <template> <placements.json> <out>: template-based map
  writer. Placements matching the template by name and pose reuse the
  original objects (skins, waypoints, macroblock links, item snapping
  survive); new or moved ones are constructed. Own map uid per document,
  stale lightmap dropped, output re-parsed before reporting.
- Bridge: /api/game/status, /api/game/save (finds Documents/Trackmania,
  also under OneDrive; template = cached TMX original or templateMap).
  TMX import now keeps the original file under maps/gbx.
- File > Save to Trackmania…
- meshdump lightmapinfo: what a map stores for computed shadows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… shadows

Lightmap frames are plain WebP atlases (light colour, a directional
greyscale, a probe grid) plus a cache with the object-to-atlas mapping.
lightmap-extract writes them as PNG, lightmap-inject writes edited PNGs
back into a renamed copy with its own uid, lightmapinfo deep prints the
whole structure. docs/NOTES-lightmap-baking.md records the format, the
three in-game test maps and the road to a baker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… logged

atmosphere rewrites a map's mood and/or adds an in-game MediaTracker clip
with a Fog block (colour, sky intensity, clouds), cloning clip nodes from
donor maps so chunk versions are the game's own. mediainfo lists a map's
clips. Research: a texture mod's Moods folder replaces the sky panorama,
clouds, reflection cubes and (untested) the mood settings with sun colour
and time of day.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
tools/sky_mod.py turns a panorama or a test chart into a texture mod that
replaces Moods/<Mood>/SkyColor.dds (BC6H_UF16 HDR, encoded here, headers
copied from the game's files), optionally clears the cloud layer and ships
an edited mood settings file. meshdump atmosphere gains mod=/modUrl=.
Experiment 2 (mood switch, fog clip) passed in game; experiment 3 maps
written.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… chart without text

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… second pass

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… is sunrise); fourth sweep

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…fth sun sweep

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…he fitted solar model

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…rse); sixth sun pass results

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…ge), written into the map on save

- core/atmosphere: custom sun/fog/sky on the document, compass helpers
- SunTool + SunDome: drag the sun over a dome around the map, moon opposite
- SkyPanel drawer page; viewport previews light, shadows, fog and the sky image
- meshdump moodmod: settings-only mood mod; build applies mood and points the map at the mod
- gameBridge: sky image store, sun/sky mod and fog clip on Save to Trackmania
- sky_mod.py: --append, panorama rows moved to their real height

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… paste a verified link

- reproducible, hash-named mod zips; the link is tied to the exact file and kept with the track
- /api/game/mod: download, reveal in the file manager (Windows/macOS/Linux), link check + write into the map
- share dialog after a save that wrote a new mod; Sky & light page shows or forgets the link

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
…ton on the Sky & light page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… checkpoint numbers in the viewport

- ghosts carry their own checkpoint times (meshdump ghost); passes = those times matched to the nearest waypoint
- waypoint types from the game's block/item definitions (meshdump waypoints -> waypoints.json), never from names
- layers panel: line rows (hue, eye, unload), expandable Start / Checkpoint n / Finish list with times, double-click flies there, LINE settings tab
- viewport: constant-size number tags over the geometry per line
- editor-placed waypoints get their waypoint property on save
- right dock resizable; list keeps scroll and updates selection in place (double-click no longer lands on another row)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
… the line tubes

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KHNGRntZ4yDXsBxenheDJY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant