PROCITY/docs/LANES/LANE_C_INTERIORS.md
2026-07-14 10:46:40 +10:00

4.6 KiB
Raw Blame History

LANE C — INTERIORS (every door opens)

Prompt for Opus 4.8. You are working in /Users/jing/Documents/PROCITY. Read docs/CITY_SPEC.md and docs/RESEARCH.md first, then the two sources you are porting: thriftgod/web/index.html buildShop() (line ~1109+, archetypes SHOP_SHAPES, wall-slot system, seeded decor) and 90sDJsim/web/world/fittings.js (parametric fittings kit — read it whole, it was written to be lifted). You own web/js/interiors/* and web/interior_test.html. Do not touch other lanes' files. Plain ES modules, three.js from web/vendor/ importmap, randomness via core/prng.js only. Commit in small, described steps on main.

Mission

The Vuntra move: every shop door opens into a unique, believable, seeded interior — generated on demand in <50ms, byte-identical every revisit (shop.seed), themed by shop.type. This lane is a standalone library + test page; Lane B wires it to real doors later via the procity:enterShop / procity:exitShop events (contract in LANE_B).

Architecture

  • web/js/interiors/interiors.js — public API:
    buildInterior(shop, THREE)  { group, spawn:{x,z,ry}, exits:[{x,z,w, toStreet:true}],
                                   places:[userData-tagged interactables], dispose() }
    
    Pure function of shop (a CityPlan shop record + its lot dims). No global state.
  • web/js/interiors/shell.js — the room shell: floor/walls/ceiling sized from the lot (lot.w × lot.d, storeys → ceiling height 3.24.5m), seeded from the 5 thriftgod archetypes (cosy / gallery / wide / hall / pokey) adapted to lot proportions, plus door/shopfront wall with real glazing (you can see a hint of street), back room doorway (blocked v1). Materials: seeded pick of wall-*.jpg wallpapers, tex-carpet-*/tex-lino-* floors, tex-* counters — all already in web/assets/gen/, all with flat-colour fallbacks.
  • web/js/interiors/fittings.js — port 90sDJsim's kit and extend it. Needed set (see the registry's fittings mixes): record bins & crates, clothes racks, wall/cube/metal shelving, bookshelves, VHS aisle shelving, glass display case, counter + till, trestle tables, fridge, magazine rack, poster/art frames (art-* future), pegboard walls. Parametric primitives first; where a GLB upgrade exists use the manifest (see below) with primitive fallback.
  • web/js/interiors/layout.js — the placer: per-archetype floor zones (window display / aisles / walls / counter-corner), the thriftgod shuffled wall-slot system so nothing overlaps, density from shop seed (some shops crammed, some sparse), guaranteed walkable path from door to counter (grid-mark occupied cells; verify connectivity with a flood fill — assert it).
  • web/js/interiors/stock.js — v1 visual stock only: product boxes/sleeves/spines as canvas-texture blocks on shelves (steal the dig.js sleeve-canvas trick — coloured cardboard + price stickers). Real items are the content phase; leave a stockAdapter hook: (shop, slotKind) => texture/mesh so BaseGod data can plug in without touching layout code.
  • GLB upgrades: read web/assets/manifest.json if present (Lane E ships it) mapping fitting ids → 3GOD depot files; promise-cached loader, placeholder-persists pattern. The test page must be fully usable with no manifest and no network.
  • Windows-from-street problem (Lane B fakes it): you own the inside-looking-out — a simple backdrop plane beyond the glazing (street-ish gradient / sky-* slice) sells it in v1.

Type theming (registry-driven)

Import SHOP_TYPES from core/registry.js; every type in CITY_SPEC's table gets a distinct recipe (fittings mix, wallpaper bias, clutter level, counter position, signage-inside flavour). A record shop must instantly read different from a toy shop from the doorway. Milk bar counter faces the door; pawn shop is counter-forward with wall hooks; dept anchor is the "grand hall" archetype with mixed sections.

Test page (web/interior_test.html)

Standalone: seed input, type dropdown, archetype override dropdown, "re-roll", first-person walk inside (reuse PointerLock pattern), wireframe/occupancy-grid debug toggle, and a "50-room soak" button that builds+disposes 50 seeded interiors and reports ms/room + leaked geometries (renderer.info.memory before vs after — must return to baseline).

Acceptance

  • Same seed twice → identical room (soak test asserts deep-equal on placement lists).
  • All 9 types × 5 archetypes render sensibly (screenshot grid into docs/shots/laneC/).
  • Build <50ms/room, dispose leak-free, flood-fill path door→counter always exists.
  • Runs with zero assets (fallback colours) and zero network.