destroyulator/LANES/LANE10-record-store.md
Monster Robot Party 8e61640c38 LANE10: SITE 7 — the real shop, imported from its own database
The level the whole game started as, and the only one that isn't authored.

robotmonster.party/store/ is assembled procedurally from Postgres (the wowplatter
virtual_* schema, served by recordgod), and this game's sites are already data — so
tools/import_store.py reads the live shop and emits assets/store/shop_floor.json:
the actual 6.66 x 9.51 m floor, 35 racks across 21 archetypes, 278 bins carrying
their real genre labels (HARD TRANCE, $12-$15 EURO/ITALO HOUSE), 21,159 records
of stock. Levels.record_store() loads it; 'store' joins ORDER as the seventh site.

The shop's schema IS the cascade. virtual_crate.rack_id already records which rack
holds which bin, so bins arrive frozen and supported_by their rack and none of the
structure is authored. To carry that, smashables gained two optional generic keys —
'id' and 'supported_by' — so any level can express support as data. Every existing
level is unaffected.

Two reconciliations, because a storefront is a renderer:
- Mesh sizes are a lie: 21 archetypes share a few stand-in GLBs, so each piece
  carries 'fit' (the archetype's real dims from the shop's table) and _glb_piece
  scales the visual to it and builds the collider from it. Also fixed racks being
  flattened to the floor — pos_y is a piece's BOTTOM, which is what sit_on means,
  so the ceiling beams, aircon and wall shelves now stay up where they belong.
- Nothing collides in a renderer: racks that sat inside each other for years get
  separated (weighted, so racks barely move and aisles keep their shape — 3 m of
  correction across 35), rack footprints inset 1.5 cm a side for the few genuinely
  wedged units, and the importer AUDITS ITS OWN OUTPUT with the same test
  probe_overlap runs. Bins are deliberately not separated from their rack: cargo
  inside a container is what the shop means, they spawn frozen, and the audit skips
  frozen bodies because a frozen body cannot be depenetrated across the room.

dev/probe_store.gd: 22 racks hold bins, 255 labels survived, and smashing the rack
carrying 22 bins releases exactly those 22 while the other 256 stay frozen.
All gates green: smoke clean, 7/7 sites 0.00 m/s, overlap CLEAN, LANE9 probes pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 00:49:49 +10:00

3.2 KiB
Raw Blame History

LANE 10 — SITE 7: MONSTER ROBOT PARTY

The level the whole game started as. Spec'd and executed by Fable, 2026-08-04.

The idea

Every other site is authored. This one is imported from the real shop. The live storefront at robotmonster.party/store/ is procedurally assembled from Postgres rows (virtual_rack, virtual_crate, virtual_rack_type*, virtual_crate_type — the wowplatter schema, now served by recordgod/storegod), and the game's sites are already data. So Site 7 is not hand-placed: a converter reads the shop and emits a level.

GET https://robotmonster.party/virtual/scene returns the shop floor:

room 6.66 m × 9.51 m, 2.89 m ceiling
racks 35 placed, across 21 archetypes
crates 302, every one on a rack
labels real: HARD TRANCE, $12-$15 EURO/ITALO HOUSE, SOUND TRACKS, SPOKEN WORD & COMEDY
stock 22,049 records across the bins (n_items)

The rack archetype names (wooden-rack-type-long, white-tub-3x3, chiu-long) are the same names as the GLBs in 3D-STORE/, because both were generated from the same table.

Why this is the best-fitting level in the game

The shop's schema is the cascade. virtual_crate.rack_id already says which rack holds which bin, so rack.supports = [its crates] falls out of the data — knock a rack and the real bins that really sit on it really go over. Nothing to author.

Deliverables

1. Generic data-driven cascade (Main.gd, small)

Extend the smashables spec entry with two optional keys so a level can express support without code: "id" (a name other entries can refer to) and "supported_by" (the id of the piece holding this one up). Main builds in order, keeps id -> Smashable, and wires holder.supports.append(piece). Every existing level is unaffected.

2. tools/import_store.py — the converter

Fetches the live scene (--url, or --offline <file>), filters to the shop-floor space, and emits game/assets/store/shop_floor.json:

  • world-space rack positions, re-centred (the shop's origin is a corner; the game centres its bounds on 0)
  • each crate placed by rack_pos + rotate_y(crate_local, rack.rotation_y), carrying its real label and n_items
  • archetype → game GLB + material mapping (tubs are plastic, timber racks wood, columns and aircon steel)
  • crates spawn frozen and supported by their rack: they don't jitter at spawn (the stillness gate stays green) and they go live exactly when the rack does
  • a measured spawn point — a grid scan for open floor, because a 6.66 × 9.51 room holding 35 racks has very little of it, and spawning inside a rack is not a level

Re-runnable: when the real shop is rearranged, re-run it and the level changes.

3. Levels.record_store() — the site

Loads the JSON and returns a normal Floorplan spec. Timber floor, white walls, the brand's pink as accent. Added to Levels.ORDER as the seventh site.

Gates

Headless smoke clean · probe_levels 7/7 at 0.00 m/s · probe_overlap CLEAN · the LANE9 probes still green. Plus dev/probe_store.gd: the site builds, the rack→crate cascade is wired, and smashing one rack releases exactly its own bins.