@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.
Files changed (152) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +11 -0
  3. package/dist/GamePlayerShell.d.ts +10 -22
  4. package/dist/GamePlayerShell.js +709 -264
  5. package/dist/GameUiPreview.js +2 -1
  6. package/dist/audio/AudioComponents.js +25 -8
  7. package/dist/audio/audioEngine.d.ts +9 -0
  8. package/dist/audio/audioEngine.js +37 -0
  9. package/dist/audio/musicDirector.d.ts +31 -0
  10. package/dist/audio/musicDirector.js +125 -0
  11. package/dist/audio/musicVoices.d.ts +10 -0
  12. package/dist/audio/musicVoices.js +338 -0
  13. package/dist/audio/synthEngine.d.ts +9 -0
  14. package/dist/audio/synthEngine.js +57 -0
  15. package/dist/behaviour.d.ts +5 -24
  16. package/dist/behaviour.js +14 -50
  17. package/dist/behaviourAttach.d.ts +9 -0
  18. package/dist/behaviourAttach.js +32 -0
  19. package/dist/behaviourDriver.d.ts +7 -0
  20. package/dist/behaviourDriver.js +21 -0
  21. package/dist/camera/GameCameraRig.js +1 -1
  22. package/dist/camera/GameFirstPersonCamera.d.ts +3 -0
  23. package/dist/camera/GameFirstPersonCamera.js +35 -4
  24. package/dist/camera/GameInspectionCamera.js +12 -1
  25. package/dist/camera/GameOrbitCamera.js +44 -1
  26. package/dist/camera/PlayerFov.d.ts +18 -0
  27. package/dist/camera/PlayerFov.js +48 -0
  28. package/dist/camera/cameraBlendMath.d.ts +13 -0
  29. package/dist/camera/cameraBlendMath.js +36 -0
  30. package/dist/camera/cameraRigs.d.ts +3 -0
  31. package/dist/camera/cameraRigs.js +36 -33
  32. package/dist/camera/fovPreference.d.ts +25 -0
  33. package/dist/camera/fovPreference.js +73 -0
  34. package/dist/camera/index.d.ts +3 -0
  35. package/dist/camera/index.js +3 -0
  36. package/dist/camera/orbitCameraMath.d.ts +18 -0
  37. package/dist/camera/orbitCameraMath.js +6 -1
  38. package/dist/camera/rigMath.d.ts +10 -0
  39. package/dist/camera/rigMath.js +36 -1
  40. package/dist/camera/shakeChannel.d.ts +3 -17
  41. package/dist/camera/shakeChannel.js +2 -21
  42. package/dist/camera/shakeChannelMath.d.ts +8 -0
  43. package/dist/camera/shakeChannelMath.js +21 -0
  44. package/dist/cartridge.d.ts +145 -0
  45. package/dist/cartridge.js +246 -0
  46. package/dist/commandSink.d.ts +20 -0
  47. package/dist/commandSink.js +27 -0
  48. package/dist/defineGame.js +4 -1
  49. package/dist/devtools/CollisionDebugWorld.d.ts +5 -0
  50. package/dist/devtools/CollisionDebugWorld.js +181 -0
  51. package/dist/devtools/DevtoolsOverlay.d.ts +65 -1
  52. package/dist/devtools/DevtoolsOverlay.js +383 -41
  53. package/dist/devtools/collisionDebug.d.ts +57 -0
  54. package/dist/devtools/collisionDebug.js +127 -0
  55. package/dist/devtools/collisionDebugMath.d.ts +103 -0
  56. package/dist/devtools/collisionDebugMath.js +129 -0
  57. package/dist/environment/Daylight.d.ts +20 -8
  58. package/dist/environment/Daylight.js +63 -15
  59. package/dist/environment/EnvironmentScene.js +91 -35
  60. package/dist/environment/RoadRibbons.d.ts +7 -0
  61. package/dist/environment/RoadRibbons.js +57 -0
  62. package/dist/environment/groundPadMath.d.ts +2 -2
  63. package/dist/environment/groundPadMath.js +1 -1
  64. package/dist/environment/index.d.ts +2 -1
  65. package/dist/environment/index.js +1 -0
  66. package/dist/environment/skyLightingPolicy.d.ts +10 -0
  67. package/dist/environment/skyLightingPolicy.js +6 -0
  68. package/dist/input/mouseLook.d.ts +27 -0
  69. package/dist/input/mouseLook.js +35 -0
  70. package/dist/inputSink.d.ts +18 -0
  71. package/dist/inputSink.js +35 -0
  72. package/dist/materialOverride.d.ts +4 -6
  73. package/dist/materialOverride.js +12 -16
  74. package/dist/multiplayer.js +7 -3
  75. package/dist/pointer/PointerProbe.js +6 -2
  76. package/dist/pointer/pointerService.d.ts +3 -0
  77. package/dist/pointer/pointerService.js +6 -0
  78. package/dist/postfx/PostProcessing.d.ts +10 -0
  79. package/dist/postfx/PostProcessing.js +82 -0
  80. package/dist/postfx/gradeShader.d.ts +4 -0
  81. package/dist/postfx/gradeShader.js +64 -0
  82. package/dist/render/modelRender.d.ts +10 -1
  83. package/dist/render/modelRender.js +32 -5
  84. package/dist/render/resolveModel.d.ts +14 -0
  85. package/dist/render/resolveModel.js +24 -0
  86. package/dist/settings/QuickControls.d.ts +4 -0
  87. package/dist/settings/QuickControls.js +42 -0
  88. package/dist/settings/SettingsChrome.d.ts +1 -0
  89. package/dist/settings/SettingsChrome.js +10 -0
  90. package/dist/settings/SettingsMenu.d.ts +6 -0
  91. package/dist/settings/SettingsMenu.js +148 -0
  92. package/dist/settings/SettingsRuntime.d.ts +11 -0
  93. package/dist/settings/SettingsRuntime.js +19 -0
  94. package/dist/settings/appliedSettings.d.ts +14 -0
  95. package/dist/settings/appliedSettings.js +27 -0
  96. package/dist/settings/settingsController.d.ts +20 -0
  97. package/dist/settings/settingsController.js +165 -0
  98. package/dist/structures/GeneratedBuilding.d.ts +10 -0
  99. package/dist/structures/GeneratedBuilding.js +96 -8
  100. package/dist/structures/index.d.ts +1 -1
  101. package/dist/structures/index.js +1 -1
  102. package/dist/terrain/CarvedTerrain.d.ts +5 -1
  103. package/dist/terrain/CarvedTerrain.js +6 -5
  104. package/dist/terrain/GrassField.d.ts +3 -1
  105. package/dist/terrain/GrassField.js +4 -2
  106. package/dist/terrain/grassBudget.d.ts +3 -0
  107. package/dist/terrain/grassBudget.js +6 -0
  108. package/dist/terrain/grassGeometry.js +1 -1
  109. package/dist/terrain/terrainDetailMaterial.d.ts +14 -0
  110. package/dist/terrain/terrainDetailMaterial.js +90 -0
  111. package/dist/terrain/terrainMath.d.ts +8 -0
  112. package/dist/terrain/terrainMath.js +9 -0
  113. package/dist/touch/OrientationHint.d.ts +3 -0
  114. package/dist/touch/OrientationHint.js +13 -0
  115. package/dist/touch/TouchControlsOverlay.d.ts +17 -1
  116. package/dist/touch/TouchControlsOverlay.js +125 -9
  117. package/dist/visibility/CullingProvider.d.ts +21 -0
  118. package/dist/visibility/CullingProvider.js +134 -0
  119. package/dist/vision/FrustumSensorHud.d.ts +1 -6
  120. package/dist/vision/FrustumSensorHud.js +25 -27
  121. package/dist/vision/frustumSampleEqual.d.ts +2 -0
  122. package/dist/vision/frustumSampleEqual.js +10 -0
  123. package/dist/water/Ocean.js +1 -1
  124. package/dist/water/OceanConfig.d.ts +13 -0
  125. package/dist/water/OceanConfig.js +25 -17
  126. package/dist/water/index.d.ts +1 -1
  127. package/dist/water/index.js +1 -1
  128. package/dist/weather/FireSpreadLayer.js +7 -2
  129. package/dist/weather/RainField.d.ts +3 -1
  130. package/dist/weather/RainField.js +4 -4
  131. package/dist/weather/SnowField.d.ts +3 -1
  132. package/dist/weather/SnowField.js +4 -4
  133. package/dist/weather/fireSpreadPose.d.ts +2 -0
  134. package/dist/weather/fireSpreadPose.js +4 -0
  135. package/dist/weather/weatherMath.d.ts +5 -1
  136. package/dist/weather/weatherMath.js +7 -2
  137. package/dist/world/DataObjects.d.ts +1 -1
  138. package/dist/world/DataObjects.js +3 -1
  139. package/dist/world/SpriteBatch.d.ts +44 -0
  140. package/dist/world/SpriteBatch.js +112 -0
  141. package/dist/world/WorldHud.d.ts +6 -1
  142. package/dist/world/WorldHud.js +95 -48
  143. package/dist/world/entityPose.d.ts +14 -0
  144. package/dist/world/entityPose.js +10 -0
  145. package/dist/world/telegraphPulse.d.ts +1 -0
  146. package/dist/world/telegraphPulse.js +4 -0
  147. package/dist/world/worldBarSamples.d.ts +30 -0
  148. package/dist/world/worldBarSamples.js +57 -0
  149. package/dist/worldSync.d.ts +10 -0
  150. package/dist/worldSync.js +19 -0
  151. package/llms.txt +1522 -1143
  152. package/package.json +4 -4
