mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
In the keyless setup a single transient failure while loading the default map layers locked in the degraded fallback until reload. _getImageryProvider cached the construction-fallback resolution (OSM) under the Esri stack id, so every later "Esri Satellite" selection showed OSM. createKeylessTerrain turns any Re:Earth failure into a flat EllipsoidTerrainProvider; the controller cached it and set _terrainMode to 'keyless', so a boot-time network blip left the globe flat. Fallbacks are still cached and shown at once, and no switch waits on a retry. One controller timer now retries the real provider behind whichever fallback is on screen (Esri's OSM stand-in, or flat terrain on a shown globe), starting at 30 seconds and doubling to a 10-minute cap while it keeps failing. A failed retry leaves the cached fallback and the installed terrain untouched. A success replaces the cache entry and applies it live: terrain is installed in place with a render request (or, behind a 3D tileset, picked up by the next globe activation), and Esri is reselected automatically, after any in-flight switch settles. A switch that read the flat fallback re-reads the terrain cache before installing, and destroy() cancels the timer and releases a provider built after it.
65 lines
2.2 KiB
JavaScript
65 lines
2.2 KiB
JavaScript
import * as Cesium from 'cesium';
|
|
import { createTerrainRetryPolicy } from './terrainRetry.js';
|
|
|
|
/** Re:Earth / Mapterhorn ellipsoidal quantized mesh, CC BY 4.0. */
|
|
export const KEYLESS_TERRAIN_URL =
|
|
'https://terrain.reearth.land/cesium-mesh/ellipsoid';
|
|
|
|
/** These factories are lazy: a hidden globe must not trigger terrain loading. */
|
|
export async function createWorldTerrain(accessToken, { signal } = {}) {
|
|
accessToken = String(accessToken || '').trim();
|
|
if (!accessToken)
|
|
throw new Error('World terrain requires an explicit ion token');
|
|
signal?.throwIfAborted();
|
|
const resource = await Cesium.IonResource.fromAssetId(1, { accessToken });
|
|
signal?.throwIfAborted();
|
|
return {
|
|
provider: await Cesium.CesiumTerrainProvider.fromUrl(resource, {
|
|
requestVertexNormals: true,
|
|
requestWaterMask: false,
|
|
ellipsoid: Cesium.Ellipsoid.WGS84,
|
|
}),
|
|
};
|
|
}
|
|
|
|
function logThrottle({ statusCode, delayMs, inWindow }) {
|
|
// One line per cooldown window, not per tile: a burst throttles dozens.
|
|
if (inWindow !== 1) return;
|
|
console.warn(
|
|
`[MapStack] Re:Earth terrain answered ${statusCode}; retrying throttled tiles after ${Math.round(delayMs)} ms`,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* The Re:Earth resource with the tile retry policy attached. Cesium copies
|
|
* `retryCallback`/`retryAttempts` onto every derived resource, so layer.json
|
|
* and each `{z}/{x}/{y}.terrain` fetch inherit it (see `terrainRetry.js`).
|
|
* @param {ReturnType<typeof createTerrainRetryPolicy>} [policy]
|
|
* @returns {Cesium.Resource}
|
|
*/
|
|
export function createKeylessTerrainResource(
|
|
policy = createTerrainRetryPolicy({ onThrottle: logThrottle }),
|
|
) {
|
|
return new Cesium.Resource({
|
|
url: KEYLESS_TERRAIN_URL,
|
|
retryCallback: policy.retryCallback,
|
|
retryAttempts: policy.retryAttempts,
|
|
});
|
|
}
|
|
|
|
export async function createKeylessTerrain() {
|
|
try {
|
|
return {
|
|
provider: await Cesium.CesiumTerrainProvider.fromUrl(
|
|
createKeylessTerrainResource(),
|
|
),
|
|
};
|
|
} catch (error) {
|
|
console.warn(
|
|
'[MapStack] Re:Earth terrain unavailable, falling back to flat ellipsoid terrain:',
|
|
error,
|
|
);
|
|
return { provider: new Cesium.EllipsoidTerrainProvider(), fallback: true };
|
|
}
|
|
}
|