PURPOSE
Loads and serves a tiny set of HUD icon sprites (gear, heart) used by in-game UI chrome. Not for weapon, upgrade, or entity artwork. Provides a synchronous accessor that returns null until preload resolves, so callers must fall back gracefully during the first few frames after boot.
OWNS
ICON_PATHSconst map fromUiIconIdto public asset paths (/icons/gear-outline.png,/icons/heart-outline.png).UiIconIdtype, derived askeyof typeof ICON_PATHS.- Private
_cachepartial record of decodedHTMLImageElementper icon id.
READS FROM
- Browser
Imageconstructor and the public/icons/asset directory. - Image
naturalWidthandnaturalHeightafter load, used to reject empty/broken decodes before caching.
PUSHES TO
- The internal
_cache, populated only when an image decodes with non-zero dimensions. console.warnon load error, tagged[ui-icons]with id and path.
DOES NOT
- Does not draw. Returns image handles only; rendering is the caller’s job.
- Does not retry failed loads. A failed icon stays null for the session.
- Does not throw on missing assets — resolves the preload promise regardless so boot never blocks on missing icons.
- Does not cover gameplay sprites, weapon icons, upgrade thumbnails, or any artwork outside the gear/heart pair.
Signals
- Successful preload:
getUiIcon(id)transitions from null to anHTMLImageElementafterpreloadUiIconsresolves. - Failed preload:
[ui-icons] <id>: failed to load <path>warning; that id remains null forever.
Entry points
getUiIcon(id: UiIconId): HTMLImageElement | null— synchronous HUD accessor.preloadUiIcons(): Promise<void>— boot-time loader, resolves after all icons settle (success or error).
Pattern notes
- Null-tolerant accessor pattern: synchronous getter returns null pre-load instead of throwing, matching the HUD’s per-frame render loop where missing chrome is acceptable on early frames.
- Boundary defensiveness — image
onerroris caught and logged as a warning rather than rejected, so a single missing icon cannot block boot or other icons. - Cache validation gate — only images with non-zero
naturalWidth/naturalHeightare cached, filtering out broken or zero-byte responses that technically firedonload. - Closed icon set — adding a new HUD icon requires extending
ICON_PATHS;UiIconIdderives from it, so callers get a compile error if they pass an unknown id.