@jgengine/core 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 (303) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/ai/flock.d.ts +36 -0
  3. package/dist/ai/flock.js +182 -0
  4. package/dist/ai/groupAssist.d.ts +19 -0
  5. package/dist/ai/groupAssist.js +59 -0
  6. package/dist/ai/laneSelect.d.ts +21 -0
  7. package/dist/ai/laneSelect.js +37 -0
  8. package/dist/ai/mobBrain.d.ts +68 -0
  9. package/dist/ai/mobBrain.js +115 -0
  10. package/dist/ai/spawnDirector.d.ts +13 -0
  11. package/dist/ai/spawnDirector.js +41 -17
  12. package/dist/ai/spawnPoint.d.ts +5 -0
  13. package/dist/ai/spawnPoint.js +5 -0
  14. package/dist/ai/threat.d.ts +2 -0
  15. package/dist/ai/threat.js +34 -0
  16. package/dist/audio/audioFalloff.d.ts +5 -2
  17. package/dist/audio/music.d.ts +53 -0
  18. package/dist/audio/music.js +34 -0
  19. package/dist/audio/synth.d.ts +60 -0
  20. package/dist/audio/synth.js +8 -0
  21. package/dist/authoring.d.ts +14 -0
  22. package/dist/authoring.js +14 -0
  23. package/dist/cartridge/runtime.d.ts +15 -0
  24. package/dist/cartridge/runtime.js +556 -0
  25. package/dist/cartridge/spec.d.ts +188 -0
  26. package/dist/cartridge/spec.js +19 -0
  27. package/dist/cartridge/validate.d.ts +2 -0
  28. package/dist/cartridge/validate.js +78 -0
  29. package/dist/combat/abilityKit.d.ts +17 -2
  30. package/dist/combat/abilityKit.js +62 -13
  31. package/dist/combat/castRunner.d.ts +40 -0
  32. package/dist/combat/castRunner.js +56 -0
  33. package/dist/combat/comboPoints.d.ts +14 -0
  34. package/dist/combat/comboPoints.js +52 -0
  35. package/dist/combat/defensiveWindow.d.ts +1 -1
  36. package/dist/combat/defensiveWindow.js +5 -3
  37. package/dist/combat/dotField.d.ts +43 -0
  38. package/dist/combat/dotField.js +48 -0
  39. package/dist/combat/projectiles.d.ts +33 -12
  40. package/dist/combat/projectiles.js +214 -129
  41. package/dist/combat/regenShield.d.ts +35 -0
  42. package/dist/combat/regenShield.js +45 -0
  43. package/dist/combat/resistance.d.ts +16 -4
  44. package/dist/combat/resistance.js +43 -7
  45. package/dist/combat/resourcePool.d.ts +20 -0
  46. package/dist/combat/resourcePool.js +55 -0
  47. package/dist/combat/shotOrigin.d.ts +52 -0
  48. package/dist/combat/shotOrigin.js +86 -0
  49. package/dist/combat/telegraph.d.ts +25 -0
  50. package/dist/combat/telegraph.js +47 -0
  51. package/dist/crafting/recipe.js +4 -1
  52. package/dist/devtools/devtools.d.ts +72 -24
  53. package/dist/devtools/devtools.js +449 -101
  54. package/dist/devtools/transformTunables.js +3 -3
  55. package/dist/devtools/tunableSchema.d.ts +140 -0
  56. package/dist/devtools/tunableSchema.js +476 -0
  57. package/dist/editor/commands.d.ts +65 -0
  58. package/dist/editor/commands.js +193 -0
  59. package/dist/editor/document.d.ts +40 -0
  60. package/dist/editor/document.js +153 -0
  61. package/dist/editor/index.d.ts +30 -0
  62. package/dist/editor/index.js +6 -0
  63. package/dist/editor/types.d.ts +69 -0
  64. package/dist/editor/types.js +29 -0
  65. package/dist/faction/factions.d.ts +33 -0
  66. package/dist/faction/factions.js +76 -0
  67. package/dist/faction/reputation.d.ts +32 -0
  68. package/dist/faction/reputation.js +82 -0
  69. package/dist/game/chat.d.ts +2 -0
  70. package/dist/game/chat.js +9 -1
  71. package/dist/game/chatFilter.d.ts +15 -0
  72. package/dist/game/chatFilter.js +55 -0
  73. package/dist/game/connectedPlayers.d.ts +28 -0
  74. package/dist/game/connectedPlayers.js +21 -0
  75. package/dist/game/controlGate.d.ts +4 -0
  76. package/dist/game/controlGate.js +7 -0
  77. package/dist/game/defineGame.d.ts +44 -1
  78. package/dist/game/defineGame.js +1 -0
  79. package/dist/game/events.d.ts +25 -0
  80. package/dist/game/gamePhase.d.ts +20 -0
  81. package/dist/game/gamePhase.js +21 -0
  82. package/dist/game/keyValueStore.d.ts +25 -0
  83. package/dist/game/keyValueStore.js +61 -0
  84. package/dist/game/levelSequence.d.ts +24 -2
  85. package/dist/game/levelSequence.js +51 -2
  86. package/dist/game/lootTable.d.ts +14 -1
  87. package/dist/game/lootTable.js +28 -7
  88. package/dist/game/modelAnimation.d.ts +8 -0
  89. package/dist/game/modelAnimation.js +18 -0
  90. package/dist/game/playableGame.d.ts +116 -4
  91. package/dist/game/playableGame.js +1 -1
  92. package/dist/game/quest.d.ts +7 -3
  93. package/dist/game/quest.js +17 -8
  94. package/dist/game/race.d.ts +39 -1
  95. package/dist/game/race.js +96 -11
  96. package/dist/game/recordBook.d.ts +27 -0
  97. package/dist/game/recordBook.js +86 -0
  98. package/dist/game/talents.d.ts +47 -0
  99. package/dist/game/talents.js +140 -0
  100. package/dist/index.d.ts +8 -0
  101. package/dist/index.js +8 -0
  102. package/dist/input/actionBindings.d.ts +2 -0
  103. package/dist/input/actionBindings.js +1 -0
  104. package/dist/input/axisInput.d.ts +33 -3
  105. package/dist/input/axisInput.js +60 -4
  106. package/dist/input/bindingOverrides.d.ts +25 -0
  107. package/dist/input/bindingOverrides.js +95 -0
  108. package/dist/input/pointerAxis.d.ts +30 -0
  109. package/dist/input/pointerAxis.js +31 -0
  110. package/dist/input/touchScheme.d.ts +6 -0
  111. package/dist/input/touchScheme.js +45 -7
  112. package/dist/interaction/contextMenu.d.ts +1 -0
  113. package/dist/interaction/contextMenu.js +1 -0
  114. package/dist/interaction/proximityPrompt.d.ts +3 -1
  115. package/dist/interaction/proximityPrompt.js +3 -3
  116. package/dist/meta/changelog.d.ts +1 -1
  117. package/dist/meta/changelog.js +44 -1
  118. package/dist/movement/dash.d.ts +3 -0
  119. package/dist/movement/dash.js +19 -5
  120. package/dist/movement/glideModel.d.ts +44 -0
  121. package/dist/movement/glideModel.js +54 -0
  122. package/dist/movement/grappleSwing.d.ts +34 -0
  123. package/dist/movement/grappleSwing.js +56 -0
  124. package/dist/movement/leaderTrail.d.ts +29 -0
  125. package/dist/movement/leaderTrail.js +67 -0
  126. package/dist/movement/movementModel.d.ts +4 -0
  127. package/dist/movement/movementModel.js +13 -0
  128. package/dist/movement/playerMovement.d.ts +41 -0
  129. package/dist/movement/playerMovement.js +181 -0
  130. package/dist/movement/steering.d.ts +27 -0
  131. package/dist/movement/steering.js +40 -0
  132. package/dist/multiplayer/feedWriteGate.d.ts +10 -0
  133. package/dist/multiplayer/feedWriteGate.js +12 -0
  134. package/dist/multiplayer/presenceModel.d.ts +14 -2
  135. package/dist/multiplayer/presenceModel.js +15 -3
  136. package/dist/nav/corridors.d.ts +30 -0
  137. package/dist/nav/corridors.js +69 -0
  138. package/dist/nav/navGrid.js +30 -4
  139. package/dist/nav/railGraph.d.ts +66 -0
  140. package/dist/nav/railGraph.js +129 -0
  141. package/dist/nav/timetable.d.ts +41 -0
  142. package/dist/nav/timetable.js +94 -0
  143. package/dist/physics/buoyancy.d.ts +6 -0
  144. package/dist/physics/buoyancy.js +14 -0
  145. package/dist/physics/flowTube.d.ts +32 -0
  146. package/dist/physics/flowTube.js +64 -0
  147. package/dist/physics/forceVolume.d.ts +27 -0
  148. package/dist/physics/forceVolume.js +38 -0
  149. package/dist/physics/kinematicVehicle.d.ts +52 -0
  150. package/dist/physics/kinematicVehicle.js +81 -0
  151. package/dist/physics/physicsWorld.d.ts +13 -6
  152. package/dist/physics/physicsWorld.js +169 -40
  153. package/dist/physics/ragdoll.js +1 -1
  154. package/dist/physics/vehicleBody.js +2 -1
  155. package/dist/random/rng.d.ts +2 -0
  156. package/dist/random/rng.js +2 -0
  157. package/dist/random/seedLink.d.ts +5 -0
  158. package/dist/random/seedLink.js +35 -0
  159. package/dist/render/postProcessing.d.ts +56 -0
  160. package/dist/render/postProcessing.js +1 -0
  161. package/dist/runtime/adapter.d.ts +19 -0
  162. package/dist/runtime/adapter.js +11 -5
  163. package/dist/runtime/cameraDirector.d.ts +6 -1
  164. package/dist/runtime/cameraDirector.js +6 -0
  165. package/dist/runtime/commandRunner.d.ts +2 -2
  166. package/dist/runtime/commandRunner.js +2 -2
  167. package/dist/runtime/gameContext.d.ts +72 -8
  168. package/dist/runtime/gameContext.js +374 -61
  169. package/dist/runtime/gameRuntime.d.ts +5 -1
  170. package/dist/runtime/gameRuntime.js +13 -12
  171. package/dist/runtime/hostPersistence.d.ts +9 -1
  172. package/dist/runtime/hostPersistence.js +23 -8
  173. package/dist/runtime/hostedGameRunner.d.ts +49 -0
  174. package/dist/runtime/hostedGameRunner.js +62 -0
  175. package/dist/runtime/hostedWorldSession.d.ts +65 -0
  176. package/dist/runtime/hostedWorldSession.js +57 -0
  177. package/dist/runtime/inputSnapshot.d.ts +18 -0
  178. package/dist/runtime/inputSnapshot.js +7 -0
  179. package/dist/runtime/motionIntents.d.ts +16 -6
  180. package/dist/runtime/motionIntents.js +31 -2
  181. package/dist/runtime/snapshot.d.ts +1 -0
  182. package/dist/runtime/snapshot.js +1 -1
  183. package/dist/runtime/visibility.d.ts +74 -0
  184. package/dist/runtime/visibility.js +127 -0
  185. package/dist/runtime/worldChannel.d.ts +58 -0
  186. package/dist/runtime/worldChannel.js +69 -0
  187. package/dist/runtime/worldMirror.d.ts +24 -0
  188. package/dist/runtime/worldMirror.js +31 -0
  189. package/dist/runtime/worldReplication.d.ts +46 -0
  190. package/dist/runtime/worldReplication.js +185 -0
  191. package/dist/runtime/worldSnapshot.d.ts +17 -0
  192. package/dist/runtime/worldSnapshot.js +15 -0
  193. package/dist/scene/assetCatalog.d.ts +1 -0
  194. package/dist/scene/colliders.d.ts +50 -0
  195. package/dist/scene/colliders.js +101 -0
  196. package/dist/scene/entityStats.d.ts +4 -0
  197. package/dist/scene/entityStats.js +21 -0
  198. package/dist/scene/entityStore.d.ts +51 -5
  199. package/dist/scene/entityStore.js +119 -12
  200. package/dist/scene/objectQuery.d.ts +13 -2
  201. package/dist/scene/objectQuery.js +34 -2
  202. package/dist/scene/objectStore.d.ts +2 -0
  203. package/dist/scene/objectStore.js +31 -12
  204. package/dist/scene/sceneRaycast.d.ts +80 -0
  205. package/dist/scene/sceneRaycast.js +284 -0
  206. package/dist/scene/spatial.d.ts +11 -16
  207. package/dist/scene/spatial.js +99 -38
  208. package/dist/sensor/recordingBuffer.d.ts +6 -0
  209. package/dist/sensor/recordingBuffer.js +7 -0
  210. package/dist/sensor/replayLoop.d.ts +39 -0
  211. package/dist/sensor/replayLoop.js +64 -0
  212. package/dist/sensor/visionCone.d.ts +31 -0
  213. package/dist/sensor/visionCone.js +72 -0
  214. package/dist/session/extraction.d.ts +2 -2
  215. package/dist/session/extraction.js +13 -2
  216. package/dist/settings/settingsModel.d.ts +97 -0
  217. package/dist/settings/settingsModel.js +100 -0
  218. package/dist/stats/statModifiers.d.ts +5 -2
  219. package/dist/stats/statModifiers.js +32 -14
  220. package/dist/store/observableKeyedStore.d.ts +4 -0
  221. package/dist/store/observableKeyedStore.js +17 -2
  222. package/dist/survival/decayMeter.d.ts +1 -1
  223. package/dist/survival/decayMeter.js +0 -1
  224. package/dist/tactics/fallingGrid.d.ts +2 -2
  225. package/dist/tactics/fallingGrid.js +2 -2
  226. package/dist/time/beatClock.d.ts +18 -0
  227. package/dist/time/beatClock.js +24 -0
  228. package/dist/time/idleProgress.d.ts +29 -0
  229. package/dist/time/idleProgress.js +31 -0
  230. package/dist/time/serverTick.d.ts +7 -1
  231. package/dist/time/serverTick.js +27 -4
  232. package/dist/time/stateSchedule.d.ts +57 -0
  233. package/dist/time/stateSchedule.js +121 -0
  234. package/dist/turn/commit.d.ts +2 -2
  235. package/dist/turn/commit.js +2 -2
  236. package/dist/ui/gameLayout.d.ts +125 -0
  237. package/dist/ui/gameLayout.js +129 -0
  238. package/dist/ui/hudLayout.d.ts +58 -0
  239. package/dist/ui/hudLayout.js +207 -0
  240. package/dist/ui/hudScale.d.ts +44 -0
  241. package/dist/ui/hudScale.js +55 -0
  242. package/dist/ui/orientation.d.ts +39 -0
  243. package/dist/ui/orientation.js +49 -0
  244. package/dist/ui/swingTimer.d.ts +42 -0
  245. package/dist/ui/swingTimer.js +38 -0
  246. package/dist/visibility/assetStreaming.d.ts +66 -0
  247. package/dist/visibility/assetStreaming.js +201 -0
  248. package/dist/visibility/bounds.d.ts +66 -0
  249. package/dist/visibility/bounds.js +113 -0
  250. package/dist/visibility/camera.d.ts +21 -0
  251. package/dist/visibility/camera.js +3 -0
  252. package/dist/visibility/config.d.ts +21 -0
  253. package/dist/visibility/config.js +1 -0
  254. package/dist/visibility/diagnostics.d.ts +26 -0
  255. package/dist/visibility/diagnostics.js +36 -0
  256. package/dist/visibility/distance.d.ts +11 -0
  257. package/dist/visibility/distance.js +30 -0
  258. package/dist/visibility/frustum.d.ts +47 -0
  259. package/dist/visibility/frustum.js +186 -0
  260. package/dist/visibility/occlusion.d.ts +36 -0
  261. package/dist/visibility/occlusion.js +45 -0
  262. package/dist/visibility/settings.d.ts +75 -0
  263. package/dist/visibility/settings.js +49 -0
  264. package/dist/visibility/simulationCulling.d.ts +34 -0
  265. package/dist/visibility/simulationCulling.js +36 -0
  266. package/dist/visibility/spatialIndex.d.ts +45 -0
  267. package/dist/visibility/spatialIndex.js +212 -0
  268. package/dist/visibility/visibilitySystem.d.ts +90 -0
  269. package/dist/visibility/visibilitySystem.js +257 -0
  270. package/dist/world/buildings.d.ts +6 -0
  271. package/dist/world/buildings.js +152 -0
  272. package/dist/world/carve.d.ts +7 -2
  273. package/dist/world/carve.js +17 -7
  274. package/dist/world/cellStates.d.ts +45 -0
  275. package/dist/world/cellStates.js +103 -0
  276. package/dist/world/environmentSummary.d.ts +21 -4
  277. package/dist/world/environmentSummary.js +22 -3
  278. package/dist/world/features.d.ts +185 -8
  279. package/dist/world/features.js +64 -6
  280. package/dist/world/gridInstances.d.ts +7 -8
  281. package/dist/world/gridInstances.js +145 -7
  282. package/dist/world/lod.d.ts +17 -0
  283. package/dist/world/lod.js +66 -0
  284. package/dist/world/mapLayers.d.ts +60 -0
  285. package/dist/world/mapLayers.js +44 -0
  286. package/dist/world/massing.d.ts +45 -0
  287. package/dist/world/massing.js +581 -0
  288. package/dist/world/minimap.d.ts +13 -1
  289. package/dist/world/minimap.js +21 -2
  290. package/dist/world/roads.d.ts +47 -0
  291. package/dist/world/roads.js +146 -0
  292. package/dist/world/streets.d.ts +80 -0
  293. package/dist/world/streets.js +144 -0
  294. package/dist/world/terrain.d.ts +69 -3
  295. package/dist/world/terrain.js +309 -16
  296. package/dist/world/water.d.ts +7 -0
  297. package/dist/world/water.js +19 -4
  298. package/dist/world/weather.d.ts +3 -18
  299. package/dist/world/weather.js +4 -17
  300. package/dist/world/windZones.d.ts +47 -0
  301. package/dist/world/windZones.js +59 -0
  302. package/llms.txt +3013 -1726
  303. package/package.json +12 -2
