Fail fast on missing terrain assets and recover empty renders

This commit is contained in:
2026-10-04 22:32:11 +05:00
parent 79d0f53a79
commit 763cf8713c
15 changed files with 842 additions and 21 deletions

View File

@@ -34,8 +34,8 @@ async function json(path) {
if (!jsonCache.has(path))
jsonCache.set(
path,
fetch(path).then((r) => {
if (!r.ok) throw new Error(path);
fetch(path, { signal: AbortSignal.timeout(60000) }).then((r) => {
if (!r.ok) throw new Error(`Minecraft asset ${path}: HTTP ${r.status}`);
return r.json();
}),
);
@@ -183,8 +183,10 @@ window.buildTerrain = async (snapshot) => {
const bs = await json(resourcePath(name, "blockstates") + ".json");
for (const v of selectModels(bs, props))
variants.push({ v, m: await model(v.model) });
} catch {
} catch (error) {
unsupported.add(name);
if (unsupported.size <= 8)
console.warn(`Missing block model ${name}: ${error.message}`);
}
stateCache.set(s, variants);
return variants;
@@ -225,6 +227,18 @@ const directions = {
[0, 1, 0],
],
};
function renderScene(camera, requireGeometry = false) {
if (gl.isContextLost())
throw new Error("Graphics context lost while rendering terrain");
renderer.render(scene, camera);
const error = gl.getError();
if (error !== gl.NO_ERROR)
throw new Error(`WebGL failed to render terrain (error ${error})`);
if (requireGeometry && renderer.info.render.triangles === 0)
throw new Error(
"Surface-map camera sees no terrain geometry. Check world coordinates and Minecraft assets.",
);
}
window.renderFace = (p, face, size) => {
renderer.setSize(size, size);
const camera = new THREE.PerspectiveCamera(90, 1, 0.05, 512);
@@ -232,7 +246,7 @@ window.renderFace = (p, face, size) => {
const [dir, up] = directions[face];
camera.up.set(...up);
camera.lookAt(p.x + dir[0], p.y + dir[1], p.z + dir[2]);
renderer.render(scene, camera);
renderScene(camera);
return renderer.domElement.toDataURL("image/webp", 0.85);
};
window.renderMap = (size) => {
@@ -249,7 +263,7 @@ window.renderMap = (size) => {
camera.position.set((b.minX + b.maxX) / 2, 512, (b.minZ + b.maxZ) / 2);
camera.up.set(0, 0, -1);
camera.lookAt(camera.position.x, 0, camera.position.z);
renderer.render(scene, camera);
renderScene(camera, true);
return renderer.domElement.toDataURL("image/webp", 0.9);
};
window.rendererReady = true;