@jgengine/convex 0.46.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -26,6 +26,176 @@ At publish, rename this heading to the new version and mirror the entries into
26
26
  `packages/core/src/meta/changelog.ts` (the typed `CHANGELOG` export).
27
27
  -->
28
28
 
29
+ ## 0.48.0
30
+
31
+ ### Migrate
32
+
33
+ - **Bump lockstep SDK packages to `^0.48.0`:** `@jgengine/{core,rapier,react,ws,node,sql,convex,shell,editor,assets,navbake}`. CLI `jgengine` is `0.45.0`; `@jgengine/github` is `0.35.0`.
34
+ - A standalone game made before this release: run `jgengine sync` to get the new `optimizeDeps` line in `vite.config.ts`, or `bun dev` stops on `Cannot read file: …draco_decoder.js?url`.
35
+ - `@jgengine/shell/render/EntityPreview` → `@jgengine/core/render/EntityPreview.draw`
36
+ - `@jgengine/shell/render/SceneModels` → `@jgengine/core/model/SceneModels.draw`
37
+ - `@jgengine/shell/render/SceneWarmupGate` → `@jgengine/core/scene/SceneWarmupGate.draw`
38
+ - `@jgengine/shell/render/assetBase` → `@jgengine/core/assets/assetBase.draw`
39
+ - `@jgengine/shell/render/authoredGrade` → `@jgengine/core/render/authoredGrade`
40
+ - `@jgengine/shell/render/decoderFiles` → `@jgengine/core/assets/decoderFiles.draw`
41
+ - `@jgengine/shell/render/decoderUrls` → `@jgengine/core/assets/decoderUrls`
42
+ - `@jgengine/shell/render/displayColor` → `@jgengine/core/render/displayColor.draw`
43
+ - `@jgengine/shell/render/measureBounds` → `@jgengine/core/model/measureBounds.draw`
44
+ - `@jgengine/shell/render/measureCollisionMesh` → `@jgengine/core/model/measureCollisionMesh.draw`
45
+ - `@jgengine/shell/render/modelAssets` → `@jgengine/core/model/modelAssets`
46
+ - `@jgengine/shell/render/modelBindPose` → `@jgengine/core/model/modelBindPose.draw`
47
+ - `@jgengine/shell/render/modelLoad` → `@jgengine/core/model/modelLoad.draw`
48
+ - `@jgengine/shell/render/modelMeshMerge` → `@jgengine/core/model/modelMeshMerge.draw`
49
+ - `@jgengine/shell/render/modelNodeVisibility` → `@jgengine/core/model/modelNodeVisibility.draw`
50
+ - `@jgengine/shell/render/modelRender` → `@jgengine/core/model/modelRender.draw`
51
+ - `@jgengine/shell/render/modelScan` → `@jgengine/core/model/modelScan.draw`
52
+ - `@jgengine/shell/render/modelSurface` → `@jgengine/core/model/modelSurface.draw`
53
+ - `@jgengine/shell/render/modelWind` → `@jgengine/core/model/modelWind.draw`
54
+ - `@jgengine/shell/render/presentationLook` → `@jgengine/core/render/presentationLook.draw`
55
+ - `@jgengine/shell/render/projectedOverdraw` → `@jgengine/core/render/projectedOverdraw.draw`
56
+ - `@jgengine/shell/render/resolveModel` → `@jgengine/core/model/resolveModel`
57
+ - `@jgengine/shell/render/rigNode` → `@jgengine/core/model/rigNode.draw`
58
+ - `@jgengine/shell/render/sceneCaptureRequest` → `@jgengine/core/scene/sceneCaptureRequest.draw`
59
+ - `@jgengine/shell/render/sceneCapture` → `@jgengine/core/scene/sceneCapture.draw`
60
+ - `@jgengine/shell/render/shaderWarmup` → `@jgengine/core/render/shaderWarmup.draw`
61
+ - `@jgengine/shell/render/sharedModelImages` → `@jgengine/core/model/sharedModelImages.draw`
62
+ - `@jgengine/shell/render/spriteRender` → `@jgengine/core/render/spriteRender.draw`
63
+ - `@jgengine/shell/render/staticTransforms` → `@jgengine/core/model/staticTransforms.draw`
64
+ - `@jgengine/shell/render/submittedDraws` → `@jgengine/core/render/submittedDraws.draw`
65
+ - `@jgengine/shell/render/triangleAttribution` → `@jgengine/core/render/triangleAttribution.draw`
66
+ - `@jgengine/shell/render/useDisposable` → `@jgengine/core/render/useDisposable.draw`
67
+ - `@jgengine/shell/render/useFrameWhile` → `@jgengine/core/render/useFrameWhile.draw`
68
+ - `@jgengine/shell/render/useModelInstance` → `@jgengine/core/model/useModelInstance.draw`
69
+ - `@jgengine/shell/render/useSlicedValue` → `@jgengine/core/render/useSlicedValue.draw`
70
+
71
+ ### Changed
72
+
73
+ - `create` scaffolds the starter scene by default (trees, crates and a goal to walk to); `--scene empty` gives just the ground and the player.
74
+
75
+ ### Fixed
76
+
77
+ - `bun dev` on a game using the npm packages no longer dies on first load. Vite's dependency pre-bundler could not read the engine's `.js?url` decoder imports; the decoder module is now imported by package name and the template's `vite.config.ts` keeps it out of pre-bundling.
78
+ - `jgengine create` pulls the starter models itself again when dependencies were installed with bun or pnpm: it runs the `@jgengine/assets` CLI directly instead of looking for npm's `assets.cmd` shim.
79
+ - The model-pull command printed by `create`, the game's AGENTS.md and missing-model messages is `npx @jgengine/assets pull <pack>`, which works after any package manager's install (`npx assets` asked the registry for an unrelated package when bun or pnpm had installed).
80
+ - The builder template runs its world offline when no `VITE_CONVEX_URL` is set, instead of a blank "connect this world" page.
81
+
82
+ ## 0.47.0
83
+
84
+ ### Migrate
85
+
86
+ - **Bump lockstep SDK packages to `^0.47.0`:** `@jgengine/{core,rapier,react,ws,node,sql,convex,shell,editor,assets,navbake}`. CLI `jgengine` is `0.44.0`; `@jgengine/github` is `0.34.0`.
87
+ - `resolveScatter` returns `readonly ScatterInstance[]` (results are shared through a per-document cache). Copy before mutating.
88
+ - `--jg-hud-dock-clearance`, `--jg-hud-dock-clearance-left|center|right`, `touchDockInsets`, `touchDockClearance`, `TouchDockInsets` and `floatingJoystickZoneHeight` are gone. A game with its own touch controls registers each one with `useRegisterLayoutRegion({ id, kind: "control", collisionPolicy: "forbid" }, ref)` (`@jgengine/core/ui/viewport.view`) instead of setting the CSS variables.
89
+ - `@jgengine/core/game/ping` → `@jgengine/core/map/ping`
90
+ - `@jgengine/shell/postfx/PostProcessing` → `@jgengine/core/postfx/PostProcessing.draw`
91
+ - `@jgengine/shell/postfx/ScreenEffectsOverlay` → `@jgengine/core/postfx/ScreenEffectsOverlay.draw`
92
+ - `@jgengine/shell/postfx/atmospherePass` → `@jgengine/core/postfx/atmospherePass.draw`
93
+ - `@jgengine/shell/postfx/autoExposure` → `@jgengine/core/postfx/autoExposure.draw`
94
+ - `@jgengine/shell/postfx/contactShadowPass` → `@jgengine/core/postfx/contactShadowPass.draw`
95
+ - `@jgengine/shell/postfx/gradeShader` → `@jgengine/core/postfx/gradeShader.draw`
96
+ - `@jgengine/shell/postfx/postfxOverlay` → `@jgengine/core/postfx/postfxOverlay.draw`
97
+ - `@jgengine/shell/postfx/postfxTierPolicy` → `@jgengine/core/postfx/postfxTierPolicy`
98
+ - `@jgengine/shell/postfx/shadowPrepass` → `@jgengine/core/postfx/shadowPrepass.draw`
99
+ - `@jgengine/shell/postfx/stylizePass` → `@jgengine/core/postfx/stylizePass.draw`
100
+ - `@jgengine/shell/postfx/temporalAaPass` → `@jgengine/core/postfx/temporalAaPass.draw`
101
+ - `@jgengine/shell/vfx/ParticleEmitters` → `@jgengine/core/vfx/ParticleEmitters.draw`
102
+ - `@jgengine/shell/vfx/ParticleField` → `@jgengine/core/vfx/ParticleField.draw`
103
+ - `@jgengine/shell/vfx/RetainedVfx` → `@jgengine/core/vfx/RetainedVfx.draw`
104
+ - `@jgengine/shell/vfx/SpellVfx` → `@jgengine/core/vfx/SpellVfx.draw`
105
+ - `@jgengine/shell/vfx/WorldFloatingText` → `@jgengine/core/hud/floatingTextWorld.draw`
106
+ - `@jgengine/shell/visibility/CullingProvider` → `@jgengine/core/visibility/CullingProvider.draw`
107
+ - `@jgengine/shell/visibility/cullingDriver` → `@jgengine/core/visibility/cullingDriver`
108
+ - `@jgengine/shell/visibility/renderBounds` → `@jgengine/core/visibility/measuredBounds`
109
+ - `@jgengine/shell/vision/RevealVision` → `@jgengine/core/sensor/RevealVision.draw`
110
+ - `@jgengine/shell/vision/frustumSampleEqual` → `@jgengine/core/sensor/frustumSampleEqual`
111
+ - `@jgengine/shell/world/ImpactFeedback` → `@jgengine/core/combat/ImpactFeedback.draw`
112
+ - `@jgengine/shell/world/ShotFeedback` → `@jgengine/core/combat/ShotFeedback.draw`
113
+ - `@jgengine/shell/world/WorldPings` → `@jgengine/core/map/pingBeacons.draw`
114
+ - `@jgengine/shell/world/floatTextStyle` → `@jgengine/core/hud/floatTextStyle`
115
+ - `@jgengine/shell/world/pingPulse` → `@jgengine/core/map/pingPulse`
116
+ - `@jgengine/shell/world/telegraphPulse` → `@jgengine/core/combat/telegraphPulse`
117
+ - `@jgengine/shell/camera` → import each name from its file: `cameraShake`/`defaultCameraShake` from `@jgengine/core/camera/shake/cameraShake`, rigs from `@jgengine/core/camera/<Rig>.draw`, math from `@jgengine/core/camera/<file>`
118
+ - `CameraBlendScratch` and the blend helpers come only from `@jgengine/core/camera/cameraBlendMath.draw` (no longer re-exported by `cameraRigs.draw`)
119
+ - `fovPreference` is now `@jgengine/core/camera/fovPreference.view` (it reads `Storage`)
120
+ - `@jgengine/shell/camera/GameCameraRig` → `@jgengine/core/camera/GameCameraRig.draw`
121
+ - `@jgengine/shell/camera/GameFirstPersonCamera` → `@jgengine/core/camera/GameFirstPersonCamera.draw`
122
+ - `@jgengine/shell/camera/GameInspectionCamera` → `@jgengine/core/camera/GameInspectionCamera.draw`
123
+ - `@jgengine/shell/camera/GameOrbitCamera` → `@jgengine/core/camera/GameOrbitCamera.draw`
124
+ - `@jgengine/shell/camera/PlayerFov` → `@jgengine/core/camera/PlayerFov.draw`
125
+ - `@jgengine/shell/camera/Viewports` → `@jgengine/core/camera/Viewports.draw`
126
+ - `@jgengine/shell/camera/aimRecoil` → `@jgengine/core/camera/aimRecoil`
127
+ - `@jgengine/shell/camera/cameraBlendMath` → `@jgengine/core/camera/cameraBlendMath.draw`
128
+ - `@jgengine/shell/camera/cameraCollision` → `@jgengine/core/camera/cameraCollision`
129
+ - `@jgengine/shell/camera/cameraRigs` → `@jgengine/core/camera/cameraRigs.draw`
130
+ - `@jgengine/shell/camera/chaseHeading` → `@jgengine/core/camera/chaseHeading`
131
+ - `@jgengine/shell/camera/customMuzzle` → `@jgengine/core/camera/customMuzzle.draw`
132
+ - `@jgengine/shell/camera/fovPreference` → `@jgengine/core/camera/fovPreference.view`
133
+ - `@jgengine/shell/camera/inspectionCameraMath` → `@jgengine/core/camera/inspectionCameraMath`
134
+ - `@jgengine/shell/camera/orbitCameraMath` → `@jgengine/core/camera/orbitCameraMath`
135
+ - `@jgengine/shell/camera/rigMath` → `@jgengine/core/camera/rigMath`
136
+ - `@jgengine/shell/camera/rigResolve` → `@jgengine/core/camera/rigResolve`
137
+ - `@jgengine/core/render/environment` → `@jgengine/core/lighting/environmentLighting`
138
+ - `@jgengine/core/render/lightProbes` → `@jgengine/core/lighting/lightProbes`
139
+ - `@jgengine/core/render/lightingBalance` → `@jgengine/core/lighting/lightingBalance`
140
+ - `@jgengine/core/world/buildPermissions` → `@jgengine/core/placement/buildPermissions`
141
+ - `@jgengine/core/world/buildSockets` → `@jgengine/core/placement/buildSockets`
142
+ - `@jgengine/shell/materialOverride` → `@jgengine/core/material/materialOverride.draw`
143
+ - `@jgengine/shell/render/CascadedShadows` → `@jgengine/core/lighting/CascadedShadows.draw`
144
+ - `@jgengine/shell/render/EnvironmentLighting` → `@jgengine/core/lighting/EnvironmentLighting.draw`
145
+ - `@jgengine/shell/render/HairCards` → `@jgengine/core/material/hairCards.draw`
146
+ - `@jgengine/shell/render/IrradianceVolumeLighting` → `@jgengine/core/lighting/IrradianceVolumeLighting.draw`
147
+ - `@jgengine/shell/render/SceneLighting` → `@jgengine/core/lighting/SceneLighting.draw`
148
+ - `@jgengine/shell/render/TextureFiltering` → `@jgengine/core/material/TextureFiltering.draw`
149
+ - `@jgengine/shell/render/authoredSurfaceMaterial` → `@jgengine/core/material/authoredSurfaceMaterial.draw`
150
+ - `@jgengine/shell/render/decalGeometry` → `@jgengine/core/scene/decalGeometry.draw`
151
+ - `@jgengine/shell/render/decalTexture` → `@jgengine/core/scene/decalTexture`
152
+ - `@jgengine/shell/render/defaultSurface` → `@jgengine/core/material/defaultSurface.draw`
153
+ - `@jgengine/shell/render/imageTexture` → `@jgengine/core/material/imageTexture.draw`
154
+ - `@jgengine/shell/render/materialAppearanceSignals` → `@jgengine/core/material/appearanceSignals.draw`
155
+ - `@jgengine/shell/render/materialAsset` → `@jgengine/core/material/materialAsset.draw`
156
+ - `@jgengine/shell/render/pmremLink` → `@jgengine/core/lighting/pmremLink.draw`
157
+ - `@jgengine/shell/render/shadowCasters` → `@jgengine/core/lighting/shadowCasters.draw`
158
+ - `@jgengine/shell/render/shadowTiers` → `@jgengine/core/lighting/shadowTiers`
159
+ - `@jgengine/shell/render/stableTextureSet` → `@jgengine/core/material/stableTextureSet.draw`
160
+ - `@jgengine/shell/render/surfaceScanShader` → `@jgengine/core/material/surfaceScanShader.draw`
161
+ - `@jgengine/shell/render/surfaceScanTextures` → `@jgengine/core/material/surfaceScanTextures.draw`
162
+ - `@jgengine/shell/render/triplanarMaterial` → `@jgengine/core/material/triplanarMaterial.draw`
163
+ - `@jgengine/shell/render/wetSurfaces` → `@jgengine/core/material/wetSurfaces.draw`
164
+ - `@jgengine/shell/render/worldReflectionProbe` → `@jgengine/core/lighting/reflectionProbe.draw`
165
+
166
+ ### Added
167
+
168
+ - `createVitals` (`@jgengine/core/survival/vitals`): named survival pools with drain, delayed regen that can cost another pool, empty-pool links (starvation hurts health, raises torpor) and hysteresis flags; snapshot/restore.
169
+ - `ambientTemperature` and `bodyComfort` (`@jgengine/core/survival/bodyTemperature`): air temperature from climate, time of day, weather, altitude, wetness and heat sources; hypothermia/hyperthermia as drain multipliers and exposure damage, with insulation and fortitude.
170
+ - `createScatterHarvest` (`@jgengine/core/harvest/scatterHarvest`): any scatter placement becomes a gatherable node (tool bias, budgets, respawn) found by a cone strike; spent nodes disappear from the drawn scatter and regrow.
171
+ - `createScatterClearing` / `scatterClearingOf` (`@jgengine/core/scatter/scatterClearing`) and `InstancedScatter`'s `hidden` prop: hide felled or mined placements; `AuthoredScene` reads it.
172
+ - `ResourceNodeConfig.resolve`: nodes created lazily on first touch, so an island of trees costs nothing until one is hit.
173
+ - `terrain({ coast })` / `withCoast`: shape any terrain into an island with a beach shelf and sea floor.
174
+ - `InstancedScatter` `maxChunks` (default 400): big fields grow their chunks instead of splitting into tens of thousands of scene objects.
175
+
176
+ ### Changed
177
+
178
+ - The output is `<staging>/<Name>.exe` (runs without installing) plus `<staging>/<Name>_<version>_x64-setup.exe`.
179
+ - Every game shares one cargo target directory (`CARGO_TARGET_DIR`, default `%LOCALAPPDATA%/jgengine/desktop-target`), and Tauri's build-time asset compression is off, so only the first build compiles Tauri and later games compile only their own small crate.
180
+ - `apps/web/public/og.png` (1200x630) and `apps/web/public/apple-touch-icon.png` (180x180) are redrawn in the site's dark theme with the orange accent, replacing the old lime cards.
181
+
182
+ Prevention: none - the change is two redrawn PNG images with no code path a test could exercise
183
+
184
+ ### Fixed
185
+
186
+ - `jgengine desktop` no longer fails after compiling Rust: it generates `icon.ico` and every PNG size Tauri needs from the game's `public/icon.png`, `icon.png`, `public/cover.png` or `cover.png` (centre-cropped), or from the jgengine mark when the game has none. `--icon` takes any PNG; an unreadable one is an error, an unreadable project icon falls back to the mark with a warning.
187
+ - The desktop window's content policy allows WebAssembly (`'wasm-unsafe-eval'`) and `data:`/`blob:` fetches, so games that load physics, decoders or embedded model data no longer hang on "Preparing scene".
188
+ - An island-sized scatter field ran at ~9 fps: every 24 m chunk was a scene object per species and draw source, small detail drew at any distance, and the impostor split searched batches quadratically. Chunks are now budgeted, sub-impostor species cull past a size-scaled distance, and only chunks whose placements crossed a switch distance re-upload (59 fps on Fernwild's island).
189
+ - Clearing one placement rebuilt every scatter mesh; untouched chunks now keep their meshes.
190
+ - `HudCanvas` keeps panels clear of the measured rectangle of every region registered as kind `control` or `system`, instead of a guessed height over each bottom third of the screen. Harbor Heat's minimap, Scrap Signal's loot and vitals, Apex Nights' garage and Hold the Line's bottom bar no longer sit under touch buttons.
191
+ - Touch buttons a game pins to an anchor (`touch.buttons` with `anchor`) register as control regions, so the HUD and the collision check see them.
192
+ - `arrangeHudPanels` shrinks the HUD before lifting a panel off its edge into the play view: a bottom bar squeezed between the joystick and the action cluster (Fernwild's build bar) stays on the bottom edge at a smaller zoom, and lifts only when no zoom down to `minScale` keeps it there.
193
+ - Drift Foundry registers its steering and pedal pads as control regions; Apex Nights' garage panel grows to fit its price tags instead of spilling onto the action buttons.
194
+
195
+ ### Bends
196
+
197
+ - Deleted the three `touchDockInsets` unit tests along with the function they tested; the new "touch controls are obstacles" browser test and the solver tests cover the behaviour that replaced it.
198
+
29
199
  ## 0.46.0
30
200
 
31
201
  ### Migrate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jgengine/convex",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "description": "Convex adapters for JGengine: game transport, presence transport, and backend wiring over @jgengine/core.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "check-types": "tsgo --noEmit -p tsconfig.json"
31
31
  },
32
32
  "dependencies": {
33
- "@jgengine/core": "^0.46.0"
33
+ "@jgengine/core": "^0.48.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "convex": "^1.31.2",
@@ -6,7 +6,7 @@
6
6
 
7
7
  - `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
8
8
  - `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
9
- - `VERSION` (const): const VERSION: "0.46.0" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
9
+ - `VERSION` (const): const VERSION: "0.48.0" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
10
10
 
11
11
  ## @jgengine/core/authoring
12
12
 
@@ -420,7 +420,7 @@
420
420
 
421
421
  - `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
422
422
  - `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
423
- - `VERSION` (const): const VERSION: "0.46.0" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
423
+ - `VERSION` (const): const VERSION: "0.48.0" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
424
424
 
425
425
  ## @jgengine/core/runtime/adapter
426
426
 
@@ -810,7 +810,7 @@
810
810
  - `GameHostProps` (interface): interface GameHostProps — Props for {@link GameHost}: the playable, optional multiplayer overrides, and the optional editor loader that enables the engine-owned F2+E summon.
811
811
  - `GameLoop` (interface): interface GameLoop<TContext = unknown> — Lifecycle hooks a game implements to drive init, per-tick simulation, and player join/leave.
812
812
  - `Hotbar` (function): function Hotbar({ inventoryId, activeSlot, keys, slotSize = 46, itemIcon, style, className, }: { inventoryId: string; activeSlot?: number; keys?: readonly string[]; slotSize?: number; /** Caller-supplied item id → icon registry; return null/undefined to fall back to the default glyph. */ itemIcon?: … — A numbered hotbar bound to an inventory — painted iconed slots (a `GameIcon` glyph over a school-keyed gradient with a count badge, #1035), an active-slot highlight, and a keycap per slot. Place it and pass the `inventoryId`; `activeSlot` highlights the equipped one. Supply `itemIcon` to map your item ids to your own glyphs — the default resolves a `GameIcon` from the item id.
813
- - `HudCanvas` (function): function HudCanvas({ layout, editChord, showDuring, className, style, children, }: { layout: HudLayoutStore; editChord?: HudEditChord | false; /** Opt-in play-phase gate: render the HUD only during these phases (e.g. `["playing"]`). Omit for always-visible (default). */ showDuring?: readonly GamePha… — Full-viewport HUD surface. Each `HudPanel` names an anchor and a priority; the canvas measures every panel and places them all at once so none lands on another, at any screen size. Panels sharing an anchor stack outward from that edge; a panel that would cover a neighbour slides along its edge to the nearest free spot; when the screen is too small, the lowest-priority panels fold into a toggle, and only then does the whole HUD shrink. Device safe areas and the touch-control dock (`--jg-hud-dock-clearance-*`) are kept clear. Games declare panels, never place them per size.
813
+ - `HudCanvas` (function): function HudCanvas({ layout, editChord, showDuring, className, style, children, }: { layout: HudLayoutStore; editChord?: HudEditChord | false; /** Opt-in play-phase gate: render the HUD only during these phases (e.g. `["playing"]`). Omit for always-visible (default). */ showDuring?: readonly GamePha… — Full-viewport HUD surface. Each `HudPanel` names an anchor and a priority; the canvas measures every panel and places them all at once so none lands on another, at any screen size. Panels sharing an anchor stack outward from that edge; a panel that would cover a neighbour slides along its edge to the nearest free spot; when the screen is too small, the lowest-priority panels fold into a toggle, and only then does the whole HUD shrink. Device safe areas and every touch control (any region registered as kind `control` or `system`) are kept clear. Games declare panels, never place them per size.
814
814
  - `HudFade` (function): function HudFade({ watch, idleMs = 3500, dimTo = 0.18, hold = false, children, className, style }: HudFadeProps): ReactNode — A HUD group that steps back when nothing is happening: it fades after a quiet spell and comes back the moment a watched value changes, so the world fills the screen and the HUD speaks only when it has news. Hovering it also brings it back.
815
815
  - `HudPanel` (function): function HudPanel({ id, anchor = "top-left", order, chip, interactive, inset, locked, showDuring, priority, mobileBehavior, allowOverlapWith, collisionGroup, region = true, width, height, type, className, style, children, }: { id: string; anchor?: HudAnchor; /** Stack position within the anchor, asc… — A HUD block anchored to a corner, edge or the centre. `HudCanvas` places every panel together: panels sharing an anchor stack outward from the screen edge in ascending `order`, and a panel that would cover another slides to the nearest free spot. When the screen is too small, lower-`priority` panels fold into a toggle first. On fine pointers panels stay draggable through the edit chord; a dragged panel leaves the flow and keeps its custom placement.
816
816
  - `HudSlots` (function): function HudSlots({ storageKey, slots, overlay, showDuring = DEFAULT_SLOT_PHASES }: HudSlotsProps): ReactNode — The play HUD in one line: a few small panels pinned to the screen's edges, scaled from a 1600x900 design to any window and movable by the player (the layout is remembered per `storageKey`). Keep it to a handful of slots; the world is the picture.