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

7.2 KiB
Raw Blame History

RESEARCH — what the parent repos already solved (port, don't reinvent)

Condensed technical briefs from full sweeps of both repos (2026-07-14). Exact paths verified. Read the section for your lane before writing code; open the referenced files and lift patterns.

90sDJsim (/Users/jing/Documents/90sDJsim)

  • three.js r175 vendored at web/world/vendor/ (copied into PROCITY web/vendor/), importmap in web/world/index.html. No build, no npm. Backend = single stdlib-Python server.py :8123.
  • Docs: CLAUDE.md, DEVMANUAL.md (single source of truth), TOWNMAP.md, ECONOMY_SPEC.md.
  • World: web/world/index.html (~3400 lines, all inline). One scene, one room Group swapped per mode. AREAS data table (~line 711) declares streets as shop rows; buildStrip() (~740) realizes them: BoxGeometry(4.8,h,4) shell + facade JPEG on a PlaneGeometry(4.7,2.4)
    • awning box + textPlane() canvas signs, seeded per building with mulberry32(i*77+5). buildHome() ~963, buildVenue() ~1094. Day/night = 6-segment applyLighting(segIdx).
  • Facade skins: web/world/tex/facade_{record,opshop,pawn,pub,video,dept,milkbar}.jpg — Cloudflare Flux, committed 2026-07-10 (commit e31e605), cropped below the sign band. Mapped by FACADE table (~line 276). Copied into PROCITY as facade-djsim-*.jpg.
  • NPC stack (the crown jewel — port for Lane D), web/world/index.html ~258393:
    • models/peds/ = 17 normal + 2 comical rigged GLBs (~2MB each) + clip-only walk.glb/idle.glb.
    • spawnRig(rig,target,x,z,ry,clipName,height,extClip): SkeletonUtils.clone → height-normalize off the head bone → plant feet by min bone Y → mixer.clipAction().play() with random start offset to desync.
    • _canon = s => s.replace(/mixamorig\d+/g,'mixamorig') — one clip binds to any character.
    • _rotOnly strips position tracks + Hips.quaternion from shared clips (prevents scale blowups).
    • upgradeStreetPeople() — world builds instantly with primitive figures, rigs hot-swap in when ~40MB of GLBs arrive. Venue crowd: rigged front rows, bobbing box-figures behind.
  • web/world/fittings.js — standalone parametric shop-fitting kit (racks, bins, shelves, counters, pegboards, canvas-texture garments). Takes THREE as arg, returns placeable Groups. Written to theme "any shop, any count". Port for Lane C.
  • web/world/dig.js — self-contained crate-riffle minigame (own scene/camera, callback API onBuy/getCash/spawnClerk/spawnFittings). Already ported across 3 games. Content phase.
  • Loaders: loadGLB/loadRig/loadProp/loadTex promise-cached, fail→null→placeholder stays.
  • Perf: zero instancing/LOD/atlases (small scenes got away with it — we can't). Tricks worth keeping: GFX_TIERS era-tiered graphics (~line 167), bloom threshold 0.9, single 2048 shadow map on street only, additive light-cones, tools/shots.py screenshot regression harness.
  • Gear/prop gen: MeshGod manifests (MESHGOD/manifests/djsim_home.json pattern), webp-optimized ~1MB GLBs, no Draco. Gotcha: thin wires/flat discs reconstruct badly — do those as in-engine primitives.

thriftgod (/Users/jing/Documents/thriftgod)

  • three.js 0.175 from unpkg importmap in web/index.html (2,061 lines = whole game). Backend server.py (1,616 lines, stdlib + psycopg2) :8777; reads dealgod DB (1.77M real listings).
  • Real-world city: build_city() (server.py:433) — Overpass query for all named AU secondhand/charity/music/antiques/books/toys shops → city_source.json cache → dedupe → nearest-capital assignment → suburb inference → parody names → seeded hours. ~2,918 shops. The recipe for later swapping PROCITY's synthetic plan for real geography.
  • Seed + override architecture (the big idea): every shop interior is deterministic from shop.seed via mulberry32 (web/index.html:1063); Postgres layout_shop/layout_area/ layout_asset tables hold optional hand-authored overrides; NULL = procedural fallback. In-game editor (E1E4) writes overrides. See EDITOR_PLAN.md.
  • Street: buildStreet() (index.html:1441-1515) — 4.4×3.4×0.4 box per shop, facade skin on front face, canvas name sign, OPEN/CLOSED plate, SphereGeometry(70) BackSide sky dome (seasonal pickSky), landmark billboard, textured ground planes.
  • Interior: buildShop() (index.html:1109+) — 5 archetypes SHOP_SHAPES (cosy/gallery/wide/hall/pokey), seeded wallpaper/carpet/art, shuffled wall-slot system so decor never overlaps, record bins, shelves with product thumbnails, floor piles, counter+till, glass case. Port for Lane C.
  • Generated assets: 557 JPGs in web/assets/gen/ from gen_assets.py (OpenRouter google/gemini-3.1-flash-image, ~$0.004/img, resumable .genraw/, style-bible prefix "1990s Australian op-shop aesthetic, slightly faded and worn…"). Facade prompts generate blank signboards (template at gen_assets.py:69-86). 69 relevant skins copied into PROCITY. CORS enabled on live /assets/*.
  • 3GOD depot loading (index.html:1072-1249): DEPOT='https://digalot.fyi/3god', GLB_CACHE[file] ||= loadAsync, SkeletonUtils.clone, bbox floor-plant, auto-play /idle/i clip. Editor palette from /api/list.
  • Movement: PointerLockControls + AABB clamps + rotated-rect divider collision (hitsDivider, index.html:1994). /img caching proxy with SSRF guard (server.py:1362) for CORS-free WebGL textures.
  • Item economy (content phase): mint() server.py:792-858 — per-shop-type profiles, gem bands, curation axis (CBD distance), isolation multiplier, TABLESAMPLE over real listings, rarity from live supply. dig.js riffle with real physical sleeve thicknesses.

Everything else

  • character_kit (~/Documents/character_kit/, also on ultra): female + male canonical rigs, props (hats/boombox/camera/thermos), scripts/finish_rig.py, export_for_mixamo.py. House law: edit here, copy into games, never edit game-local.
  • mixamo-fetch (~/Documents/mixamo-fetch/): fetch.cjs drives Mixamo's REST API (token from logged-in Brave via CDP :9222). 34 clips in out/. Search first; never re-download. Bespoke clips (crate-riffle, DJ) don't exist there — hand-author.
  • ultra 3D=models library (johnking@100.91.239.7:~/Documents/3D=models/): shop-fittings/ (record_crate_plastic_01, clothes_rack_01, shelf_metal_wire_01, garage_shelves_metal_v2, bookshelves, cube_bookcase, wardrobes, many tables, balcao counter…), street-furniture/ (bench, longbench, park_bench_01, market_stall_01, food_cart_bakso_01, building_shell_01.glb), furniture/, props-scenes/ (dj_room, turntable), characters/, animations/. MANIFEST.md + CH_MAPPING.md + _thumbnails/ exist — read them on ultra.
  • GODVERSE brain (~/Documents/dealgod/GODVERSE.md, docs/GODVERSE_3D_BRIEF.md): recordgod/ toygod/bookgod/mediagod data feeds, 44k solid-object 3D candidates, 185k vinyl w/ images — this is the content firehose for later. Not v1.
  • Vuntra City reference (YouTube devlogs): 20×20km UE5 city, every building enterable, interiors generated at runtime, million-NPC layered simulation (detailed near / abstract far), faked GI. We steal the ideas at hamlet scale: on-demand interiors, LOD'd simulation, cheap lighting.