The hip-hop room has stock (7 racks, 47 bins, 2,865 records); the entry hall and
back room are empty. Import all four anyway: the empty rooms are the connective
tissue, and they are the only floor in the building big enough to get an office
chair up to speed.
A portal pair is one doorway seen from both sides, so the importer walks the graph
and places each room by making its portal land exactly on its neighbour's. Every
pair here sits on parallel walls with opposite facings, so each join is a pure
translation — and when one isn't, it says so rather than quietly getting it wrong.
It then recentres the union, emits the interior walls with a gap at each doorway,
and puts the spawn in the entry hall, because that is the way in.
hiphop-room <-> entry-hall <-> shop-floor <-> back-room
12.96 x 15.41 m - 36 racks - 325 bins - 302 real genre labels - 24,024 records
Levels.record_store() now takes the walls and rooms from the import, hangs the
street glazing on the entry hall's outer wall, and lays a light grid across
whatever footprint the rooms came out as.
probe_store.gd also checks the new facts: five doorways exist, and the spawn has
nothing in it (excluding the player, who is supposed to be standing there — that
false positive was the probe's bug, not the level's).
All gates green: smoke clean, 7/7 sites 0.00 m/s, overlap CLEAN, all probes pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>