@@ -0,0 +1,181 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Html, Line } from "@react-three/drei";
3
+ import { useFrame } from "@react-three/fiber";
4
+ import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
+ import * as THREE from "three";
6
+ import { useGameContext } from "@jgengine/react/provider";
7
+ import { aimProbeNeeded, anyCollisionLayerOn, colliderScanNeeded, collisionDebug, projectileListenNeeded, } from "./collisionDebug.js";
8
+ import { AIM_DAMAGE_COLOR, AIM_LASER_COLOR, AIM_MISS_COLOR, AIM_SOLID_COLOR, BODY_WIRE_COLOR, collectDebugShapes, computeAimLaser, HITBOX_WIRE_COLOR, muzzleMarkerFromOrigin, PROJECTILE_PATH_COLOR, } from "./collisionDebugMath.js";
9
+ function useCollisionDebugState() {
10
+ return useSyncExternalStore(collisionDebug.subscribe, () => collisionDebug.getState(), () => collisionDebug.getState());
11
+ }
12
+ function WireSphere({ center, radius, color, label, }) {
13
+ return (_jsxs("group", { position: [center[0], center[1], center[2]], children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [radius, 16, 12] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, transparent: true, opacity: 0.85, depthTest: false })] }), _jsx(Html, { center: true, distanceFactor: 14, zIndexRange: [25, 0], style: { pointerEvents: "none" }, children: _jsx("span", { className: "rounded bg-black/70 px-1 text-[9px] font-medium text-white/90", children: label }) })] }));
14
+ }
15
+ function WireAabb({ center, halfExtents, rotationY, color, label, }) {
16
+ return (_jsxs("group", { position: [center[0], center[1], center[2]], rotation: [0, rotationY, 0], children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [halfExtents[0] * 2, halfExtents[1] * 2, halfExtents[2] * 2] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, transparent: true, opacity: 0.85, depthTest: false })] }), _jsx(Html, { position: [0, halfExtents[1] + 0.15, 0], center: true, distanceFactor: 14, zIndexRange: [25, 0], style: { pointerEvents: "none" }, children: _jsx("span", { className: "rounded bg-black/70 px-1 text-[9px] font-medium text-white/90", children: label }) })] }));
17
+ }
18
+ function ColliderShapeMesh({ entry }) {
19
+ const color = entry.style === "hitbox" ? HITBOX_WIRE_COLOR : BODY_WIRE_COLOR;
20
+ if (entry.shape.kind === "sphere") {
21
+ return (_jsx(WireSphere, { center: entry.shape.center, radius: entry.shape.radius, color: color, label: entry.label }));
22
+ }
23
+ return (_jsx(WireAabb, { center: entry.shape.center, halfExtents: entry.shape.halfExtents, rotationY: entry.rotationY, color: color, label: entry.label }));
24
+ }
25
+ function endpointColor(kind) {
26
+ if (kind === "damage")
27
+ return AIM_DAMAGE_COLOR;
28
+ if (kind === "solid")
29
+ return AIM_SOLID_COLOR;
30
+ return AIM_MISS_COLOR;
31
+ }
32
+ function AimEndpointMark({ point, kind, }) {
33
+ const color = endpointColor(kind);
34
+ if (kind === "damage") {
35
+ const s = 0.14;
36
+ return (_jsxs("group", { position: [point[0], point[1], point[2]], children: [_jsx(Line, { points: [
37
+ new THREE.Vector3(-s, -s, 0),
38
+ new THREE.Vector3(s, s, 0),
39
+ ], color: color, lineWidth: 2, depthTest: false }), _jsx(Line, { points: [
40
+ new THREE.Vector3(-s, s, 0),
41
+ new THREE.Vector3(s, -s, 0),
42
+ ], color: color, lineWidth: 2, depthTest: false })] }));
43
+ }
44
+ if (kind === "solid") {
45
+ return (_jsxs("mesh", { position: [point[0], point[1], point[2]], children: [_jsx("sphereGeometry", { args: [0.1, 12, 10] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, depthTest: false })] }));
46
+ }
47
+ return (_jsxs("mesh", { position: [point[0], point[1], point[2]], children: [_jsx("sphereGeometry", { args: [0.06, 8, 8] }), _jsx("meshBasicMaterial", { color: color, transparent: true, opacity: 0.55, depthTest: false })] }));
48
+ }
49
+ function MuzzleMark({ origin }) {
50
+ const mark = muzzleMarkerFromOrigin([origin[0], origin[1], origin[2]]);
51
+ return (_jsxs("mesh", { position: [mark.center[0], mark.center[1], mark.center[2]], children: [_jsx("sphereGeometry", { args: [mark.radius, 12, 10] }), _jsx("meshBasicMaterial", { color: mark.color, depthTest: false })] }));
52
+ }
53
+ function collectFromContext(ctx, layers) {
54
+ return collectDebugShapes({
55
+ layers,
56
+ entities: ctx.scene.entity.list().map((entity) => ({
57
+ id: entity.id,
58
+ position: entity.position,
59
+ rotationY: entity.rotationY,
60
+ name: entity.name,
61
+ })),
62
+ objects: ctx.scene.object.list().map((object) => ({
63
+ instanceId: object.instanceId,
64
+ catalogId: object.catalogId,
65
+ position: object.position,
66
+ rotationY: object.rotationY,
67
+ })),
68
+ entityCollidersOf: (id) => ctx.scene.entity.collidersOf(id),
69
+ objectCollidersOf: (id) => ctx.scene.object.collidersOf(id),
70
+ objectHalfExtentsOf: (catalogId) => {
71
+ for (const object of ctx.scene.object.list()) {
72
+ if (object.catalogId !== catalogId)
73
+ continue;
74
+ const half = ctx.scene.object.catalog(object.instanceId)?.halfExtents;
75
+ if (half === undefined)
76
+ return null;
77
+ return [half[0], half[1], half[2]];
78
+ }
79
+ return null;
80
+ },
81
+ });
82
+ }
83
+ /**
84
+ * World-space collision debugger. Performs zero scene scans and zero raycasts
85
+ * when every layer is off. Mount only when shell devtools are enabled.
86
+ */
87
+ export function CollisionDebugWorld() {
88
+ const ctx = useGameContext();
89
+ const state = useCollisionDebugState();
90
+ const [shapes, setShapes] = useState([]);
91
+ const [laser, setLaser] = useState(null);
92
+ const frameCounter = useRef(0);
93
+ useEffect(() => {
94
+ if (!projectileListenNeeded(state.layers))
95
+ return;
96
+ return ctx.game.events.on("projectile.settled", (event) => {
97
+ collisionDebug.pushProjectileTrace({
98
+ origin: event.origin,
99
+ at: event.at,
100
+ hit: event.hit,
101
+ nowMs: performance.now(),
102
+ });
103
+ });
104
+ }, [ctx, state.layers.projectiles, state.layers.muzzles]);
105
+ useFrame(() => {
106
+ if (!anyCollisionLayerOn(state.layers)) {
107
+ if (shapes.length > 0)
108
+ setShapes([]);
109
+ if (laser !== null)
110
+ setLaser(null);
111
+ return;
112
+ }
113
+ frameCounter.current += 1;
114
+ const now = performance.now();
115
+ if (projectileListenNeeded(state.layers)) {
116
+ collisionDebug.pruneProjectileTraces(now);
117
+ }
118
+ if (colliderScanNeeded(state.layers) && frameCounter.current % 2 === 0) {
119
+ setShapes(collectFromContext(ctx, state.layers));
120
+ }
121
+ else if (!colliderScanNeeded(state.layers) && shapes.length > 0) {
122
+ setShapes([]);
123
+ }
124
+ if (aimProbeNeeded(state.layers)) {
125
+ const probe = collisionDebug.getAimProbe();
126
+ if (probe === null) {
127
+ if (laser !== null)
128
+ setLaser(null);
129
+ }
130
+ else {
131
+ const next = computeAimLaser({
132
+ layers: state.layers,
133
+ sceneRaycast: {
134
+ raycast: (input) => ctx.scene.raycast(input),
135
+ raycastAll: (input) => [...ctx.scene.raycastAll(input)],
136
+ },
137
+ positionOf: (id) => ctx.scene.entity.get(id)?.position,
138
+ rotationYOf: (id) => ctx.scene.entity.get(id)?.rotationY,
139
+ collidersOf: (id) => ctx.scene.entity.collidersOf(id),
140
+ from: probe.from,
141
+ aim: probe.aim,
142
+ originPolicy: probe.originPolicy,
143
+ maxDistance: probe.maxDistance ?? 100,
144
+ });
145
+ setLaser(next);
146
+ }
147
+ }
148
+ else if (laser !== null) {
149
+ setLaser(null);
150
+ }
151
+ });
152
+ const projectilePoints = useMemo(() => {
153
+ if (!state.layers.projectiles)
154
+ return [];
155
+ return state.projectileTraces.map((trace) => ({
156
+ id: trace.id,
157
+ points: [
158
+ new THREE.Vector3(trace.origin[0], trace.origin[1], trace.origin[2]),
159
+ new THREE.Vector3(trace.at[0], trace.at[1], trace.at[2]),
160
+ ],
161
+ }));
162
+ }, [state.layers.projectiles, state.projectileTraces]);
163
+ const muzzleOrigins = useMemo(() => {
164
+ if (!state.layers.muzzles)
165
+ return [];
166
+ const origins = state.projectileTraces.map((trace) => ({
167
+ id: trace.id,
168
+ origin: trace.origin,
169
+ }));
170
+ if (laser !== null && state.layers.aimLaser) {
171
+ origins.push({ id: -1, origin: laser.origin });
172
+ }
173
+ return origins;
174
+ }, [state.layers.muzzles, state.layers.aimLaser, state.projectileTraces, laser]);
175
+ if (!anyCollisionLayerOn(state.layers))
176
+ return null;
177
+ return (_jsxs("group", { children: [shapes.map((entry) => (_jsx(ColliderShapeMesh, { entry: entry }, entry.key))), projectilePoints.map((path) => (_jsx(Line, { points: path.points, color: PROJECTILE_PATH_COLOR, lineWidth: 2, transparent: true, opacity: 0.9, depthTest: false }, path.id))), muzzleOrigins.map((entry) => (_jsx(MuzzleMark, { origin: entry.origin }, `muzzle-${entry.id}`))), laser !== null ? (_jsxs(_Fragment, { children: [_jsx(Line, { points: [
178
+ new THREE.Vector3(laser.origin[0], laser.origin[1], laser.origin[2]),
179
+ new THREE.Vector3(laser.end[0], laser.end[1], laser.end[2]),
180
+ ], color: AIM_LASER_COLOR, lineWidth: 1.5, transparent: true, opacity: 0.95, depthTest: false }), _jsx(AimEndpointMark, { point: laser.end, kind: laser.kind })] })) : null] }));
181
+ }
@@ -1,4 +1,4 @@
1
- import { type DevtoolsOverrides } from "@jgengine/core/devtools/devtools";
1
+ import { type DevtoolsOverrides, type DevtoolsSnapshot } from "@jgengine/core/devtools/devtools";
2
2
  import type { GameContext } from "@jgengine/core/runtime/gameContext";
