PURPOSE

Asset preload entry point. Loads every image, font, and sprite-bundle the game needs before the menu is shown, so first-frame rendering and first planet switch never block on a network fetch. Reports progress as a fraction 0.0 → 1.0 via a caller-supplied callback. Designed to be called exactly once at app boot.

OWNS

  • preloadAllAssets(onProgress?) — the single public entry point that orchestrates all six preload steps and ticks progress.
  • PreloadProgress type — callback signature (fraction: number) => void.
  • _loadImg(src) — internal helper that wraps an Image element in a Promise<void> and resolves on both onload and onerror (never rejects).
  • _preloadFonts() — internal helper that uses the document.fonts FontFace API to warm Cal Sans, Space Grotesk, and Bungee at 16px / weight 400.
  • PLANET_SPRITE_PATHS — hard-coded list of 11 planet PNG paths (Landing Site, Sunrise City, Voidstar, Solaris, Speedway, Eden-5, Old Earth, Network Station, Delphi, Obelisk, Desolation).
  • TERRAIN_SPRITE_PATHS — hard-coded list of terrain PNGs (currently just /terrain/building1.png for Sunrise City).

READS FROM

  • ../rendering/ships-v4-loaderpreloadAllShipV4() for ship diffuse + normal + points bundles across every hull in the ship manifest.
  • ../rendering/enemy-spritespreloadEnemySprites() for the four enemy archetypes.
  • ../rendering/weapon-iconspreloadWeaponIcons() for weapon UI icons.
  • ../rendering/ui-iconspreloadUiIcons() for generic UI icons.
  • DOM globals — Image, document.fonts (guarded by typeof document and 'fonts' in document checks for SSR safety).
  • Static asset paths under /planets/ and /terrain/ — served from the Vite public/ folder at runtime.

PUSHES TO

  • The browser’s HTTP image cache and decoded-image cache (via Image.src = ... triggering fetch + decode).
  • The browser’s font cache and the document.fonts FontFaceSet (Cal Sans, Space Grotesk, Bungee at 16px / 400 weight).
  • The onProgress callback supplied by the caller — invoked six times, once per completed step.
  • Indirect: ship-v4 loader, enemy-sprite loader, weapon-icon loader, and UI-icon loader all populate their own module-level caches.

DOES NOT

  • Does not render anything. No canvas, no DOM mutation other than transient Image and FontFace warm-up.
  • Does not reject. Image errors resolve silently (onerror → resolve()); font errors are swallowed in a try/catch. Missing assets never block boot.
  • Does not gate steps in parallel — steps 1–6 run strictly sequentially via await. Within steps 5 and 6, paths within that step do load in parallel via Promise.all.
  • Does not retry, timeout, or cancel. A hung asset fetch will stall boot indefinitely.
  • Does not check the asset list at runtime — PLANET_SPRITE_PATHS is hard-coded and is not derived from PLANET_ORDER (the comment claims it must match but there is no programmatic link).
  • Does not preload audio, particle textures, or background art.
  • Does not de-duplicate calls — calling preloadAllAssets twice will trigger the full pipeline twice.

Signals

None. This module does not emit, subscribe to, or use the engine signal bus. Progress is communicated solely through the onProgress callback parameter; completion is communicated through resolution of the returned Promise<void>.

Entry points

  • preloadAllAssets(onProgress?: PreloadProgress): Promise<void> — only public export besides the PreloadProgress type. Called once at app boot by the boot screen / loader UI.

The boot pipeline through this module is fixed at six steps:

  1. preloadAllShipV4() — ship bundles (diffuse + normal + points per hull).
  2. preloadEnemySprites() — four enemy archetypes.
  3. _preloadFonts() — Cal Sans, Space Grotesk, Bungee.
  4. preloadWeaponIcons() then preloadUiIcons() — both awaited inside the same step before the single tick().
  5. Planet sprites — Promise.all over PLANET_SPRITE_PATHS.
  6. Terrain sprites — Promise.all over TERRAIN_SPRITE_PATHS.

The progress denominator steps = 6 is hard-coded; adding or removing a step requires updating that constant in the same edit.

Pattern notes

  • Never-reject contract. Every async helper resolves even on failure. The design choice is to keep boot resilient against missing or corrupt assets — the game continues with whatever loaded, and downstream renderers handle missing textures themselves.
  • Step granularity vs. fan-out. Steps are sequential to make progress monotonic and the progress UI smooth, but each step internally fans out (Promise.all) where it can. Steps 1, 2, 3, and 4 are sequential at the inter-step level because each is itself a fan-out inside its own loader module.
  • Hard-coded path lists. PLANET_SPRITE_PATHS and TERRAIN_SPRITE_PATHS are literal arrays in this file rather than being imported from the planet or terrain data tables. The planet list comment explicitly notes it “must match all planets in PLANET_ORDER” — drift here is a known maintenance hazard.
  • Font selection. The FontFace API call uses 400 16px "Family" strings. This warms only the 400-weight 16px variant; other weights/sizes used at runtime rely on font-display: swap to fill in lazily. The comments mention Roboto Slab and Saira but the code preloads Space Grotesk and Bungee — the source-of-truth for fonts actually warmed is the _preloadFonts body, not the file-header comment.
  • SSR guard. The font helper bails early if document is undefined or lacks a fonts property. The image helper does not guard Image — it assumes a browser environment.
  • Building bake dependency. Terrain sprites are preloaded so the building-bake step (used by Sunrise City) can synchronously read pixel data from a fully decoded image without races.
  • One-shot semantics. No idempotency guard. Caller is responsible for ensuring preloadAllAssets is invoked exactly once.