@@ -0,0 +1,56 @@
1
+ /** Renderer tone-mapping curve applied by the post chain's output stage. */
2
+ export type ToneMappingMode = "aces" | "agx" | "reinhard" | "cineon" | "linear" | "none";
3
+ /** UnrealBloom stage — soft HDR glow around bright pixels (sun, glints, emissive). */
4
+ export interface BloomConfig {
5
+ /** Glow intensity. Default 0.32. */
6
+ strength?: number;
7
+ /** Glow spread radius, 0..1. Default 0.55. */
8
+ radius?: number;
9
+ /** Luminance above which a pixel blooms, 0..1. Default 0.85. */
10
+ threshold?: number;
11
+ }
12
+ /** Ground-truth ambient occlusion stage — darkens contact creases and cavities for depth. */
13
+ export interface AoConfig {
14
+ /** Sample radius in world units. Default 1.8. */
15
+ radius?: number;
16
+ /** Occlusion strength multiplier. Default 2.4. */
17
+ intensity?: number;
18
+ /** Distance over which occlusion fades out, world units. Default 3.6. */
19
+ distanceFalloff?: number;
20
+ /** Blend the AO onto the beauty at this fraction, 0..1. Default 1. */
21
+ blend?: number;
22
+ }
23
+ /** Final colour-grade stage: lift/gain/gamma, saturation, vignette, film grain — applied in display space after tone mapping. */
24
+ export interface GradeConfig {
25
+ /** Additive shadow tint (RGB, ~0..0.1). Default cool [0.012, 0.010, 0.018]. */
26
+ lift?: readonly [number, number, number];
27
+ /** Multiplicative highlight tint (RGB, ~1). Default warm [1.05, 1.02, 0.98]. */
28
+ gain?: readonly [number, number, number];
29
+ /** Output gamma. Default 0.96. */
30
+ gamma?: number;
31
+ /** Saturation multiplier around luma. Default 1.12. */
32
+ saturation?: number;
33
+ /** Vignette darkening strength at the corners, 0..1. Default 0.2. */
34
+ vignette?: number;
35
+ /** Animated film-grain amplitude. Default 0.012. */
36
+ grain?: number;
37
+ }
38
+ /**
39
+ * Declarative post-processing chain (RenderPass → AO → Bloom → tone-map output →
40
+ * Grade). Present on a game means the shell mounts an `EffectComposer` and owns
41
+ * the render; absent means the renderer draws directly (unchanged). Each stage is
42
+ * a config object, `false` to skip, or omitted for its default. Pure data — no
43
+ * three.js types leak into core.
44
+ */
45
+ export interface PostProcessingConfig {
46
+ /** Master switch; a config object with `enabled: false` mounts nothing. Default true. */
47
+ enabled?: boolean;
48
+ /** Tone-mapping curve the output stage applies. Default "aces". */
49
+ toneMapping?: ToneMappingMode;
50
+ /** Exposure multiplier applied before tone mapping. Default 1. */
51
+ exposure?: number;
52
+ bloom?: BloomConfig | false;
53
+ /** Ambient occlusion. Heavier than the other stages — omit or `false` on low-end targets. Default off (omitted). */
54
+ ao?: AoConfig | false;
55
+ grade?: GradeConfig | false;
56
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,52 +1,71 @@
1
1
  export type MultiplayerTopology = "shared" | "lobbies" | "private";
2
+ /**
3
+ * Where the world simulation is authoritative. `"client"` (default) keeps the historical model — each client runs
4
+ * its own `onTick` and syncs only presence/feeds/chat. `"server"` opts into host-authoritative replication: the
5
+ * host runs the loop, and the shell mirrors the server's world into the local `ctx` instead of simulating locally.
6
+ */
7
+ export type MultiplayerAuthority = "server" | "client";
2
8
  export type MultiplayerAdapterConfig = {
3
9
  kind: "convex";
4
10
  topology?: MultiplayerTopology;
11
+ authority?: MultiplayerAuthority;
5
12
  } | {
6
13
  kind: "ws";
7
14
  topology?: MultiplayerTopology;
8
15
  url?: string;
16
+ authority?: MultiplayerAuthority;
9
17
  } | {
10
18
  kind: "socketio";
11
19
  topology?: MultiplayerTopology;
12
20
  url?: string;
21
+ authority?: MultiplayerAuthority;
13
22
  } | {
14
23
  kind: "p2p";
15
24
  topology?: MultiplayerTopology;
16
25
  room?: string;
26
+ authority?: MultiplayerAuthority;
17
27
  } | {
18
28
  kind: "lan";
19
29
  topology?: MultiplayerTopology;
20
30
  port?: number;
21
31
  path?: string;
32
+ authority?: MultiplayerAuthority;
22
33
  } | {
23
34
  kind: "offline";
24
35
  };
25
36
  export declare function convex(config?: {
26
37
  topology?: MultiplayerTopology;
38
+ authority?: MultiplayerAuthority;
27
39
  }): MultiplayerAdapterConfig;
28
40
  export declare function ws(config?: {
29
41
  topology?: MultiplayerTopology;
30
42
  url?: string;
43
+ authority?: MultiplayerAuthority;
31
44
  }): MultiplayerAdapterConfig;
32
45
  export declare function fly(config: {
33
46
  app: string;
34
47
  topology?: MultiplayerTopology;
35
48
  path?: string;
49
+ authority?: MultiplayerAuthority;
36
50
  }): MultiplayerAdapterConfig;
37
51
  export declare function socketIo(config?: {
38
52
  topology?: MultiplayerTopology;
39
53
  url?: string;
54
+ authority?: MultiplayerAuthority;
40
55
  }): MultiplayerAdapterConfig;
41
56
  export declare function p2p(config?: {
42
57
  topology?: MultiplayerTopology;
43
58
  room?: string;
59
+ authority?: MultiplayerAuthority;
44
60
  }): MultiplayerAdapterConfig;
45
61
  export declare function lan(config?: {
46
62
  topology?: MultiplayerTopology;
47
63
  port?: number;
48
64
  path?: string;
65
+ authority?: MultiplayerAuthority;
49
66
  }): MultiplayerAdapterConfig;
67
+ /** True when the adapter opts into host-authoritative world replication (`authority: "server"`). */
68
+ export declare function isServerAuthoritative(multiplayer: unknown): boolean;
50
69
  export declare function offline(): MultiplayerAdapterConfig;
51
70
  export declare function adapterOf(multiplayer: unknown): MultiplayerAdapterConfig | null;
52
71
  export declare function multiplayerAdapterKind(multiplayer: unknown): string | null;
@@ -1,24 +1,30 @@
1
1
  export function convex(config) {
2
- return { kind: "convex", topology: config?.topology ?? "shared" };
2
+ return { kind: "convex", topology: config?.topology ?? "shared", authority: config?.authority };
3
3
  }
4
4
  export function ws(config) {
5
- return { kind: "ws", topology: config?.topology ?? "shared", url: config?.url };
5
+ return { kind: "ws", topology: config?.topology ?? "shared", url: config?.url, authority: config?.authority };
6
6
  }
7
7
  export function fly(config) {
8
8
  return {
9
9
  kind: "ws",
10
10
  topology: config.topology ?? "shared",
11
11
  url: `wss://${config.app}.fly.dev${config.path ?? "/ws"}`,
12
+ authority: config.authority,
12
13
  };
13
14
  }
14
15
  export function socketIo(config) {
15
- return { kind: "socketio", topology: config?.topology ?? "shared", url: config?.url };
16
+ return { kind: "socketio", topology: config?.topology ?? "shared", url: config?.url, authority: config?.authority };
16
17
  }
17
18
  export function p2p(config) {
18
- return { kind: "p2p", topology: config?.topology ?? "private", room: config?.room };
19
+ return { kind: "p2p", topology: config?.topology ?? "private", room: config?.room, authority: config?.authority };
19
20
  }
20
21
  export function lan(config) {
21
- return { kind: "lan", topology: config?.topology ?? "shared", port: config?.port, path: config?.path };
22
+ return { kind: "lan", topology: config?.topology ?? "shared", port: config?.port, path: config?.path, authority: config?.authority };
23
+ }
24
+ /** True when the adapter opts into host-authoritative world replication (`authority: "server"`). */
25
+ export function isServerAuthoritative(multiplayer) {
26
+ const adapter = adapterOf(multiplayer);
27
+ return adapter !== null && "authority" in adapter && adapter.authority === "server";
22
28
  }
23
29
  export function offline() {
24
30
  return { kind: "offline" };
@@ -1,10 +1,15 @@
1
- import type { CinematicCameraConfig } from "../game/playableGame.js";
1
+ import type { ChaseCameraConfig, CinematicCameraConfig } from "../game/playableGame.js";
2
+ /** Runtime patch over the static `camera.chase` config — distance/height/fov retuning from gameplay events (#286.11). */
3
+ export type ChaseCameraTuning = Partial<Pick<ChaseCameraConfig, "distance" | "height" | "lookHeight" | "springDamping" | "fov" | "lead" | "bank">>;
2
4
  export interface CameraDirector {
3
5
  follow(entityId: string | null): void;
4
6
  /** `undefined` means no runtime override — the shell falls back to the static `playable.camera.followEntityId`. `null` means explicitly follow nothing. */
5
7
  followedEntityId(): string | null | undefined;
6
8
  setCinematic(config: CinematicCameraConfig | null): void;
7
9
  cinematic(): CinematicCameraConfig | null;
10
+ /** Overlay a runtime patch on the chase rig's config — a boss-intro pull-back, drift zoom-out; `null` restores the static config. */
11
+ setChaseTuning(tuning: ChaseCameraTuning | null): void;
12
+ chaseTuning(): ChaseCameraTuning | null;
8
13
  subscribe(listener: () => void): () => void;
9
14
  }
10
15
  export declare function createCameraDirector(): CameraDirector;
@@ -2,6 +2,7 @@ export function createCameraDirector() {
2
2
  const listeners = new Set();
3
3
  let followEntity = undefined;
4
4
  let cinematicConfig = null;
5
+ let chaseTuningPatch = null;
5
6
  function notify() {
6
7
  for (const listener of listeners)
7
8
  listener();
@@ -17,6 +18,11 @@ export function createCameraDirector() {
17
18
  notify();
18
19
  },
19
20
  cinematic: () => cinematicConfig,
21
+ setChaseTuning(tuning) {
22
+ chaseTuningPatch = tuning;
23
+ notify();
24
+ },
25
+ chaseTuning: () => chaseTuningPatch,
20
26
  subscribe(listener) {
21
27
  listeners.add(listener);
22
28
  return () => listeners.delete(listener);
@@ -2,8 +2,8 @@ export type CommandValidationError = {
2
2
  reason: string;
3
3
  };
4
4
  export type CommandDef<TInput = unknown> = {
5
- validate: (snapshot: import("./snapshot.js").GameRuntimeSnapshot, input: TInput) => CommandValidationError | null;
6
- apply: (snapshot: import("./snapshot.js").GameRuntimeSnapshot, input: TInput) => import("./snapshot.js").GameRuntimeSnapshot;
5
+ validate: (snapshot: import("./snapshot.js").GameRuntimeSnapshot, input: TInput, actorUserId: string) => CommandValidationError | null;
6
+ apply: (snapshot: import("./snapshot.js").GameRuntimeSnapshot, input: TInput, actorUserId: string) => import("./snapshot.js").GameRuntimeSnapshot;
7
7
  };
8
8
  export type RunCommandResult = {
9
9
  ok: true;
@@ -3,11 +3,11 @@ export function runCommand(snapshot, commands, commandName, input, actorUserId)
3
3
  if (!command) {
4
4
  return { ok: false, reason: `Unknown command: ${commandName}` };
5
5
  }
6
- const validationError = command.validate(snapshot, input);
6
+ const validationError = command.validate(snapshot, input, actorUserId);
7
7
  if (validationError) {
8
8
  return { ok: false, reason: validationError.reason };
9
9
  }
10
- const next = command.apply(snapshot, input);
10
+ const next = command.apply(snapshot, input, actorUserId);
11
11
  return {
12
12
  ok: true,
13
13
  snapshot: {
@@ -28,18 +28,23 @@ import { type PoseAllowedStates, type PoseState } from "../movement/poseState.js
28
28
  import type { ModelAssetRef } from "../scene/assetCatalog.js";
29
29
  import { type PaintLayer } from "../scene/paintLayer.js";
30
30
  import { type EntityStatsApi, type StatCatalog } from "../scene/entityStats.js";
31
- import type { EntityPose, EntityPosition, EntityStore, SceneEntity, SpawnOptions, SpawnPose } from "../scene/entityStore.js";
31
+ import type { EntityBlackboard, EntityPose, EntityPosition, EntityStore, SceneEntity, SpawnOptions, SpawnPose } from "../scene/entityStore.js";
32
32
  import { type Forms } from "../scene/form.js";
33
+ import { type EntityColliderSet } from "../scene/colliders.js";
33
34
  import { type ObjectRaycastHit, type ObjectRaycastInput } from "../scene/objectQuery.js";
34
35
  import { type ObjectStore } from "../scene/objectStore.js";
35
36
  import { type Roster } from "../scene/roster.js";
37
+ import { type ConnectedPlayers } from "../game/connectedPlayers.js";
36
38
  import { type Possession } from "../scene/possession.js";
39
+ import { type SceneRaycastHit, type SceneRaycastInput } from "../scene/sceneRaycast.js";
37
40
  import { type SpatialApi } from "../scene/spatial.js";
38
41
  import { type CycleTargetOptions } from "../scene/targeting.js";
39
42
  import { type Stats } from "../stats/statModifiers.js";
40
43
  import { type ObservableKeyedStore } from "../store/observableKeyedStore.js";
44
+ import { type WorldSnapshot } from "./worldSnapshot.js";
41
45
  import { type SimClock } from "../time/simClock.js";
42
46
  import { type TurnLoop, type TurnLoopConfig } from "../turn/turnLoop.js";
47
+ import { RaceState, type RaceStateConfig } from "../game/race.js";
43
48
  import { type CameraDirector } from "./cameraDirector.js";
44
49
  import { type InputSnapshot } from "./inputSnapshot.js";
45
50
  import { type MotionIntents } from "./motionIntents.js";
@@ -63,6 +68,8 @@ export interface GameContextEntityEntry {
63
68
  role?: CatalogEntityRole;
64
69
  /** Right-click context-menu verbs for this entity (#31). */
65
70
  verbs?: readonly ContextVerb[];
71
+ /** Purpose-specific colliders (physical body + named damage hitboxes). */
72
+ colliders?: EntityColliderSet;
66
73
  }
67
74
  export interface GameContextObjectEntry {
68
75
  proximityPrompt?: ProximityPrompt;
@@ -72,6 +79,8 @@ export interface GameContextObjectEntry {
72
79
  slotInventory?: InventoryLayout;
73
80
  /** Right-click context-menu verbs for this object (#31). */
74
81
  verbs?: readonly ContextVerb[];
82
+ colliders?: EntityColliderSet;
83
+ halfExtents?: readonly [number, number, number];
75
84
  }
76
85
  export interface GameContextContent {
77
86
  itemById?(itemId: string): GameContextItemEntry | null | undefined;
@@ -86,11 +95,14 @@ export interface GameContextOptions<TAssetRef extends ModelAssetRef = ModelAsset
86
95
  isNew: boolean;
87
96
  };
88
97
  now?: () => number;
98
+ occluder?: (from: EntityPosition, to: EntityPosition) => boolean;
89
99
  }
90
100
  export interface SceneObjectContext extends ObjectStore {
91
101
  catalog(instanceId: string): GameContextObjectEntry | null;
92
102
  raycast(input: ObjectRaycastInput): ObjectRaycastHit | null;
93
103
  raycastAll(input: ObjectRaycastInput): readonly ObjectRaycastHit[];
104
+ setColliders(instanceId: string, colliders: EntityColliderSet | null): void;
105
+ collidersOf(instanceId: string): EntityColliderSet | null;
94
106
  }
95
107
  export interface FloatTextInput {
96
108
  instanceId?: string;
@@ -129,11 +141,13 @@ export interface SceneEntityContext {
129
141
  despawn(instanceId: string): boolean;
130
142
  update: EntityStore["update"];
131
143
  setPose(instanceId: string, pose: EntityPose): boolean;
144
+ setPoseConstraint: EntityStore["setPoseConstraint"];
132
145
  get(instanceId: string): SceneEntity | null;
133
146
  list(): readonly SceneEntity[];
134
147
  spawnPoseOf(instanceId: string): SpawnPose | null;
135
148
  resetToSpawn(instanceId: string): boolean;
136
149
  resetAllToSpawn(filter?: (entity: SceneEntity) => boolean): number;
150
+ blackboard: EntityBlackboard;
137
151
  stats: EntityStatsApi;
138
152
  floatText(input: FloatTextInput): void;
139
153
  telegraph(input: TelegraphInput): () => void;
@@ -152,6 +166,9 @@ export interface SceneEntityContext {
152
166
  hasLineOfSight: SpatialApi["hasLineOfSight"];
153
167
  queryArc: SpatialApi["queryArc"];
154
168
  moveToward: SpatialApi["moveToward"];
169
+ invalidateSpatial: SpatialApi["invalidate"];
170
+ setColliders(instanceId: string, colliders: EntityColliderSet | null): void;
171
+ collidersOf(instanceId: string): EntityColliderSet | null;
155
172
  form: Forms;
156
173
  paint: PaintLayer;
157
174
  }
@@ -175,6 +192,10 @@ export interface GameContextCommands {
175
192
  has(name: string): boolean;
176
193
  names(): string[];
177
194
  run(name: string, input: unknown): CommandResult<GameContext>;
195
+ /** Run a command attributed to `actorUserId` — a shared-world host routes each client's command through this so the handler can read {@link actor}. */
196
+ runAs(actorUserId: string, name: string, input: unknown): CommandResult<GameContext>;
197
+ /** The user a command is running on behalf of, or `null` outside a {@link runAs} call — commands default to `ctx.player.userId` when this is `null`. */
198
+ actor(): string | null;
178
199
  }
179
200
  export interface GameContextFeed extends Omit<GameFeed, "bind"> {
180
201
  bind(action: keyof GameEventMap): () => void;
@@ -210,36 +231,69 @@ export interface GameContextTurn {
210
231
  /** Lazily creates (on first call, `config` required) or returns the existing notify-wrapped turn loop for `id`. */
211
232
  loop(id: string, config?: TurnLoopConfig): TurnLoop;
212
233
  }
234
+ export interface GameContextRace {
235
+ /** Lazily creates (on first call, `config` required) or returns the existing reactive race for `id` — discrete mutations and eventful `update` calls bump `ctx.version()`, so HUDs stop hand-managing `store.set` (#286.2). */
236
+ state(id: string, config?: RaceStateConfig): RaceState;
237
+ }
238
+ /** Reachable audio seam on `ctx.game`: `play`, `music`, and `resume` route through the `audio.play`/`audio.music`/`audio.resume` events the shell's audio engine listens on, so game code triggers sound without importing the shell. */
239
+ export interface GameAudio {
240
+ play(sound: string, at?: readonly [number, number, number]): void;
241
+ /** Crossfade the procedural soundtrack to `theme` (null fades out); `transpose` shifts the incoming theme's key in semitones. */
242
+ music(theme: string | null, transpose?: number): void;
243
+ resume(): void;
244
+ }
213
245
  export interface GameContext {
214
246
  scene: {
215
247
  object: SceneObjectContext;
216
248
  entity: SceneEntityContext;
217
249
  worldItem: SceneWorldItemContext;
250
+ raycast(input: SceneRaycastInput): SceneRaycastHit | null;
251
+ raycastAll(input: SceneRaycastInput): readonly SceneRaycastHit[];
218
252
  };
219
253
  world: GameContextWorld;
220
254
  game: {
221
255
  commands: GameContextCommands;
222
256
  events: GameEvents;
257
+ audio: GameAudio;
258
+ /** Play a model's one-shot animation clip bound to `event` in its `animation.oneShots` (e.g. an attack swing) — emits `entity.animation` for the shell to pick up. */
259
+ playEntityAnimation(instanceId: string, event: string): void;
223
260
  feed: GameContextFeed;
224
261
  loot: GameContextLoot;
225
262
  trade: TradeSystem;
226
263
  quest: QuestJournal;
227
- social: Social;
228
- chat: Chat;
264
+ /** Friends/party/presence/emotes/world-invites — present only when `features.social` is set. */
265
+ social?: Social;
266
+ /** Channels + messages — present only when `features.chat` is set (implies `social`). */
267
+ chat?: Chat;
229
268
  unlocks: Unlocks;
230
269
  economy: GameContextEconomy;
231
- leaderboard: Leaderboard;
232
- roster: Roster;
270
+ /** Competitive score tracking — present only when `features.leaderboard` is set. */
271
+ leaderboard?: Leaderboard;
272
+ /** Owned-entity roster — present only when `features.roster` is set. */
273
+ roster?: Roster;
233
274
  /** Game-defined keyed reactive store slot (#163.1); mutations bump `ctx.version()`/notify `ctx.subscribe`. */
234
275
  store: ObservableKeyedStore<unknown>;
235
- cards: GameContextCards;
236
- turn: GameContextTurn;
276
+ /** Card pile zones — present only when `features.cards` is set. */
277
+ cards?: GameContextCards;
278
+ /** Turn/phase loop — present only when `features.turn` is set. */
279
+ turn?: GameContextTurn;
280
+ /** Lap/checkpoint race state — present only when `features.race` is set. */
281
+ race?: GameContextRace;
282
+ /** Connected-player set for a shared world — present only when `features.players` is set. */
283
+ players?: ConnectedPlayers;
237
284
  };
238
285
  player: {
286
+ /** The acting player's id — the command actor inside `runAs`, the local player everywhere else. */
239
287
  userId: string;
240
288
  isNew: boolean;
289
+ /** The acting player's inventory set — the command actor's bags inside `runAs`, the local player's everywhere else. */
241
290
  inventory: InventorySet<string>;
291
+ /** A specific player's inventory set — how a host reads or grants into any connected player's bags. */
292
+ inventoryFor(userId: string): InventorySet<string>;
293
+ /** The acting player's stat modifiers — the command actor's inside `runAs`, the local player's everywhere else. */
242
294
  stats: Stats<string>;
295
+ /** A specific player's stat modifiers — how a host reads or buffs any connected player's stats. */
296
+ statsFor(userId: string): Stats<string>;
243
297
  loadout: Loadouts;
244
298
  applyLoadout(userId: string, loadoutId: string): {
245
299
  reason: string;
@@ -247,8 +301,10 @@ export interface GameContext {
247
301
  movement: PoseState;
248
302
  possession: Possession;
249
303
  cosmetics: Cosmetics;
250
- /** Vertical-motion seam into the shell-owned FrameDriver (#162.4); see `MotionIntents`. */
304
+ /** Motion seam into the movement integrator (#162.4); routes to the command actor's queue (or the local player outside a command), so a command's impulse lands on whoever ran it. See `MotionIntents`. */
251
305
  motion: MotionIntents;
306
+ /** A specific player's motion queue — how the host-side per-player movement integrator drains each connected player's impulses. */
307
+ motionFor(userId: string): MotionIntents;
252
308
  };
253
309
  item: {
254
310
  use: GameContextItemUse;
@@ -261,5 +317,13 @@ export interface GameContext {
261
317
  input: InputSnapshot;
262
318
  subscribe(listener: () => void): () => void;
263
319
  version(): number;
320
+ /**
321
+ * Gather every opted-in live subsystem into one {@link WorldSnapshot} — entities, entity stats, the
322
+ * keyed store, the action feed, plus leaderboard/chat when those features are on. The full-world
323
+ * baseline a host sends a joining client; {@link hydrate} is its inverse.
324
+ */
325
+ snapshot(): WorldSnapshot;
326
+ /** Apply a {@link WorldSnapshot} from an authoritative host, hydrating each subsystem key present in it. */
327
+ hydrate(snapshot: WorldSnapshot): void;
264
328
  }
265
329
  export declare function createGameContext<TAssetRef extends ModelAssetRef, TMultiplayer>(options: GameContextOptions<TAssetRef, TMultiplayer>): GameContext;