PURPOSE
Resolves runtime performance toggles and the device-adaptive pixel budget at module load. Reads URL query parameters and localStorage, combines them with mobile detection, and exports a frozen-in-practice PERF_FLAGS object plus a PERF_VERSION_TAG string that fingerprints the active toggles alongside BUILD_VERSION.
OWNS
PERF_FLAGS— single object holding every runtime perf toggle, the resolveddprOverride, thelowPerfmode resolution, and thedevScenarioselector.PERF_VERSION_TAG—BUILD_VERSIONsuffixed with the hyphen-joined names of every flag whose value is the booleantrue.- The pixel-budget heuristic:
MAX_PIXELS = 1_500_000total canvas pixels per frame, floored at DPR 1.0, ceilinged at DPR 2.0. - The three-source
lowPerfresolution order:?lowPerfquery param, thenlocalStorage.lowPerf === '1', then mobile fallback.
READS FROM
./_versionforBUILD_VERSION../_gameplayfor_IS_MOBILE.window.location.searchviaURLSearchParams(guarded bytypeof window !== 'undefined').window.localStoragefor stickylowPerfpreference (try/catch guarded for privacy-mode throws).window.devicePixelRatio,window.innerWidth,window.innerHeightfor the pixel-budget computation.
PUSHES TO
Nothing. Module-level export only — consumers import PERF_FLAGS and PERF_VERSION_TAG directly. No side effects beyond reading the URL/localStorage/window at module load.
DOES NOT
- Does not mutate
PERF_FLAGSafter module load — values are resolved once. - Does not write to
localStorage; only reads the stickylowPerfpreference. - Does not apply the DPR cap to a canvas — only computes the override value; canvas wiring lives elsewhere.
- Does not throw on missing
window— every browser API access is guarded for SSR / non-browser contexts. - Does not validate query-param values beyond a
parseFloatfordprand a!== '0'check forlowPerf.
Signals
noStickers,noTerrain,noNebula,noWorldObj,noBullets,noPostFx,noParticles,noEffects,noBackground— disable individual render layers when the matching query param is present.autoplay— present-only flag for kiosk / soak modes.webglBatch— inverted: defaultstrue, setfalseonly when?noWebglis present.perftest— present-only flag for the perf-test harness.lowPerf— boolean resolved from query → localStorage → mobile fallback. Boss data files read this viaisLowPerfMode()to skip ambient VFX layers (dustMotes,floorGlowStripes, per-swarmcorePulse,refractionSweep).devScenario— string from?dev=, empty string when absent.dprOverride—number | null.nullmeans use the native DPR; a number means cap to that value. ReturnsMath.max(1, sqrt(MAX_PIXELS / (w*h)))when desired pixels exceed the budget,2when native DPR > 2, otherwisenull.isMobile— mirror of_IS_MOBILEfor callers that already havePERF_FLAGSin scope.
Entry points
import { PERF_FLAGS } from '.../config/_perf-flags'— runtime toggles, mobile flag, DPR override,lowPerfresolution, dev scenario string.import { PERF_VERSION_TAG } from '.../config/_perf-flags'— version string with active-flag suffix, used for telemetry / cache busting.
Pattern notes
- Module-load resolution: every value is computed inside an IIFE or expression at import time. No lazy getters, no recomputation, no reactive updates if the URL changes after load.
- Pixel-budget over DPR-ratio: history note in source records v5.122.0 capped phones at DPR 1.0 (caused grainy sprites on 3× retina via browser upsampling); v5.123.3 switched to capping total pixels rendered so each device gets the highest crisp DPR under a fixed budget.
- DPR floor at 1.0 prevents desktop monitors at native DPR=1 from rendering a sub-CSS-pixel buffer that the browser then upscales — that CSS upscale was the source of soft desktop sprites.
- DPR ceiling at 2.0 is a perception-based cap: beyond 2× the eye can’t resolve more detail at phone viewing distance.
PERF_VERSION_TAGfilters by strict=== true, so non-boolean values (dprOverridenumber,devScenariostring,lowPerfwhen sourced from localStorage) only contribute to the tag when they happen to be the booleantrue. ThewebglBatchdefault oftruemeans it appears in the tag unless?noWebglis set.try/catcharoundlocalStoragereads exists because privacy modes throw on access — failure path silently falls through to the mobile heuristic.