Deploy-base-aware asset URLs; live at partly.party/toastsim
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 <noreply@anthropic.com>
This commit is contained in:
parent
d5ed20cacb
commit
db31273fc9
@ -4,6 +4,13 @@ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
const cache = new Map<string, Promise<THREE.Group>>();
|
const cache = new Map<string, Promise<THREE.Group>>();
|
||||||
|
|
||||||
|
/** 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.
|
* Load a generated GLB and make it usable without touching the file.
|
||||||
*
|
*
|
||||||
@ -17,7 +24,7 @@ export function loadProp(url: string, size: number): Promise<THREE.Group> {
|
|||||||
const key = `${url}@${size}`;
|
const key = `${url}@${size}`;
|
||||||
let p = cache.get(key);
|
let p = cache.get(key);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = loader.loadAsync(url).then((gltf) => {
|
p = loader.loadAsync(assetUrl(url)).then((gltf) => {
|
||||||
const root = gltf.scene;
|
const root = gltf.scene;
|
||||||
const box = new THREE.Box3().setFromObject(root);
|
const box = new THREE.Box3().setFromObject(root);
|
||||||
const dim = box.getSize(new THREE.Vector3());
|
const dim = box.getSize(new THREE.Vector3());
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type { Verdict } from '../game/judging';
|
|||||||
import { judgeFace, verdictLines } from '../game/lines';
|
import { judgeFace, verdictLines } from '../game/lines';
|
||||||
import { TOOLS, type ToolId } from '../sim/cutlery';
|
import { TOOLS, type ToolId } from '../sim/cutlery';
|
||||||
import { clear, el, Panel } from '../ui/hud';
|
import { clear, el, Panel } from '../ui/hud';
|
||||||
|
import { assetUrl } from './assets';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scorecard. This is the screen the game is actually about: every number
|
* 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);
|
const lines = verdictLines(verdict, order, TOOLS[tool].name, rand);
|
||||||
for (const l of lines) el('p', undefined, this.linesEl, l);
|
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.textContent = verdict.grade;
|
||||||
this.stampEl.className = `judge-stamp grade-${verdict.grade}`;
|
this.stampEl.className = `judge-stamp grade-${verdict.grade}`;
|
||||||
// re-trigger the stamp animation
|
// re-trigger the stamp animation
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
|
import { assetUrl } from './assets';
|
||||||
|
|
||||||
export function roundedRect(w: number, h: number, r: number): THREE.Shape {
|
export function roundedRect(w: number, h: number, r: number): THREE.Shape {
|
||||||
const hw = w / 2;
|
const hw = w / 2;
|
||||||
@ -169,7 +170,7 @@ export function makeBench(): THREE.Group {
|
|||||||
const g = new THREE.Group();
|
const g = new THREE.Group();
|
||||||
const loader = new THREE.TextureLoader();
|
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.wrapS = wood.wrapT = THREE.RepeatWrapping;
|
||||||
wood.repeat.set(4, 2);
|
wood.repeat.set(4, 2);
|
||||||
// The texture was generated as artwork, i.e. sRGB. Saying so is what keeps it
|
// 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);
|
g.add(top);
|
||||||
|
|
||||||
// Splashback: a blurred kitchen so the scene has a horizon instead of fog.
|
// 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;
|
back.colorSpace = THREE.SRGBColorSpace;
|
||||||
const wall = new THREE.Mesh(
|
const wall = new THREE.Mesh(
|
||||||
new THREE.PlaneGeometry(22, 8),
|
new THREE.PlaneGeometry(22, 8),
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { el, Panel } from './hud';
|
import { el, Panel } from './hud';
|
||||||
|
import { assetUrl } from '../scenes/assets';
|
||||||
|
|
||||||
/** The front door. One button, one piece of art, one joke. */
|
/** The front door. One button, one piece of art, one joke. */
|
||||||
export class Title {
|
export class Title {
|
||||||
@ -8,7 +9,7 @@ export class Title {
|
|||||||
this.panel = new Panel('title');
|
this.panel = new Panel('title');
|
||||||
const wrap = el('div', 'title-wrap', this.panel.root);
|
const wrap = el('div', 'title-wrap', this.panel.root);
|
||||||
const art = el('img', 'title-art', wrap);
|
const art = el('img', 'title-art', wrap);
|
||||||
art.src = '/assets/img/title_art.png';
|
art.src = assetUrl('/assets/img/title_art.png');
|
||||||
art.alt = '';
|
art.alt = '';
|
||||||
const txt = el('div', 'title-txt', wrap);
|
const txt = el('div', 'title-txt', wrap);
|
||||||
el('h1', undefined, txt, 'TOASTSIM');
|
el('h1', undefined, txt, 'TOASTSIM');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user