From db31273fc91b590f4920831c175b30c73e8970fa Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 15:58:18 +1000 Subject: [PATCH] Deploy-base-aware asset URLs; live at partly.party/toastsim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Absolute '/assets/...' paths 404 under the /toastsim/ subpath (and the root /assets/ URL is another game's — returns 200 with wrong content, the classic partly.party trap). assetUrl() prefixes BASE_URL inside loadProp + the four direct loads (bench/backdrop textures, title art, judge portraits). Verified live: JS application/javascript, toaster.glb 4.5MB binary, title_art image/png, title screen renders. Co-Authored-By: Claude Fable 5 --- src/scenes/assets.ts | 9 ++++++++- src/scenes/judge.ts | 3 ++- src/scenes/props.ts | 5 +++-- src/ui/title.ts | 3 ++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/scenes/assets.ts b/src/scenes/assets.ts index daa8857..fbed285 100644 --- a/src/scenes/assets.ts +++ b/src/scenes/assets.ts @@ -4,6 +4,13 @@ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; const loader = new GLTFLoader(); const cache = new Map>(); +/** Root-relative asset path → deploy-base-aware URL. Dev base is '/', the + * partly.party deploy serves from /toastsim/ — absolute '/assets/...' paths + * silently 404 (or worse, hit another game's files) under a subpath. */ +export function assetUrl(path: string): string { + return import.meta.env.BASE_URL.replace(/\/$/, '') + path; +} + /** * Load a generated GLB and make it usable without touching the file. * @@ -17,7 +24,7 @@ export function loadProp(url: string, size: number): Promise { const key = `${url}@${size}`; let p = cache.get(key); if (!p) { - p = loader.loadAsync(url).then((gltf) => { + p = loader.loadAsync(assetUrl(url)).then((gltf) => { const root = gltf.scene; const box = new THREE.Box3().setFromObject(root); const dim = box.getSize(new THREE.Vector3()); diff --git a/src/scenes/judge.ts b/src/scenes/judge.ts index 7b057a0..67f907d 100644 --- a/src/scenes/judge.ts +++ b/src/scenes/judge.ts @@ -6,6 +6,7 @@ import type { Verdict } from '../game/judging'; import { judgeFace, verdictLines } from '../game/lines'; import { TOOLS, type ToolId } from '../sim/cutlery'; import { clear, el, Panel } from '../ui/hud'; +import { assetUrl } from './assets'; /** * The scorecard. This is the screen the game is actually about: every number @@ -148,7 +149,7 @@ export class JudgeView implements View { const lines = verdictLines(verdict, order, TOOLS[tool].name, rand); for (const l of lines) el('p', undefined, this.linesEl, l); - this.faceEl.src = `/assets/img/judge_${judgeFace(verdict.grade)}.png`; + this.faceEl.src = assetUrl(`/assets/img/judge_${judgeFace(verdict.grade)}.png`); this.stampEl.textContent = verdict.grade; this.stampEl.className = `judge-stamp grade-${verdict.grade}`; // re-trigger the stamp animation diff --git a/src/scenes/props.ts b/src/scenes/props.ts index 061616d..0c463d6 100644 --- a/src/scenes/props.ts +++ b/src/scenes/props.ts @@ -1,4 +1,5 @@ import * as THREE from 'three'; +import { assetUrl } from './assets'; export function roundedRect(w: number, h: number, r: number): THREE.Shape { const hw = w / 2; @@ -169,7 +170,7 @@ export function makeBench(): THREE.Group { const g = new THREE.Group(); const loader = new THREE.TextureLoader(); - const wood = loader.load('/assets/img/bench_wood.png'); + const wood = loader.load(assetUrl('/assets/img/bench_wood.png')); wood.wrapS = wood.wrapT = THREE.RepeatWrapping; wood.repeat.set(4, 2); // The texture was generated as artwork, i.e. sRGB. Saying so is what keeps it @@ -185,7 +186,7 @@ export function makeBench(): THREE.Group { g.add(top); // Splashback: a blurred kitchen so the scene has a horizon instead of fog. - const back = loader.load('/assets/img/kitchen_backdrop.png'); + const back = loader.load(assetUrl('/assets/img/kitchen_backdrop.png')); back.colorSpace = THREE.SRGBColorSpace; const wall = new THREE.Mesh( new THREE.PlaneGeometry(22, 8), diff --git a/src/ui/title.ts b/src/ui/title.ts index e3266dd..7fb8ef4 100644 --- a/src/ui/title.ts +++ b/src/ui/title.ts @@ -1,4 +1,5 @@ import { el, Panel } from './hud'; +import { assetUrl } from '../scenes/assets'; /** The front door. One button, one piece of art, one joke. */ export class Title { @@ -8,7 +9,7 @@ export class Title { this.panel = new Panel('title'); const wrap = el('div', 'title-wrap', this.panel.root); const art = el('img', 'title-art', wrap); - art.src = '/assets/img/title_art.png'; + art.src = assetUrl('/assets/img/title_art.png'); art.alt = ''; const txt = el('div', 'title-txt', wrap); el('h1', undefined, txt, 'TOASTSIM');