The arcade moved to monsterrobot.games, where every game lives under
/games/<name>/. BLOBBO's build was pinned to base '/blobbo/', so at the new
mount its absolute /blobbo/assets/... requests 404'd and the module loader got
HTML (the error John hit). Fix:
- vite base -> './' (relative). One build now works at ANY mount point:
index.html + editor.html sit at the deploy root, assets resolve as
./assets/... against the (trailing-slash) page URL, and assetUrl() reads
import.meta.env.BASE_URL='./' so the manifest resolves the same way. Verified
by serving dist/ under a /games/blobbo/ subpath locally: game + editor boot,
manifest fetch resolves to /games/blobbo/assets/manifest.json.
- deploy.sh publishes to the RIGHT place for each host. monsterrobot.games's
docroot is bind-mounted READ-ONLY into forum-nginx from host
/home/humanjing/monsterrobot.games/games/blobbo, so it's rsync'd on the host
(docker cp is refused on the ro mount). partly.party's container-internal
/blobbo stays a best-effort docker-cp copy. Both overlay (keep old chunks;
prune >7d) and both are verified live (index 200 + entry chunk is JS).
Live-verified: monsterrobot.games/games/blobbo/ boots (world+blob, course
select, no console errors); partly.party/blobbo/ still boots too.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- src/main.ts: await initAssets() before the world is built (createBlob captures
blob.mesh by reference). Safe: preload races each url against a deadline with
allSettled, so a stalled asset is a slow boot on built-ins, never a hang.
- src/game.ts: course.tramp hook (hides the MATERIAL — the custom model is a
child, so hiding the mesh would hide it too). Collider untouched.
- vite.config.ts: editor.html as a build input. Without it the Workshop existed
only under vite dev — invisible in the production deploy it is built for.
- editor cannon.barrel: anchor the preview at the cannon group's origin (where
the runtime attaches it) while still hiding the pivot's tube. Preview was
0.45m above where the game renders it — WYSIWYG off by a measurable amount.
- manifest-io.test: drop the stale NOT_YET_IN_THE_RUNTIME guard now that the
runtime adopted all four ids; the check is strict both ways, which is what
stops the two halves drifting again.
Verified: 10/10 test suites (360 assertions), sacred-parity fingerprint
49df4f20 unchanged from pre-workshop main, dist/editor.html + dist/assets/
manifest.json ship.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- installZones + cannonConfigs through the single cannon path; old centre
plate/boot removed (fork versions supersede); belt+bucket to centre lane
(sunk flush — proud face curbed the line); arch punishes failed MEGA runs
- puddles: distance-based stamping (speed-independent coverage), rate 4/u,
contact tolerance 1.0 (bounce hops starved strips), fork strips widened
toward the racing line + neutral-centre red top-up strip
- under-shelf volumes filled solid in the centre (side corridors left open);
launcher catch widened to the full gap
- verified: naive hold-W finishes ~12s, ghost records+replays, MINI (0.77)
passes the tunnel with 47% pink, buffs activate (GRIP live at 29% green),
78% total coverage on a wandering run
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixed-step world runtime, event bus wire protocol between lanes, integration
seam (game.ts) with placeholder ball. Lanes A/B/C own disjoint dirs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>