@jgengine/shell 0.8.0 → 0.10.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 +36 -0
- package/README.md +11 -0
- package/dist/GamePlayerShell.d.ts +10 -22
- package/dist/GamePlayerShell.js +709 -264
- package/dist/GameUiPreview.js +2 -1
- package/dist/audio/AudioComponents.js +25 -8
- package/dist/audio/audioEngine.d.ts +9 -0
- package/dist/audio/audioEngine.js +37 -0
- package/dist/audio/musicDirector.d.ts +31 -0
- package/dist/audio/musicDirector.js +125 -0
- package/dist/audio/musicVoices.d.ts +10 -0
- package/dist/audio/musicVoices.js +338 -0
- package/dist/audio/synthEngine.d.ts +9 -0
- package/dist/audio/synthEngine.js +57 -0
- package/dist/behaviour.d.ts +5 -24
- package/dist/behaviour.js +14 -50
- package/dist/behaviourAttach.d.ts +9 -0
- package/dist/behaviourAttach.js +32 -0
- package/dist/behaviourDriver.d.ts +7 -0
- package/dist/behaviourDriver.js +21 -0
- package/dist/camera/GameCameraRig.js +1 -1
- package/dist/camera/GameFirstPersonCamera.d.ts +3 -0
- package/dist/camera/GameFirstPersonCamera.js +35 -4
- package/dist/camera/GameInspectionCamera.js +12 -1
- package/dist/camera/GameOrbitCamera.js +44 -1
- package/dist/camera/PlayerFov.d.ts +18 -0
- package/dist/camera/PlayerFov.js +48 -0
- package/dist/camera/cameraBlendMath.d.ts +13 -0
- package/dist/camera/cameraBlendMath.js +36 -0
- package/dist/camera/cameraRigs.d.ts +3 -0
- package/dist/camera/cameraRigs.js +36 -33
- package/dist/camera/fovPreference.d.ts +25 -0
- package/dist/camera/fovPreference.js +73 -0
- package/dist/camera/index.d.ts +3 -0
- package/dist/camera/index.js +3 -0
- package/dist/camera/orbitCameraMath.d.ts +18 -0
- package/dist/camera/orbitCameraMath.js +6 -1
- package/dist/camera/rigMath.d.ts +10 -0
- package/dist/camera/rigMath.js +36 -1
- package/dist/camera/shakeChannel.d.ts +3 -17
- package/dist/camera/shakeChannel.js +2 -21
- package/dist/camera/shakeChannelMath.d.ts +8 -0
- package/dist/camera/shakeChannelMath.js +21 -0
- package/dist/cartridge.d.ts +145 -0
- package/dist/cartridge.js +246 -0
- package/dist/commandSink.d.ts +20 -0
- package/dist/commandSink.js +27 -0
- package/dist/defineGame.js +4 -1
- package/dist/devtools/CollisionDebugWorld.d.ts +5 -0
- package/dist/devtools/CollisionDebugWorld.js +181 -0
- package/dist/devtools/DevtoolsOverlay.d.ts +65 -1
- package/dist/devtools/DevtoolsOverlay.js +383 -41
- package/dist/devtools/collisionDebug.d.ts +57 -0
- package/dist/devtools/collisionDebug.js +127 -0
- package/dist/devtools/collisionDebugMath.d.ts +103 -0
- package/dist/devtools/collisionDebugMath.js +129 -0
- package/dist/environment/Daylight.d.ts +20 -8
- package/dist/environment/Daylight.js +63 -15
- package/dist/environment/EnvironmentScene.js +91 -35
- package/dist/environment/RoadRibbons.d.ts +7 -0
- package/dist/environment/RoadRibbons.js +57 -0
- package/dist/environment/groundPadMath.d.ts +2 -2
- package/dist/environment/groundPadMath.js +1 -1
- package/dist/environment/index.d.ts +2 -1
- package/dist/environment/index.js +1 -0
- package/dist/environment/skyLightingPolicy.d.ts +10 -0
- package/dist/environment/skyLightingPolicy.js +6 -0
- package/dist/input/mouseLook.d.ts +27 -0
- package/dist/input/mouseLook.js +35 -0
- package/dist/inputSink.d.ts +18 -0
- package/dist/inputSink.js +35 -0
- package/dist/materialOverride.d.ts +4 -6
- package/dist/materialOverride.js +12 -16
- package/dist/multiplayer.js +7 -3
- package/dist/pointer/PointerProbe.js +6 -2
- package/dist/pointer/pointerService.d.ts +3 -0
- package/dist/pointer/pointerService.js +6 -0
- package/dist/postfx/PostProcessing.d.ts +10 -0
- package/dist/postfx/PostProcessing.js +82 -0
- package/dist/postfx/gradeShader.d.ts +4 -0
- package/dist/postfx/gradeShader.js +64 -0
- package/dist/render/modelRender.d.ts +10 -1
- package/dist/render/modelRender.js +32 -5
- package/dist/render/resolveModel.d.ts +14 -0
- package/dist/render/resolveModel.js +24 -0
- package/dist/settings/QuickControls.d.ts +4 -0
- package/dist/settings/QuickControls.js +42 -0
- package/dist/settings/SettingsChrome.d.ts +1 -0
- package/dist/settings/SettingsChrome.js +10 -0
- package/dist/settings/SettingsMenu.d.ts +6 -0
- package/dist/settings/SettingsMenu.js +148 -0
- package/dist/settings/SettingsRuntime.d.ts +11 -0
- package/dist/settings/SettingsRuntime.js +19 -0
- package/dist/settings/appliedSettings.d.ts +14 -0
- package/dist/settings/appliedSettings.js +27 -0
- package/dist/settings/settingsController.d.ts +20 -0
- package/dist/settings/settingsController.js +165 -0
- package/dist/structures/GeneratedBuilding.d.ts +10 -0
- package/dist/structures/GeneratedBuilding.js +96 -8
- package/dist/structures/index.d.ts +1 -1
- package/dist/structures/index.js +1 -1
- package/dist/terrain/CarvedTerrain.d.ts +5 -1
- package/dist/terrain/CarvedTerrain.js +6 -5
- package/dist/terrain/GrassField.d.ts +3 -1
- package/dist/terrain/GrassField.js +4 -2
- package/dist/terrain/grassBudget.d.ts +3 -0
- package/dist/terrain/grassBudget.js +6 -0
- package/dist/terrain/grassGeometry.js +1 -1
- package/dist/terrain/terrainDetailMaterial.d.ts +14 -0
- package/dist/terrain/terrainDetailMaterial.js +90 -0
- package/dist/terrain/terrainMath.d.ts +8 -0
- package/dist/terrain/terrainMath.js +9 -0
- package/dist/touch/OrientationHint.d.ts +3 -0
- package/dist/touch/OrientationHint.js +13 -0
- package/dist/touch/TouchControlsOverlay.d.ts +17 -1
- package/dist/touch/TouchControlsOverlay.js +125 -9
- package/dist/visibility/CullingProvider.d.ts +21 -0
- package/dist/visibility/CullingProvider.js +134 -0
- package/dist/vision/FrustumSensorHud.d.ts +1 -6
- package/dist/vision/FrustumSensorHud.js +25 -27
- package/dist/vision/frustumSampleEqual.d.ts +2 -0
- package/dist/vision/frustumSampleEqual.js +10 -0
- package/dist/water/Ocean.js +1 -1
- package/dist/water/OceanConfig.d.ts +13 -0
- package/dist/water/OceanConfig.js +25 -17
- package/dist/water/index.d.ts +1 -1
- package/dist/water/index.js +1 -1
- package/dist/weather/FireSpreadLayer.js +7 -2
- package/dist/weather/RainField.d.ts +3 -1
- package/dist/weather/RainField.js +4 -4
- package/dist/weather/SnowField.d.ts +3 -1
- package/dist/weather/SnowField.js +4 -4
- package/dist/weather/fireSpreadPose.d.ts +2 -0
- package/dist/weather/fireSpreadPose.js +4 -0
- package/dist/weather/weatherMath.d.ts +5 -1
- package/dist/weather/weatherMath.js +7 -2
- package/dist/world/DataObjects.d.ts +1 -1
- package/dist/world/DataObjects.js +3 -1
- package/dist/world/SpriteBatch.d.ts +44 -0
- package/dist/world/SpriteBatch.js +112 -0
- package/dist/world/WorldHud.d.ts +6 -1
- package/dist/world/WorldHud.js +95 -48
- package/dist/world/entityPose.d.ts +14 -0
- package/dist/world/entityPose.js +10 -0
- package/dist/world/telegraphPulse.d.ts +1 -0
- package/dist/world/telegraphPulse.js +4 -0
- package/dist/world/worldBarSamples.d.ts +30 -0
- package/dist/world/worldBarSamples.js +57 -0
- package/dist/worldSync.d.ts +10 -0
- package/dist/worldSync.js +19 -0
- package/llms.txt +1522 -1143
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,42 @@ Agents building on the published SDK can also read this programmatically:
|
|
|
11
11
|
same data as typed values, so an updater can diff its installed version against
|
|
12
12
|
the latest and surface the migration steps.
|
|
13
13
|
|
|
14
|
+
## 0.10.0
|
|
15
|
+
|
|
16
|
+
### Migrate
|
|
17
|
+
|
|
18
|
+
- **Nothing to change for existing games** — the shared mobile-composition system (viewport allocation, region collision, `--jg-*` viewport vars) is wired automatically by the shell for every game; `HudPanel`s inside a `HudCanvas` register themselves. Legacy `orientation: "landscape" | "portrait"` keeps its advisory dismissible-hint behavior unchanged.
|
|
19
|
+
- **Opt a driving/landscape game into the strict gate**: replace the advisory `orientation` with the contract form — `orientation: { mobile: "landscape-required" }` (rules: `any` · `portrait`/`landscape` advisory · `portrait-required`/`landscape-required` · `unsupported`). In portrait the engine now shows a polished `RotateDeviceScreen`, suppresses input, freezes the sim, and unmounts the HUD/controls until the device is landscape.
|
|
20
|
+
- **Declare HUD intent** where useful: `HudPanel` gains `priority` (`critical`/`secondary`/`tertiary`), `mobileBehavior` (`hidden` unmounts on phones, `transient` softens collision, …), `allowOverlapWith`, and `collisionGroup`. Optional — omitting them keeps prior behavior.
|
|
21
|
+
- **Mobile validation now also fails on overlap**: `bun run shoot <game> --device mobile|mobile-landscape|both` exits non-zero on forbidden inter-element collisions (not just viewport overflow), naming both regions.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Shared mobile layout composition — `@jgengine/core/ui/gameLayout` (pure geometry: `resolveLayoutMode`, `intersects`, `overlapArea`, `detectLayoutCollisions`, `computeGameplayRect`, `LayoutRegion`, `GameViewportLayout`) and `@jgengine/core/ui/orientation` (`resolveOrientationRequirement`, `orientationGateActive`, `MobileOrientationRule`). `@jgengine/react` adds `GameViewportProvider` (mounted by the shell), hooks (`useGameViewportLayout`, `useGameLayoutMode`, `useGameOrientation`, `useReservedControlZones`, `useLayoutCollisions`, `useRegisterLayoutRegion`), and a headless `RotateDeviceScreen`. The provider tracks `window.visualViewport`, publishes `--jg-viewport-*` / `--jg-visual-viewport-*` / `--jg-safe-*` CSS vars, resolves the explicit layout mode, and detects forbidden region overlaps (dev `data-jg-layout-collision` + console diagnostic).
|
|
26
|
+
- Mandatory orientation contract — `PlayableGame.orientation` accepts `{ mobile: <rule> }`; `landscape-required`/`portrait-required` render an engine-owned rotate gate that blocks gameplay (input suppressed, simulation frozen, HUD/controls unmounted), self-correcting when the device is turned. Reduced-motion and safe-area respected; `visualViewport`-sized for mobile Safari/PWA.
|
|
27
|
+
- Reserved touch-control zones — the touch dock registers its joystick / action-cluster / utility rectangles (runtime-measured) as `control` regions, so HUD placement and collision validation know exactly where controls sit.
|
|
28
|
+
- HUD placement metadata — `HudPanel` gains `priority`, `mobileBehavior`, `allowOverlapWith`, `collisionGroup`, and registers as a collision-tracked layout region.
|
|
29
|
+
- Mobile-landscape shoot device — `bun run shoot --device mobile-landscape` (844×390) plus collision-gate reads that fail mobile validation on forbidden overlaps.
|
|
30
|
+
- Canyon Chase migrated as the reference landscape-required game — declares `orientation: { mobile: "landscape-required" }`, composes its HUD through coordinated `HudPanel` regions (pursuit distance critical, border secondary, survey map hidden on mobile, radio transient) instead of independent fixed corners.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- First-person projectile tracers now originate from the weapon muzzle instead of the camera/eye centerline. Hit detection is unchanged (still crosshair-accurate) — only the drawn tracer's start point moved to the viewmodel muzzle, which tracks full aim yaw and pitch. Non-viewmodel games and enemy tracers are unaffected.
|
|
35
|
+
|
|
36
|
+
## 0.9.0
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Mobile HUD fit — design-resolution UI scaling now applies to every game by default: `HudCanvas` measures the live viewport and scales the whole HUD from `PlayableGame.hudFit.designSize` (default 1600×900, clamps `minScale`/`maxScale` 0.4–1) so desktop-authored layouts shrink to fit a phone instead of overflowing it; `hudFit.mobile` overrides tune the phone fit separately. Pure math lives in `@jgengine/core/ui/hudScale` (`hudScaleForViewport`, `resolveHudFit`, `rectOverflow`, `overflowingPanels`); the shell mounts `@jgengine/react`'s `HudViewportProvider` around `GameUI` so games need no wiring.
|
|
41
|
+
- Graphics → UI scale — a player-facing `graphics.uiScale` slider (0.5–1.5, default 1) multiplies the computed HUD scale on every platform; the same resolution system drives desktop preference and mobile shrink.
|
|
42
|
+
- HUD overflow gate — `HudCanvas` measures every `HudPanel` against the viewport at runtime and reports offenders on a `data-hud-overflow` attribute (plus a console warning); `bun run shoot <game> --device mobile|both` now exits non-zero naming the panels that escape the viewport.
|
|
43
|
+
- Automatic visibility & streaming defaults — an engine-level `VisibilitySystem` (exported from `@jgengine/core`) gives every scene renderer-agnostic culling and asset-streaming policy with no per-object wiring: distance culling, preload margins, hysteresis, delayed unloading, multi-camera awareness (including cameras excluded from streaming), and per-object overrides (always-visible, never-unload, disabled culling/streaming, custom render distance and preload margin).
|
|
44
|
+
- Self-hosted asset mirror — `DEFAULT_RELEASE_BASE` now points at this repo's rolling `packs` release instead of the upstream host; a catalog-driven `mirror-assets` workflow (weekly cron + manual dispatch) keeps the mirror in sync with the asset catalog.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- Mobile HUD fit is on by default — design-resolution HUD scaling now applies to every game with no config change (previously opt-in via `platforms: ["web", "mobile"]`). A desktop-only game keeps the legacy fixed 0.85 compact zoom by declaring `platforms: ["web"]` (without `"mobile"`).
|
|
49
|
+
|
|
14
50
|
## 0.8.0
|
|
15
51
|
|
|
16
52
|
Transport-agnostic multiplayer (socket.io, WebRTC p2p, LAN/Fly adapters) plus grid/voxel
|
package/README.md
CHANGED
|
@@ -49,6 +49,17 @@ import { generateBuilding } from "@jgengine/core/world/buildings";
|
|
|
49
49
|
<GeneratedBuilding building={generateBuilding({ seed: "block-a", floors: 6 })} />;
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
Building parts are batched into one `InstancedMesh` per part kind, so a whole building costs about a dozen draw calls regardless of part count. `InstancedBuildings` batches many buildings together the same way — a full district in one pass — and is what `EnvironmentScene` uses for `building()` world features:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { InstancedBuildings } from "@jgengine/shell/structures/GeneratedBuilding";
|
|
56
|
+
import { generateBuildingDistrict } from "@jgengine/core/world/buildings";
|
|
57
|
+
|
|
58
|
+
const district = generateBuildingDistrict({ rows: 3, cols: 3, seed: "downtown" });
|
|
59
|
+
|
|
60
|
+
<InstancedBuildings buildings={district.map((building) => ({ building }))} />;
|
|
61
|
+
```
|
|
62
|
+
|
|
52
63
|
The component vocabulary (windows, awnings, AC units, clotheslines, storefronts, shutters, store signs, roof props, guardrails) and placement logic follow achrefelouafi's MIT [BuildingGeneratorThreeJS](https://github.com/achrefelouafi/BuildingGeneratorThreeJS) (see [CREDITS.md](../../CREDITS.md)).
|
|
53
64
|
|
|
54
65
|
## Terrain primitives
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { type ActionStateTracker } from "@jgengine/core/input/actionBindings";
|
|
2
2
|
import type { Aim } from "@jgengine/core/scene/spatial";
|
|
3
|
-
import { type CollisionObstacle, type MovementTuningOverrides } from "@jgengine/core/movement/movementModel";
|
|
4
|
-
import type { PhysicsConfig } from "@jgengine/core/game/defineGame";
|
|
5
3
|
import { type GameContext } from "@jgengine/core/runtime/gameContext";
|
|
6
|
-
import type
|
|
4
|
+
import { type CommandSink } from "./commandSink.js";
|
|
7
5
|
import type { SkyEnvironmentDescriptor, WorldFeature } from "@jgengine/core/world/features";
|
|
8
|
-
import { type SceneObject } from "@jgengine/core/scene/objectStore";
|
|
9
6
|
import type { ShellMultiplayer } from "./multiplayer.js";
|
|
10
7
|
import type { PlayableGame } from "./registry.js";
|
|
11
8
|
/** Actions from `input` currently held down, for `ctx.input.publish` (#164.1); includes reserved movement/jump actions. */
|
|
@@ -13,26 +10,17 @@ export declare function heldActionsFor(tracker: Pick<ActionStateTracker<string>,
|
|
|
13
10
|
/** Whether a bound action should fire this frame: on press, or on repeat interval while held (shared by `FrameDriver` and `HudOnlyDriver`). */
|
|
14
11
|
export declare function shouldFireBoundAction(tracker: Pick<ActionStateTracker<string>, "isDown" | "wasPressed">, action: string, input: PlayableGame["game"]["input"], repeatFiredAt: ReadonlyMap<string, number>, now: number): boolean;
|
|
15
12
|
/** Resolves and runs the command bound to `action` via the shell's action→command convention (shared by `FrameDriver` and `HudOnlyDriver`). */
|
|
16
|
-
export declare function dispatchBoundAction(ctx: GameContext, action: string, yaw: number, pitch: number, aim: Aim): void;
|
|
17
|
-
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
export
|
|
13
|
+
export declare function dispatchBoundAction(ctx: GameContext, action: string, yaw: number, pitch: number, aim: Aim, reserved?: ReadonlySet<string>, sink?: CommandSink): void;
|
|
14
|
+
export { applyMotionImpulses } from "@jgengine/core/runtime/motionIntents";
|
|
15
|
+
export { nearbyObstacles } from "@jgengine/core/movement/movementModel";
|
|
16
|
+
export { resolvePhysicsTuning } from "@jgengine/core/movement/playerMovement";
|
|
17
|
+
export { hasEnvironmentTerrain } from "@jgengine/core/world/terrain";
|
|
21
18
|
/** The world's declared sky, when its world feature is an environment with one (#196.1). */
|
|
22
19
|
export declare function resolveWorldSky(world: WorldFeature | undefined): SkyEnvironmentDescriptor | undefined;
|
|
23
|
-
|
|
24
|
-
* Maps the game's declared `physics` onto the movement controllers' tuning
|
|
25
|
-
* overrides. `PhysicsConfig.gravity` is a signed world acceleration (negative
|
|
26
|
-
* points down, matching every game's config and the Y-up convention), but the
|
|
27
|
-
* controllers integrate `velocityY -= gravityAcceleration * dt` and so expect a
|
|
28
|
-
* positive downward magnitude. Negating here is what keeps a down-pointing
|
|
29
|
-
* gravity pulling the player *down*; passing the signed value straight through
|
|
30
|
-
* flipped the sign and launched airborne players upward instead.
|
|
31
|
-
*/
|
|
32
|
-
export declare function resolvePhysicsTuning(physics: PhysicsConfig | undefined): MovementTuningOverrides | undefined;
|
|
33
|
-
/** True when the world is an environment feature with terrain, so the voxel controller should sample its height. */
|
|
34
|
-
export declare function hasEnvironmentTerrain(world: WorldFeature | undefined): boolean;
|
|
35
|
-
export declare function GamePlayerShell({ playable, multiplayer: rawMultiplayer, }: {
|
|
20
|
+
export declare function GamePlayerShell({ playable, multiplayer: rawMultiplayer, poster, onContextReady, }: {
|
|
36
21
|
playable: PlayableGame;
|
|
37
22
|
multiplayer?: ShellMultiplayer | null;
|
|
23
|
+
poster?: boolean;
|
|
24
|
+
/** Called once per boot after onInit/onNewPlayer with the live GameContext — a staging seam for screenshots, tests, analytics. */
|
|
25
|
+
onContextReady?: (ctx: GameContext) => void;
|
|
38
26
|
}): import("react").JSX.Element;
|