3
3
  import type { ShellMultiplayer } from "../multiplayer.js";
4
4
  import type { PlayableGame } from "../registry.js";
@@ -6,6 +6,70 @@ export declare function persistDevtoolsOverrides(gameName: string): DevtoolsOver
6
6
  export declare function applyStoredDevtoolsOverrides(gameName: string): void;
7
7
  export declare function withDevtoolsLatency(multiplayer: ShellMultiplayer): ShellMultiplayer;
8
8
  export declare function DevtoolsRendererProbe(): null;
9
+ export declare function buildLeanReport(playable: PlayableGame): {
10
+ game: string;
11
+ at: number;
12
+ why: string | null;
13
+ frame: {
14
+ fps: number;
15
+ avgFrameMs: number;
16
+ p95FrameMs: number;
17
+ maxFrameMs: number;
18
+ avgSimMs: number;
19
+ maxSimMs: number;
20
+ avgOutsideMs: number;
21
+ maxOutsideMs: number;
22
+ longFrames: number;
23
+ samples: number;
24
+ phases: {
25
+ name: string;
26
+ avgMs: number;
27
+ maxMs: number;
28
+ pctOfSim: number;
29
+ }[];
30
+ } | null;
31
+ render: import("@jgengine/core/devtools/devtools").RenderSample | null;
32
+ latency: import("@jgengine/core/devtools/devtools").LatencyStats | null;
33
+ longFrameSummary: {
34
+ count: number;
35
+ culprits: {
36
+ culprit: string;
37
+ count: number;
38
+ }[];
39
+ maxFrameMs: number;
40
+ maxDrawCalls: number | undefined;
41
+ maxGeometries: number | undefined;
42
+ } | null;
43
+ longFrames: {
44
+ at: number;
45
+ frameMs: number;
46
+ simMs: number;
47
+ outsideMs: number;
48
+ culprit: string;
49
+ reason: string;
50
+ phases: {
51
+ name: string;
52
+ ms: number;
53
+ }[];
54
+ probes: Record<string, unknown>;
55
+ render: import("@jgengine/core/devtools/devtools").RenderSample | null;
56
+ }[];
57
+ probes: Record<string, unknown>;
58
+ logs: import("@jgengine/core/devtools/devtools").DevtoolsLogEntry[] | undefined;
59
+ controls: {
60
+ name: string;
61
+ value: unknown;
62
+ initial: unknown;
63
+ }[] | undefined;
64
+ discovered: {
65
+ id: string;
66
+ value: unknown;
67
+ }[] | undefined;
68
+ discoveredCount: number;
69
+ };
70
+ export declare function buildFullReport(playable: PlayableGame): DevtoolsSnapshot & {
71
+ game: string;
72
+ };
9
73
  export declare function DevtoolsOverlay({ open, ctx, playable, multiplayer, }: {
10
74
  open: boolean;
11
75
  ctx: GameContext;