Spaces:
Running
Running
Download modules/space_exploration/src/space_module.js from CREATORJD/massfront-playtest: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/spaces/CREATORJD/massfront-playtest/resolve/main/modules/space_exploration/src/space_module.js
- Command line
-
hf download hf://spaces/CREATORJD/massfront-playtest/modules/space_exploration/src/space_module.js
-
curl -L -o space_module.js https://huggingface.co/spaces/CREATORJD/massfront-playtest/resolve/main/modules/space_exploration/src/space_module.js
14 kB
| /* -------------------------------------------------------------------------- | |
| MASSFRONT — EXPLORATION DOCUMENT BOOTSTRAP | |
| The reusable lifecycle lives in space_experience.js. Direct document loads | |
| retain the standalone simulator; a live same-tab base-game ticket selects | |
| the profile-isolated solo adapter. Only the canonical content downloader is | |
| shared with the base document; its renderer and updater are not imported, | |
| so MASSFRONT and Three.js cannot compete for one WebGL context. | |
| -------------------------------------------------------------------------- */ | |
| import './startup_content.js?v=20260906-release5'; | |
| import { createSpaceExperience } from './space_experience.js?v=20260908-uga81r1'; | |
| import { MASSFRONT_WORLD_MODEL_LIBRARY } from './core/world_model_catalog.js'; | |
| import { LocalSandboxHost } from './host/local_sandbox_host.js?v=20260825-host1'; | |
| import { | |
| readNativeExplorationMount, | |
| acknowledgeMountedRuntimeReady, | |
| installNativeExplorationLoaderUrls, | |
| resolveBaseRuntimeNavigation | |
| } from './host/base_runtime_url.js?v=20260908-uga81r1'; | |
| import { | |
| MASSFRONT_GALACTIC_ENTRY_TICKET_KEY, | |
| MassfrontSoloHost, | |
| readMassfrontGalacticEntryTicket | |
| } from './host/massfront_solo_host.js?v=20260906-release5'; | |
| export { | |
| SPACE_FIRST_ENTRY_CONTINUATION, | |
| createSpaceExperience | |
| } from './space_experience.js?v=20260908-uga81r1'; | |
| export { | |
| ExplorationHostError, | |
| LocalSandboxHost, | |
| createExplorationHostV1 | |
| } from './host/local_sandbox_host.js?v=20260825-host1'; | |
| export { | |
| MassfrontSoloHost, | |
| createMassfrontGalacticEntryTicket, | |
| createMassfrontGalacticTacticalReportV1, | |
| createMassfrontSoloHost, | |
| readMassfrontGalacticEntryTicket, | |
| validateMassfrontGalacticEntryTicket | |
| } from './host/massfront_solo_host.js?v=20260906-release5'; | |
| let gpuRebuilds = 0; | |
| let gpuRebuildPending = false; | |
| let selectedHost = null; | |
| let hostSelectionError = null; | |
| const consumedReturnNonces = new Set(); | |
| const FATAL_RETURN_SYSTEM_IDS = new Set(['aelos', 'veyra', 'karak']); | |
| const FATAL_RETURN_TARGET_ID = /^[a-z0-9_]{1,96}$/; | |
| const CLASSIC_FALLBACK_SESSION_KEY = 'massfront.galactic.classic-fallback.v1'; | |
| function armClassicFallbackSession() { | |
| try { | |
| window.sessionStorage.setItem(CLASSIC_FALLBACK_SESSION_KEY, '1'); | |
| return window.sessionStorage.getItem(CLASSIC_FALLBACK_SESSION_KEY) === '1'; | |
| } catch (_) { | |
| return false; | |
| } | |
| } | |
| function fatalReturnLocation() { | |
| let snapshot = null; | |
| try { snapshot = window.__MASSFRONT_SPACE__?.getState?.() || null; } catch (_) {} | |
| if (!snapshot) { | |
| try { | |
| const candidate = selectedHost?.loadCampaignSnapshot?.(); | |
| if (candidate && typeof candidate.then !== 'function') snapshot = candidate; | |
| } catch (_) {} | |
| } | |
| const systemId = FATAL_RETURN_SYSTEM_IDS.has(snapshot?.route?.systemId) ? snapshot.route.systemId : 'aelos'; | |
| const candidateTarget = snapshot?.route?.targetId; | |
| const targetId = typeof candidateTarget === 'string' && FATAL_RETURN_TARGET_ID.test(candidateTarget) | |
| ? candidateTarget | |
| : null; | |
| return { systemId, targetId }; | |
| } | |
| async function returnToMassfrontFromFatalState() { | |
| const button = document.querySelector('[data-render-return]'); | |
| if (button?.disabled) return; | |
| if (button) { | |
| button.disabled = true; | |
| button.setAttribute('aria-busy', 'true'); | |
| button.textContent = 'RETURNING TO MASSFRONT'; | |
| } | |
| const classicFallbackLatched = armClassicFallbackSession(); | |
| try { | |
| if (classicFallbackLatched && selectedHost?.productionIntegrated === true && typeof selectedHost.openBaseRoute === 'function') { | |
| await selectedHost.openBaseRoute('war-room', fatalReturnLocation()); | |
| return; | |
| } | |
| } catch (error) { | |
| // A corrupt or expired Galactic bridge must not remove the unprivileged | |
| // route back to the base game; the War Room request simply cannot be kept. | |
| console.warn('[MASSFRONT GALACTIC FAIL-SAFE]', error); | |
| } | |
| try { | |
| const target = resolveBaseRuntimeNavigation('../../../index.html?galacticFallback=classic'); | |
| window.location.assign(target); | |
| } catch (error) { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| console.error('[MASSFRONT GALACTIC FAIL-SAFE]', error); | |
| if (button) { | |
| button.disabled = false; | |
| button.removeAttribute('aria-busy'); | |
| button.textContent = 'RETURN TO MASSFRONT'; | |
| } | |
| } | |
| } | |
| function installFatalReturn() { | |
| const button = document.querySelector('[data-render-return]'); | |
| window.__MASSFRONT_FATAL_RETURN_HANDLER__ = returnToMassfrontFromFatalState; | |
| /* index.html owns a dependency-free dispatcher so an import failure still | |
| has a working escape. Direct embedders without that dispatcher retain the | |
| normal module binding here. */ | |
| if (button && window.__MASSFRONT_INLINE_FATAL_RETURN_BOUND__ !== true) { | |
| button.addEventListener('click', returnToMassfrontFromFatalState); | |
| } | |
| } | |
| function exposeFatalActions(veil) { | |
| const retry = veil?.querySelector('[data-render-retry]'); | |
| if (retry) { | |
| retry.hidden = false; | |
| retry.removeAttribute('aria-busy'); | |
| } | |
| } | |
| function retrySpaceAfterFatalState() { | |
| if (gpuRebuildPending) return; | |
| const button = document.querySelector('[data-render-retry]'); | |
| if (button) button.setAttribute('aria-busy', 'true'); | |
| // A deliberate player retry starts a fresh bounded recovery attempt. The | |
| // context-loss listener still caps unattended rebuilds, so this cannot loop. | |
| gpuRebuilds = 0; | |
| rebuildAfterGpuInterruption(); | |
| } | |
| function installFatalRetry() { | |
| const button = document.querySelector('[data-render-retry]'); | |
| if (button) button.addEventListener('click', retrySpaceAfterFatalState); | |
| } | |
| function hasIntegratedReturnQuery() { | |
| const parameters = new URLSearchParams(window.location.search); | |
| return parameters.has('groundResult') || parameters.has('groundRejected'); | |
| } | |
| function hasGalacticEntryRecord() { | |
| try { | |
| return window.sessionStorage?.getItem(MASSFRONT_GALACTIC_ENTRY_TICKET_KEY) !== null; | |
| } catch (_) { | |
| return false; | |
| } | |
| } | |
| function chooseHost() { | |
| if (selectedHost) return selectedHost; | |
| const ticket = readMassfrontGalacticEntryTicket(); | |
| if (ticket) { | |
| try { | |
| selectedHost = new MassfrontSoloHost({ expectedProfileId: ticket.profileId }); | |
| return selectedHost; | |
| } catch (error) { | |
| hostSelectionError = error; | |
| throw error; | |
| } | |
| } | |
| if (hasIntegratedReturnQuery() || hasGalacticEntryRecord()) { | |
| hostSelectionError = new Error('The MASSFRONT Galactic entry ticket is missing, unreadable, or expired. The standalone career was not opened.'); | |
| throw hostSelectionError; | |
| } | |
| selectedHost = new LocalSandboxHost(); | |
| return selectedHost; | |
| } | |
| function showIntegratedFailure(error) { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| window.__MASSFRONT_GALACTIC_RESULT__ = null; | |
| console.error('[MASSFRONT GALACTIC BRIDGE]', error); | |
| const frame = document.getElementById('moduleFrame'); | |
| const veil = frame?.querySelector('#renderVeil'); | |
| if (!veil) return; | |
| veil.className = 'render-veil failed'; | |
| const title = veil.querySelector('b'); | |
| const status = veil.querySelector('#loadStatus'); | |
| if (title) title.textContent = 'GALACTIC RESULT REJECTED'; | |
| if (status) status.textContent = String(error?.message || 'THE TACTICAL RESULT COULD NOT BE VERIFIED').toUpperCase(); | |
| exposeFatalActions(veil); | |
| } | |
| function quarantineReturnedTacticalResult(experience, error) { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| window.__MASSFRONT_GALACTIC_RESULT__ = null; | |
| console.warn('[MASSFRONT GALACTIC RESULT RECOVERY]', error); | |
| if (window.history && typeof window.history.replaceState === 'function') { | |
| window.history.replaceState(window.history.state, '', `${window.location.pathname}${window.location.hash || ''}`); | |
| } | |
| experience.recoverGroundOperation?.(error); | |
| } | |
| async function consumeReturnedTacticalResult(experience, host) { | |
| const parameters = new URLSearchParams(window.location.search); | |
| if (!parameters.has('groundResult')) return; | |
| await experience.ready; | |
| const nonce = parameters.get('groundResult'); | |
| if (consumedReturnNonces.has(nonce)) return; | |
| if (hostSelectionError) throw hostSelectionError; | |
| if (host.productionIntegrated !== true || typeof host.consumeTacticalResult !== 'function') { | |
| throw new Error('A live MASSFRONT Galactic entry ticket is required to consume this tactical result.'); | |
| } | |
| const outcome = await host.consumeTacticalResult(nonce); | |
| if (!outcome?.accepted && !outcome?.duplicate) throw new Error('The MASSFRONT tactical result was not accepted.'); | |
| consumedReturnNonces.add(nonce); | |
| let queryStripped = false; | |
| if (window.history && typeof window.history.replaceState === 'function') { | |
| window.history.replaceState(window.history.state, '', `${window.location.pathname}${window.location.hash || ''}`); | |
| queryStripped = !new URLSearchParams(window.location.search).has('groundResult'); | |
| } | |
| let finalization = { finalized: false, deferred: true }; | |
| if (queryStripped && typeof host.finalizeTacticalResult === 'function') { | |
| try { | |
| finalization = await host.finalizeTacticalResult(nonce, outcome.resultId); | |
| } catch (error) { | |
| finalization = { finalized: false, deferred: true, warning: String(error?.message || error) }; | |
| console.warn('[MASSFRONT GALACTIC RESULT FINALIZATION]', error); | |
| } | |
| } | |
| window.__MASSFRONT_GALACTIC_RESULT__ = { ...outcome, finalization }; | |
| } | |
| function boot() { | |
| const container = document.getElementById('moduleFrame'); | |
| if (!container || window.__MASSFRONT_SPACE__) return; | |
| try { | |
| const mountedRuntime = readNativeExplorationMount(); | |
| installNativeExplorationLoaderUrls(); | |
| const host = chooseHost(); | |
| const integrated = host.productionIntegrated === true; | |
| container.dataset.runtime = integrated ? 'massfront' : 'sandbox'; | |
| container.dataset.entryView = host.ticket?.entryView || 'system'; | |
| const reset = container.querySelector('#btnResetRoom'); | |
| if (reset) reset.hidden = integrated; | |
| const experience = createSpaceExperience(container, { | |
| host, | |
| entryView: host.ticket?.entryView || 'system', | |
| seed: 'massfront-cinematic-test-room-v1' | |
| }); | |
| window.__MASSFRONT_SPACE__ = experience; | |
| window.__MASSFRONT_SPACE_HOST__ = host; | |
| window.__MASSFRONT_SPACE_ERROR__ = null; | |
| window.__MASSFRONT_STORY_RAIL__ = experience.transmissions; | |
| window.__MASSFRONT_WORLD_MODELS__ = MASSFRONT_WORLD_MODEL_LIBRARY; | |
| window.__MASSFRONT_SPACE_ENTRY__ = { | |
| getState: () => experience.firstEntryIntro, | |
| start: () => experience.startFirstEntryIntro() | |
| }; | |
| const entryView = host.ticket?.entryView || 'system'; | |
| const introRequired = host.ticket?.introRequired !== false; | |
| if (host.productionIntegrated === true && entryView === 'system' && introRequired && !hasIntegratedReturnQuery()) { | |
| /* A new experimental career first sees the real exterior scene. The | |
| story rail then offers the protected tutorial or the required faction | |
| gate without ever routing through the ship cutaway. */ | |
| experience.ready.then(() => experience.startFirstEntryIntro()).catch(error => { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| console.error('[MASSFRONT GALACTIC FIRST ENTRY]', error); | |
| }); | |
| } else if (host.productionIntegrated === true && entryView === 'campaign_hub') { | |
| /* Strategic controls are DOM + campaign state, so expose them on the | |
| first module frame. Exterior PBR and the optional ship cutaway no | |
| longer hold Campaign Hub navigation behind a multi-minute asset load. */ | |
| Promise.resolve(experience.openCampaignHub({ persist: false })).catch(error => { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| console.error('[MASSFRONT GALACTIC ENTRY]', error); | |
| }); | |
| } | |
| experience.ready.catch(error => { | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| console.error('[MASSFRONT SPACE]', error); | |
| }); | |
| experience.ready.then(() => { | |
| if (window.__MASSFRONT_SPACE__ === experience && !experience.disposed | |
| && !window.__MASSFRONT_SPACE_ERROR__) acknowledgeMountedRuntimeReady(mountedRuntime); | |
| }, () => {}); | |
| consumeReturnedTacticalResult(experience, host).catch(error => quarantineReturnedTacticalResult(experience, error)); | |
| } catch (error) { | |
| if (hostSelectionError || hasIntegratedReturnQuery() || selectedHost?.productionIntegrated === true) showIntegratedFailure(error); | |
| else { | |
| // createSpaceExperience paints the player-facing failure state before it | |
| // throws. Catch here so the standalone bootstrap never strands the shell | |
| // in an indefinite loading state or produces an unhandled module error. | |
| window.__MASSFRONT_SPACE_ERROR__ = error; | |
| console.error('[MASSFRONT SPACE]', error); | |
| } | |
| } | |
| } | |
| function rebuildAfterGpuInterruption() { | |
| if (gpuRebuildPending) return; | |
| gpuRebuildPending = true; | |
| const current = window.__MASSFRONT_SPACE__; | |
| window.__MASSFRONT_SPACE__ = null; | |
| try { current?.dispose?.(); } catch (error) { console.warn('[MASSFRONT GPU] renderer disposal during recovery failed', error); } | |
| gpuRebuilds++; | |
| window.setTimeout(() => { | |
| gpuRebuildPending = false; | |
| document.querySelector('[data-render-retry]')?.removeAttribute('aria-busy'); | |
| if (gpuRebuilds <= 2) boot(); | |
| else { | |
| const frame = document.getElementById('moduleFrame'); | |
| const veil = frame?.querySelector('#renderVeil'); | |
| if (veil) { | |
| veil.className = 'render-veil failed'; | |
| const title = veil.querySelector('b'); | |
| const status = veil.querySelector('#loadStatus'); | |
| if (title) title.textContent = 'GPU PROCESS REMAINS UNSTABLE'; | |
| if (status) status.textContent = 'TWO CLEAN WEBGL2 RENDERERS WERE INTERRUPTED · CLOSE OTHER GPU-HEAVY WINDOWS, THEN RETRY'; | |
| exposeFatalActions(veil); | |
| } | |
| } | |
| }, 500); | |
| } | |
| window.addEventListener('massfront:space-gpu-stalled', rebuildAfterGpuInterruption); | |
| installFatalReturn(); | |
| installFatalRetry(); | |
| window.__MASSFRONT_SPACE_MODULE_BOUND__ = true; | |
| if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot, { once: true }); | |
| else boot(); | |