From ad93d55de9a2bf29933d018233c83c91b0797bd9 Mon Sep 17 00:00:00 2001 From: type-two Date: Sun, 19 Jul 2026 12:39:09 +1000 Subject: [PATCH] Custom-assets pill in game, deploy size guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - game.ts: a forgotten Workshop swap otherwise reads as a broken game with no way back; the pill says what is on and links to the Workshop. hasOverrides() existed in idb.ts and nothing called it. - deploy.sh: fail if dist/ exceeds 10MB. stage-farm-assets.sh copies 43MB of raw GLBs into public/, vite copies public/ into dist/, and deploy rsyncs all of dist/ — I hit exactly this while browser-testing (47MB build). Browser-verified end to end: stock boot clean (44 scene children, blob r=0.5, no console errors), Workshop lists all 18 slots, real .glb drop swaps the stage, Save writes a raw ArrayBuffer manifest, the game loads it (120k-tri boot renders in-game), pill appears, Clear restores the stock scene exactly. Co-Authored-By: Claude Fable 5 --- deploy.sh | 13 +++++++++++++ src/game.ts | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/deploy.sh b/deploy.sh index ca06b09..5e62b13 100644 --- a/deploy.sh +++ b/deploy.sh @@ -24,6 +24,19 @@ echo "[1/4] Building ..." cd "$SCRIPT_DIR" npm run build +# Guard: scripts/stage-farm-assets.sh copies ~43MB of raw farm GLBs into +# public/ for local Workshop testing, and vite copies public/ straight into +# dist/. Shipping those means every player downloads 43MB of background props. +# Custom models belong in the player's browser (IndexedDB) or in a decimated +# committed pack — never as an accident of local testing. +DIST_KB="$(du -sk dist | cut -f1)" +if [ "$DIST_KB" -gt 10240 ]; then + echo " ✗ dist/ is ${DIST_KB}KB (>10MB). Staged farm assets leaked into the build?" + echo " Run: rm -rf public/assets/meshes && npm run build" + exit 1 +fi +echo " dist/ is ${DIST_KB}KB — ok" + echo "[2/4] Syncing dist/ to VPS staging ..." ssh "$VPS" "rm -rf '$STAGING' && mkdir -p '$STAGING'" rsync -az --exclude='.DS_Store' "$SCRIPT_DIR/dist/" "$VPS:$STAGING/" diff --git a/src/game.ts b/src/game.ts index 54aa01e..c550747 100644 --- a/src/game.ts +++ b/src/game.ts @@ -14,6 +14,7 @@ import { PaintSkin, PaintCannon, BuffSystem, PaintHUD, installPaint } from './pa import { createBucketDump, createBubbleArch, createConveyorBelt } from './machine/index' import { installZones } from './course/zones' import { assets } from './assets/registry' +import { hasOverrides } from './assets/idb' import { installAudio } from './audio/index' import { installGhost } from './ghost/index' import { installTitle } from './ui/title' @@ -249,6 +250,20 @@ export function installGame(world: World) { setTimeout(() => toast.remove(), 3200) }) + // ---- custom-assets pill: a forgotten Workshop swap otherwise reads as a + // broken game ("why is the boot a weird cylinder?"), with no way back. ---- + void hasOverrides().then((on) => { + if (!on) return + const pill = document.createElement('a') + pill.href = 'editor.html' + pill.textContent = '🎨 your custom models are on — open the Workshop' + pill.style.cssText = + 'position:fixed;bottom:14px;left:14px;font:12px ui-monospace,Menlo,monospace;' + + 'color:#0a2540;background:rgba(255,255,255,.86);padding:7px 12px;border-radius:999px;' + + 'text-decoration:none;z-index:18;box-shadow:0 1px 6px rgba(0,0,0,.18)' + document.body.appendChild(pill) + }) + // ---- wave 2: audio, ghost, title ---- installAudio(world) installGhost(world, blob, { radius: blob.radius })