@jgengine/shell 0.10.0 → 0.12.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 (286) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/CombatPresentation.d.ts +5 -0
  5. package/dist/CombatPresentation.js +8 -0
  6. package/dist/GameHost.d.ts +25 -1
  7. package/dist/GameHost.js +60 -4
  8. package/dist/GamePhaseStamp.d.ts +1 -0
  9. package/dist/GamePhaseStamp.js +9 -0
  10. package/dist/GamePlayer.d.ts +5 -0
  11. package/dist/GamePlayer.js +5 -0
  12. package/dist/GamePlayerShell.d.ts +5 -12
  13. package/dist/GamePlayerShell.js +67 -1332
  14. package/dist/GameUiPreview.js +3 -2
  15. package/dist/Shell3dPresentation.d.ts +63 -0
  16. package/dist/Shell3dPresentation.js +302 -0
  17. package/dist/ShellChrome.d.ts +51 -0
  18. package/dist/ShellChrome.js +51 -0
  19. package/dist/ShellHudPresentation.d.ts +41 -0
  20. package/dist/ShellHudPresentation.js +22 -0
  21. package/dist/audio/audioEngine.d.ts +4 -0
  22. package/dist/audio/audioEngine.js +128 -21
  23. package/dist/audio/audioWire.d.ts +40 -0
  24. package/dist/audio/audioWire.js +62 -0
  25. package/dist/audio/loopParams.d.ts +20 -0
  26. package/dist/audio/loopParams.js +28 -0
  27. package/dist/behaviour.d.ts +2 -1
  28. package/dist/behaviour.js +2 -1
  29. package/dist/behaviourAttach.d.ts +1 -0
  30. package/dist/behaviourAttach.js +1 -0
  31. package/dist/behaviourDriver.d.ts +1 -0
  32. package/dist/behaviourDriver.js +1 -0
  33. package/dist/boundActionDispatch.d.ts +13 -0
  34. package/dist/boundActionDispatch.js +37 -0
  35. package/dist/camera/GameCameraRig.d.ts +5 -2
  36. package/dist/camera/GameCameraRig.js +8 -3
  37. package/dist/camera/GameFirstPersonCamera.d.ts +9 -2
  38. package/dist/camera/GameFirstPersonCamera.js +8 -3
  39. package/dist/camera/GameInspectionCamera.d.ts +1 -1
  40. package/dist/camera/GameInspectionCamera.js +2 -2
  41. package/dist/camera/GameOrbitCamera.js +24 -9
  42. package/dist/camera/cameraBlendMath.d.ts +3 -0
  43. package/dist/camera/cameraBlendMath.js +3 -0
  44. package/dist/camera/cameraRigs.d.ts +3 -1
  45. package/dist/camera/cameraRigs.js +21 -3
  46. package/dist/camera/fovPreference.d.ts +6 -1
  47. package/dist/camera/fovPreference.js +6 -1
  48. package/dist/camera/index.d.ts +4 -7
  49. package/dist/camera/index.js +4 -7
  50. package/dist/camera/inspectionCameraMath.d.ts +7 -2
  51. package/dist/camera/inspectionCameraMath.js +7 -2
  52. package/dist/camera/orbitCameraMath.d.ts +36 -6
  53. package/dist/camera/orbitCameraMath.js +56 -6
  54. package/dist/camera/rigMath.d.ts +114 -24
  55. package/dist/camera/rigMath.js +129 -24
  56. package/dist/camera/rigResolve.d.ts +4 -2
  57. package/dist/camera/rigResolve.js +4 -2
  58. package/dist/camera/shakeChannel.d.ts +6 -2
  59. package/dist/camera/shakeChannel.js +6 -2
  60. package/dist/camera/shakeChannelMath.d.ts +1 -0
  61. package/dist/camera/shakeChannelMath.js +1 -0
  62. package/dist/commandSink.d.ts +8 -3
  63. package/dist/commandSink.js +8 -3
  64. package/dist/defineGame.d.ts +15 -1
  65. package/dist/defineGame.js +50 -9
  66. package/dist/devtools/ColPanel.d.ts +1 -0
  67. package/dist/devtools/ColPanel.js +14 -0
  68. package/dist/devtools/DevtoolsOverlay.d.ts +11 -7
  69. package/dist/devtools/DevtoolsOverlay.js +47 -462
  70. package/dist/devtools/KeysPanel.d.ts +4 -0
  71. package/dist/devtools/KeysPanel.js +31 -0
  72. package/dist/devtools/LogsPanel.d.ts +1 -0
  73. package/dist/devtools/LogsPanel.js +12 -0
  74. package/dist/devtools/NetPanel.d.ts +4 -0
  75. package/dist/devtools/NetPanel.js +10 -0
  76. package/dist/devtools/PerfPanel.d.ts +4 -0
  77. package/dist/devtools/PerfPanel.js +53 -0
  78. package/dist/devtools/TunePanel.d.ts +3 -0
  79. package/dist/devtools/TunePanel.js +309 -0
  80. package/dist/devtools/agentBridge.d.ts +41 -0
  81. package/dist/devtools/agentBridge.js +266 -0
  82. package/dist/devtools/collisionDebug.d.ts +6 -0
  83. package/dist/devtools/collisionDebug.js +6 -0
  84. package/dist/devtools/collisionDebugMath.d.ts +8 -2
  85. package/dist/devtools/collisionDebugMath.js +24 -5
  86. package/dist/devtools/devtoolsOverrides.d.ts +6 -0
  87. package/dist/devtools/devtoolsOverrides.js +48 -0
  88. package/dist/devtools/panelAtoms.d.ts +9 -0
  89. package/dist/devtools/panelAtoms.js +10 -0
  90. package/dist/devtools/perfDiagnose.d.ts +2 -0
  91. package/dist/devtools/perfDiagnose.js +43 -0
  92. package/dist/diagnostics/RuntimeDiagnostics.d.ts +36 -0
  93. package/dist/diagnostics/RuntimeDiagnostics.js +80 -0
  94. package/dist/drivers/FrameDriver.d.ts +37 -0
  95. package/dist/drivers/FrameDriver.js +232 -0
  96. package/dist/drivers/HudOnlyDriver.d.ts +16 -0
  97. package/dist/drivers/HudOnlyDriver.js +60 -0
  98. package/dist/environment/Daylight.d.ts +23 -7
  99. package/dist/environment/Daylight.js +106 -13
  100. package/dist/environment/EnvironmentScene.js +44 -9
  101. package/dist/environment/VolumetricClouds.d.ts +17 -0
  102. package/dist/environment/VolumetricClouds.js +202 -0
  103. package/dist/environment/daylightCycle.d.ts +3 -1
  104. package/dist/environment/daylightCycle.js +3 -1
  105. package/dist/environment/groundPadMath.d.ts +3 -0
  106. package/dist/environment/groundPadMath.js +3 -0
  107. package/dist/environment/index.d.ts +1 -0
  108. package/dist/environment/index.js +1 -0
  109. package/dist/environment/skyLightingPolicy.d.ts +2 -0
  110. package/dist/environment/skyLightingPolicy.js +2 -0
  111. package/dist/environment/terrainGroundColor.d.ts +9 -0
  112. package/dist/environment/terrainGroundColor.js +22 -0
  113. package/dist/gameKit.d.ts +27 -0
  114. package/dist/gameKit.js +29 -0
  115. package/dist/hotbarActions.d.ts +26 -0
  116. package/dist/hotbarActions.js +27 -0
  117. package/dist/inputSink.d.ts +16 -4
  118. package/dist/inputSink.js +57 -7
  119. package/dist/map/MapMarkerBeacons.d.ts +3 -2
  120. package/dist/materialOverride.d.ts +10 -0
  121. package/dist/materialOverride.js +15 -3
  122. package/dist/multiplayer.js +8 -2
  123. package/dist/postfx/PostProcessing.d.ts +9 -1
  124. package/dist/postfx/PostProcessing.js +56 -11
  125. package/dist/postfx/gradeShader.js +9 -1
  126. package/dist/presentationResolve.d.ts +35 -0
  127. package/dist/presentationResolve.js +51 -0
  128. package/dist/registry.d.ts +4 -2
  129. package/dist/render/EnvironmentLighting.d.ts +10 -0
  130. package/dist/render/EnvironmentLighting.js +34 -0
  131. package/dist/render/SceneLighting.d.ts +7 -0
  132. package/dist/render/SceneLighting.js +18 -0
  133. package/dist/render/SceneModels.d.ts +14 -0
  134. package/dist/render/SceneModels.js +337 -0
  135. package/dist/render/assetBase.d.ts +17 -0
  136. package/dist/render/assetBase.js +35 -0
  137. package/dist/render/defaultSurface.d.ts +29 -0
  138. package/dist/render/defaultSurface.js +101 -0
  139. package/dist/render/modelLoad.d.ts +24 -0
  140. package/dist/render/modelLoad.js +76 -0
  141. package/dist/render/modelRender.d.ts +11 -0
  142. package/dist/render/modelRender.js +15 -0
  143. package/dist/render/resolveModel.d.ts +54 -3
  144. package/dist/render/resolveModel.js +116 -4
  145. package/dist/render/useEntityRenderCues.d.ts +13 -0
  146. package/dist/render/useEntityRenderCues.js +62 -0
  147. package/dist/scatter/InstancedScatter.d.ts +24 -0
  148. package/dist/scatter/InstancedScatter.js +135 -0
  149. package/dist/scatter/scatterModels.d.ts +25 -0
  150. package/dist/scatter/scatterModels.js +61 -0
  151. package/dist/scatter/scatterProxies.d.ts +6 -0
  152. package/dist/scatter/scatterProxies.js +118 -0
  153. package/dist/scatter.d.ts +1 -0
  154. package/dist/scatter.js +1 -0
  155. package/dist/scene/AuthoredScene.d.ts +84 -0
  156. package/dist/scene/AuthoredScene.js +178 -0
  157. package/dist/scene/CityRenderer.d.ts +2 -0
  158. package/dist/scene/CityRenderer.js +1031 -0
  159. package/dist/scene/GeneratedAssetRenderer.d.ts +14 -0
  160. package/dist/scene/GeneratedAssetRenderer.js +59 -0
  161. package/dist/scene/GrassFieldRenderer.d.ts +2 -0
  162. package/dist/scene/GrassFieldRenderer.js +73 -0
  163. package/dist/scene/PoleLineRenderer.d.ts +2 -0
  164. package/dist/scene/PoleLineRenderer.js +287 -0
  165. package/dist/scene/SoilPatchRenderer.d.ts +2 -0
  166. package/dist/scene/SoilPatchRenderer.js +84 -0
  167. package/dist/scene/StudioStage.d.ts +37 -0
  168. package/dist/scene/StudioStage.js +42 -0
  169. package/dist/scene/WaterRenderer.d.ts +2 -0
  170. package/dist/scene/WaterRenderer.js +61 -0
  171. package/dist/scene/builtinSceneKindRenderers.d.ts +2 -0
  172. package/dist/scene/builtinSceneKindRenderers.js +26 -0
  173. package/dist/scene/cityWindowMaterial.d.ts +16 -0
  174. package/dist/scene/cityWindowMaterial.js +81 -0
  175. package/dist/scene/sceneKindRenderers.d.ts +30 -0
  176. package/dist/scene/sceneKindRenderers.js +17 -0
  177. package/dist/scene.d.ts +1 -0
  178. package/dist/scene.js +1 -0
  179. package/dist/settings/appliedSettings.d.ts +7 -1
  180. package/dist/settings/appliedSettings.js +13 -2
  181. package/dist/settings/settingsController.d.ts +2 -0
  182. package/dist/settings/settingsController.js +22 -1
  183. package/dist/shellConstants.d.ts +4 -0
  184. package/dist/shellConstants.js +4 -0
  185. package/dist/shellMovement.d.ts +8 -0
  186. package/dist/shellMovement.js +11 -0
  187. package/dist/shellPointer.d.ts +20 -0
  188. package/dist/shellPointer.js +28 -0
  189. package/dist/structures/PlacementGhost.d.ts +4 -0
  190. package/dist/structures/PlacementGhost.js +4 -0
  191. package/dist/structures/TransformGizmo.d.ts +53 -0
  192. package/dist/structures/TransformGizmo.js +59 -0
  193. package/dist/structures/index.d.ts +1 -0
  194. package/dist/structures/index.js +1 -0
  195. package/dist/terrain/GrassField.d.ts +11 -3
  196. package/dist/terrain/GrassField.js +16 -6
  197. package/dist/terrain/TerraformBrushCursor.js +3 -0
  198. package/dist/terrain/grassBudget.d.ts +11 -2
  199. package/dist/terrain/grassBudget.js +20 -4
  200. package/dist/terrain/grassGeometry.d.ts +35 -0
  201. package/dist/terrain/grassGeometry.js +85 -20
  202. package/dist/terrain/grassMaterial.d.ts +20 -0
  203. package/dist/terrain/grassMaterial.js +68 -13
  204. package/dist/terrain/heightfieldGeometry.d.ts +34 -0
  205. package/dist/terrain/heightfieldGeometry.js +109 -0
  206. package/dist/terrain/index.d.ts +1 -0
  207. package/dist/terrain/index.js +1 -0
  208. package/dist/terrain/random.d.ts +3 -0
  209. package/dist/terrain/random.js +3 -0
  210. package/dist/terrain/soilPatchMaterial.d.ts +23 -0
  211. package/dist/terrain/soilPatchMaterial.js +147 -0
  212. package/dist/terrain/terrainDetailMaterial.d.ts +19 -2
  213. package/dist/terrain/terrainDetailMaterial.js +87 -7
  214. package/dist/terrain/terrainMath.d.ts +8 -1
  215. package/dist/terrain/terrainMath.js +8 -1
  216. package/dist/touch/TouchControlsOverlay.d.ts +9 -5
  217. package/dist/touch/TouchControlsOverlay.js +201 -22
  218. package/dist/useShellMultiplayerSync.d.ts +9 -0
  219. package/dist/useShellMultiplayerSync.js +98 -0
  220. package/dist/visibility/CullingProvider.js +1 -1
  221. package/dist/water/Ocean.d.ts +7 -1
  222. package/dist/water/Ocean.js +16 -3
  223. package/dist/water/OceanConfig.d.ts +11 -0
  224. package/dist/water/OceanConfig.js +8 -0
  225. package/dist/water/OceanMaterial.d.ts +12 -0
  226. package/dist/water/OceanMaterial.js +9 -0
  227. package/dist/water/OceanShader.d.ts +2 -2
  228. package/dist/water/OceanShader.js +78 -10
  229. package/dist/weather/fireSpreadPose.d.ts +1 -0
  230. package/dist/weather/fireSpreadPose.js +1 -0
  231. package/dist/weather/weatherGeometry.d.ts +1 -0
  232. package/dist/weather/weatherGeometry.js +1 -0
  233. package/dist/weather/weatherMath.d.ts +3 -0
  234. package/dist/weather/weatherMath.js +3 -0
  235. package/dist/weather/weatherUniforms.d.ts +3 -0
  236. package/dist/weather/weatherUniforms.js +3 -0
  237. package/dist/world/PlaceScene.d.ts +11 -0
  238. package/dist/world/PlaceScene.js +27 -0
  239. package/dist/world/RetainedVfx.d.ts +10 -0
  240. package/dist/world/RetainedVfx.js +136 -0
  241. package/dist/world/WorldHud.d.ts +49 -2
  242. package/dist/world/WorldHud.js +87 -2
  243. package/dist/world/WorldScene.d.ts +21 -0
  244. package/dist/world/WorldScene.js +186 -0
  245. package/dist/world/WorldVfx.d.ts +9 -0
  246. package/dist/world/WorldVfx.js +184 -0
  247. package/dist/world/entityPose.d.ts +2 -0
  248. package/dist/world/entityPose.js +2 -0
  249. package/dist/world/floatTextStyle.d.ts +1 -0
  250. package/dist/world/floatTextStyle.js +1 -0
  251. package/dist/world/telegraphPulse.d.ts +1 -0
  252. package/dist/world/telegraphPulse.js +1 -0
  253. package/dist/world/worldBarSamples.d.ts +25 -0
  254. package/dist/world/worldBarSamples.js +38 -0
  255. package/dist/worldSky.d.ts +11 -0
  256. package/dist/worldSky.js +21 -0
  257. package/dist/worldSync.d.ts +2 -1
  258. package/dist/worldSync.js +2 -1
  259. package/package.json +6 -6
  260. package/skills/game-design/SKILL.md +28 -0
  261. package/skills/game-design/agents/openai.yaml +4 -0
  262. package/skills/game-design/references/application-playbook.md +170 -0
  263. package/skills/game-design/references/field-guide.md +288 -0
  264. package/skills/jgengine/SKILL.md +54 -0
  265. package/skills/jgengine/api.md +527 -0
  266. package/skills/jgengine/capabilities.md +131 -0
  267. package/skills/jgengine/recipes/minimal-game.md +88 -0
  268. package/skills/jgengine-ui/SKILL.md +41 -0
  269. package/skills/jgengine-ui/api.md +2007 -0
  270. package/skills/jgengine-ui/capabilities.md +211 -0
  271. package/skills/jgengine-ui/recipes/portable-minimap.md +150 -0
  272. package/skills/jgengine-ui/reference.md +513 -0
  273. package/skills/jgengine-ui/references/visual-scorecard.md +73 -0
  274. package/skills/jgengine-world/SKILL.md +51 -0
  275. package/skills/jgengine-world/api.md +3056 -0
  276. package/skills/jgengine-world/capabilities.md +476 -0
  277. package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
  278. package/skills/jgengine-world/reference.md +261 -0
  279. package/skills/level-design/SKILL.md +54 -0
  280. package/skills/level-design/agents/openai.yaml +4 -0
  281. package/skills/level-design/references/application-playbook.md +192 -0
  282. package/skills/level-design/references/field-guide.md +337 -0
  283. package/skills/level-design/references/live-editor-loop.md +179 -0
  284. package/dist/cartridge.d.ts +0 -145
  285. package/dist/cartridge.js +0 -246
  286. package/llms.txt +0 -2761
@@ -0,0 +1,476 @@
1
+ <!-- GENERATED by scripts/gen-capability-index.ts — do not edit. Regenerate: bun run gen:capabilities -->
2
+
3
+ # jgengine-world — capability index
4
+
5
+ Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
6
+
7
+ ## area-effect-field — source-following area membership with enter/refresh/leave edges, stacking, and cleanup
8
+
9
+ - `createAreaEffectField` (function) · `import { createAreaEffectField } from "@jgengine/core/world"`
10
+
11
+ ## area-stack-additive — sum a magnitude across overlapping area memberships
12
+
13
+ - `sumMagnitude` (function) · `import { sumMagnitude } from "@jgengine/core/world"`
14
+
15
+ ## area-stack-capped — cap area memberships per stack key at a maximum count
16
+
17
+ - `cappedStacks` (function) · `import { cappedStacks } from "@jgengine/core/world"`
18
+
19
+ ## area-stack-extremum — keep only the strongest or weakest overlapping area membership
20
+
21
+ - `extremumStack` (function) · `import { extremumStack } from "@jgengine/core/world"`
22
+
23
+ ## area-stack-independent — apply every overlapping area membership independently
24
+
25
+ - `independentStacks` (function) · `import { independentStacks } from "@jgengine/core/world"`
26
+
27
+ ## area-stack-unique — keep one area membership per stack key, strongest wins
28
+
29
+ - `uniqueByStackKey` (function) · `import { uniqueByStackKey } from "@jgengine/core/world"`
30
+
31
+ ## asset-anchor — resolve a model's pivot offset from its footprint center
32
+
33
+ - `resolveAnchorOffset` (function) · `import { resolveAnchorOffset } from "@jgengine/core/world"`
34
+
35
+ ## asset-facing — resolve a placement heading into a Three.js Y-rotation using canonical forward
36
+
37
+ - `resolveFacingRotationY` (function) · `import { resolveFacingRotationY } from "@jgengine/core/world"`
38
+
39
+ ## asset-footprint — rotate a rectangular footprint into its axis-aligned extent
40
+
41
+ - `rotatedFootprint` (function) · `import { rotatedFootprint } from "@jgengine/core/world"`
42
+
43
+ ## asset-heading — turn a north-relative degree heading into a Three.js Y-rotation
44
+
45
+ - `headingToRotationY` (function) · `import { headingToRotationY } from "@jgengine/core/world"`
46
+ - `normalizeDegrees` (function) · `import { normalizeDegrees } from "@jgengine/core/world"`
47
+ - `rotationYToHeading` (function) · `import { rotationYToHeading } from "@jgengine/core/world"`
48
+
49
+ ## asset-load-diagnostics — classify a model fetch (missing / HTML fallback / corrupt / unsupported) before parsing
50
+
51
+ - `classifyAssetResponse` (function) · `import { classifyAssetResponse } from "@jgengine/core/scene/assetDiagnostics"`
52
+
53
+ ## asset-space — parse serialized asset-space metadata into a validated shape
54
+
55
+ - `parseAssetSpace` (function) · `import { parseAssetSpace } from "@jgengine/core/world"`
56
+ - `validateAssetSpace` (function) · `import { validateAssetSpace } from "@jgengine/core/world"`
57
+
58
+ ## asset-units — convert a source-space length to engine meters via catalog unit scale
59
+
60
+ - `toEngineUnits` (function) · `import { toEngineUnits } from "@jgengine/core/world"`
61
+
62
+ ## attack-move-order — advance-and-engage order that pursues hostiles en route and completes at its destination
63
+
64
+ - `defineAttackMoveOrder` (function) · `import { defineAttackMoveOrder } from "@jgengine/core/world"`
65
+
66
+ ## authored-entities — spawn authored mob/boss markers from the editor document at runtime
67
+
68
+ - `authoredEntitySpawns` (function) · `import { authoredEntitySpawns } from "@jgengine/core/world/authoredEntities"`
69
+
70
+ ## authored-objects — marker kinds resolved as entity spawns, not static props
71
+
72
+ - `ENTITY_MARKER_KINDS` (const) · `import { ENTITY_MARKER_KINDS } from "@jgengine/core/world/authoredObjects"`
73
+ - `markerCatalogId` (function) · `import { markerCatalogId } from "@jgengine/core/world"`
74
+ - `placeAuthoredObjects` (function) · `import { placeAuthoredObjects } from "@jgengine/core/world"`
75
+ - `resolveAuthoredObjects` (function) · `import { resolveAuthoredObjects } from "@jgengine/core/world"`
76
+
77
+ ## authored-spawn — read spawn points and markers from the editor document
78
+
79
+ - `authoredSpawnPosition` (function) · `import { authoredSpawnPosition } from "@jgengine/core/world/authoredSpawn"`
80
+ - `authoredSpawnRotation` (function) · `import { authoredSpawnRotation } from "@jgengine/core/world/authoredSpawn"`
81
+ - `markersOfKind` (function) · `import { markersOfKind } from "@jgengine/core/world/authoredSpawn"`
82
+
83
+ ## authored-triggers — built-in announce/win/advance actions authorable on any marker or volume
84
+
85
+ - `BUILTIN_TRIGGER_ACTIONS` (const) · `import { BUILTIN_TRIGGER_ACTIONS } from "@jgengine/core/scene/authoredTriggers"`
86
+ - `collectAuthoredTriggers` (function) · `import { collectAuthoredTriggers } from "@jgengine/core/world"`
87
+ - `createAuthoredTriggerRuntime` (function) · `import { createAuthoredTriggerRuntime } from "@jgengine/core/world"`
88
+ - `createTriggerOutcome` (function) · `import { createTriggerOutcome } from "@jgengine/core/scene/authoredTriggers"`
89
+ - `registerBuiltinTriggerActions` (function) · `import { registerBuiltinTriggerActions } from "@jgengine/core/scene/authoredTriggers"`
90
+ - `registerTriggerAction` (function) · `import { registerTriggerAction } from "@jgengine/core/world"`
91
+
92
+ ## behavior-control — pause/disable/resume/seek/inspect behavior instances per entity
93
+
94
+ - `behaviorControl` (function) · `import { behaviorControl } from "@jgengine/core/world"`
95
+
96
+ ## behavior-tick — auto-advance patrol/wander behaviors on spawned entities, no per-game route loop
97
+
98
+ - `advanceBehaviors` (function) · `import { advanceBehaviors } from "@jgengine/core/world"`
99
+
100
+ ## body-bind — mirror sim-body snapshots onto scene entities each tick, no per-body setPose
101
+
102
+ - `createBodyBind` (function) · `import { createBodyBind } from "@jgengine/core/world"`
103
+
104
+ ## build-footprint-cells — grid cells a snapped build piece footprint covers (footprintGrid occupancy bridge)
105
+
106
+ - `footprintCells` (function) · `import { footprintCells } from "@jgengine/core/world/buildSockets"`
107
+
108
+ ## build-socket-catalog — data-driven named-socket snap catalog for modular base building
109
+
110
+ - `createBuildSocketCatalog` (function) · `import { createBuildSocketCatalog } from "@jgengine/core/world/buildSockets"`
111
+
112
+ ## city-district — polygon math for road-derived blocks, parcels, and buildable footprints
113
+
114
+ - `Vec2` (type) · `import { Vec2 } from "@jgengine/core/world/cityGeometry"`
115
+ - `resolveCityObject` (function) · `import { resolveCityObject } from "@jgengine/core/world"`
116
+
117
+ ## companion-intent — resolve a companion's command + threat context into a per-tick follow/hold/engage/assist intent
118
+
119
+ - `resolveCompanionIntent` (function) · `import { resolveCompanionIntent } from "@jgengine/core/scene/companion"`
120
+
121
+ ## companion-roster — manage tamed companions — allegiance, commands, per-companion stats/leveling, and mobBrain-shaped intent
122
+
123
+ - `createCompanionRoster` (function) · `import { createCompanionRoster } from "@jgengine/core/scene/companion"`
124
+
125
+ ## contour-interval — readable auto-spacing for elevation contours
126
+
127
+ - `chooseContourInterval` (function) · `import { chooseContourInterval } from "@jgengine/core/world"`
128
+
129
+ ## crouch-prone — stance/pose transitions that change the hitbox
130
+
131
+ - `createPoseState` (function) · `import { createPoseState } from "@jgengine/core/world"`
132
+
133
+ ## decay-meter — survival meters that drain/refill over game time (hunger, water, oxygen, stamina)
134
+
135
+ - `createDecayMeterSet` (function) · `import { createDecayMeterSet } from "@jgengine/core/procedural"`
136
+
137
+ ## elevation-readout — cursor height and delta-from-reference feedback
138
+
139
+ - `sampleElevation` (function) · `import { sampleElevation } from "@jgengine/core/world"`
140
+
141
+ ## elevation-summary — selection min/max/mean and relief over a region
142
+
143
+ - `summarizeElevation` (function) · `import { summarizeElevation } from "@jgengine/core/world"`
144
+
145
+ ## entity-meta — cast-free narrow of SceneEntity.meta via a type guard
146
+
147
+ - `entityMetaOf` (function) · `import { entityMetaOf } from "@jgengine/core/world"`
148
+
149
+ ## flight-dynamics — simulate fixed-wing, helicopter, and VTOL aircraft
150
+
151
+ - `createAircraftDynamics` (function) · `import { createAircraftDynamics } from "@jgengine/core/world"`
152
+
153
+ ## follow-trail — trailing follower/snake formation that chases a leader
154
+
155
+ - `createLeaderTrail` (function) · `import { createLeaderTrail } from "@jgengine/core/world"`
156
+
157
+ ## footprint-grid — multi-cell footprint occupancy/reservation on a shared build grid
158
+
159
+ - `createFootprintGrid` (function) · `import { createFootprintGrid } from "@jgengine/core/world"`
160
+
161
+ ## formation-assignment — stable deterministic member-to-slot matching for a group formation
162
+
163
+ - `assignFormationSlots` (function) · `import { assignFormationSlots } from "@jgengine/core/world"`
164
+
165
+ ## formation-box — box/grid slot generator for group destinations
166
+
167
+ - `boxFormation` (function) · `import { boxFormation } from "@jgengine/core/world"`
168
+
169
+ ## formation-circle — ring/cordon slot generator for group destinations
170
+
171
+ - `circleFormation` (function) · `import { circleFormation } from "@jgengine/core/world"`
172
+
173
+ ## formation-facing — group facing yaw from a travel direction on the XZ plane
174
+
175
+ - `facingYaw` (function) · `import { facingYaw } from "@jgengine/core/world"`
176
+
177
+ ## formation-line — line (abreast) slot generator for group destinations
178
+
179
+ - `lineFormation` (function) · `import { lineFormation } from "@jgengine/core/world"`
180
+
181
+ ## formation-placement — place a group formation's world slots around a destination
182
+
183
+ - `placeFormation` (function) · `import { placeFormation } from "@jgengine/core/world"`
184
+
185
+ ## formation-wedge — wedge/arrowhead slot generator for group destinations
186
+
187
+ - `wedgeFormation` (function) · `import { wedgeFormation } from "@jgengine/core/world"`
188
+
189
+ ## forward-axis — declared front convention for parametric assets — auto-orient product shots
190
+
191
+ - `DEFAULT_FORWARD` (const) · `import { DEFAULT_FORWARD } from "@jgengine/core/world"`
192
+
193
+ ## glide — gliding/wingsuit descent control from a launch
194
+
195
+ - `createGlideModel` (function) · `import { createGlideModel } from "@jgengine/core/world"`
196
+
197
+ ## grapple-swing — grappling-hook rope swing physics with reel-in
198
+
199
+ - `createGrappleSwing` (function) · `import { createGrappleSwing } from "@jgengine/core/world"`
200
+
201
+ ## gravity-field — sample configurable uniform, radial, or combined gravity
202
+
203
+ - `combineGravity` (function) · `import { combineGravity } from "@jgengine/core/world"`
204
+ - `pointGravity` (function) · `import { pointGravity } from "@jgengine/core/world"`
205
+ - `uniformGravity` (function) · `import { uniformGravity } from "@jgengine/core/world"`
206
+
207
+ ## hold-order — stand-ground order that holds position until preempted or canceled
208
+
209
+ - `defineHoldOrder` (function) · `import { defineHoldOrder } from "@jgengine/core/world"`
210
+
211
+ ## interest-census — running active/dormant gate tally folded into the caller's tick loop
212
+
213
+ - `createInterestCensus` (function) · `import { createInterestCensus } from "@jgengine/core/world"`
214
+
215
+ ## interest-gate — per-agent sleep/wake + cadence gate state so far agents skip expensive ticks
216
+
217
+ - `createInterestGateState` (function) · `import { createInterestGateState } from "@jgengine/core/world"`
218
+
219
+ ## interest-scheduler — advance a sleep/wake gate with hysteresis, cadence tiers, and stagger
220
+
221
+ - `advanceInterestGate` (function) · `import { advanceInterestGate } from "@jgengine/core/world"`
222
+
223
+ ## interest-stagger — deterministic per-id cadence phase that spreads sibling gate ticks across frames
224
+
225
+ - `interestPhase` (function) · `import { interestPhase } from "@jgengine/core/world"`
226
+
227
+ ## limb-health — per-body-part/region health tracked separately
228
+
229
+ - `createMultiRegionHealth` (function) · `import { createMultiRegionHealth } from "@jgengine/core/procedural"`
230
+
231
+ ## local-avoidance — bounded deterministic local collision avoidance for moving agents
232
+
233
+ - `resolveLocalAvoidance` (function) · `import { resolveLocalAvoidance } from "@jgengine/core/world"`
234
+
235
+ ## lockpick — a solvable grid depth-puzzle with fog-of-war, gates, and hidden traps
236
+
237
+ - `generateLock` (function) · `import { generateLock } from "@jgengine/core/world"`
238
+
239
+ ## mesh-hitboxes — shots pass through holes in concave models — opted-in catalog assets raycast their actual triangles instead of the fitted box.
240
+
241
+ - `ColliderShape` (type) · `import { ColliderShape } from "@jgengine/core/scene/colliders"`
242
+
243
+ ## mesh-movement — the walking player slides against a mesh collider's compound `boxes` — a capsule walks THROUGH an opted-in archway opening and is stopped by its pillars/lintel instead of one outer box.
244
+
245
+ - `ColliderShape` (type) · `import { ColliderShape } from "@jgengine/core/scene/colliders"`
246
+
247
+ ## minimap-bake — rasterize authored terrain + zones into a top-down minimap image
248
+
249
+ - `bakeMinimapImage` (function) · `import { bakeMinimapImage } from "@jgengine/core/world"`
250
+ - `minimapBakeToPngDataUri` (function) · `import { minimapBakeToPngDataUri } from "@jgengine/core/world"`
251
+
252
+ ## minimap-track — project a world point to a 0..1 fraction along a linear track axis
253
+
254
+ - `trackFraction` (function) · `import { trackFraction } from "@jgengine/core/world/minimapTrack"`
255
+
256
+ ## model-sockets — named attachment points read from a model
257
+
258
+ - `ModelNode` (interface) · `import { ModelNode } from "@jgengine/core/world"`
259
+
260
+ ## move-order — go-to-point order that completes on arrival, composed over a motion adapter
261
+
262
+ - `defineMoveOrder` (function) · `import { defineMoveOrder } from "@jgengine/core/world"`
263
+
264
+ ## order-queue — serializable per-entity command queue with lifecycle, preemption, and pluggable order kinds
265
+
266
+ - `createOrderQueue` (function) · `import { createOrderQueue } from "@jgengine/core/world"`
267
+
268
+ ## order-registry — register order verbs (move/attack/custom) as data so engine code never branches on a verb
269
+
270
+ - `createOrderRegistry` (function) · `import { createOrderRegistry } from "@jgengine/core/world"`
271
+
272
+ ## path-follow-progress — read normalized/distance/segment progress from follow state
273
+
274
+ - `pathFollowProgress` (function) · `import { pathFollowProgress } from "@jgengine/core/world"`
275
+
276
+ ## path-follow-seek — jump a path-follower to normalized/distance/segment progress
277
+
278
+ - `pathFollowSeek` (function) · `import { pathFollowSeek } from "@jgengine/core/world"`
279
+
280
+ ## path-length — total polyline distance for progress math and seeding
281
+
282
+ - `pathLength` (function) · `import { pathLength } from "@jgengine/core/world"`
283
+
284
+ ## path-network — build a deterministic road/track graph (nodes, edges, streets, junctions, bridges, tunnels) from sliders
285
+
286
+ - `buildPathNetwork` (function) · `import { buildPathNetwork } from "@jgengine/core/world/pathNetwork"`
287
+
288
+ ## path-terrain — apply flatten/grade/carve/retaining path profiles to a terrain field
289
+
290
+ - `applyPathProfiles` (function) · `import { applyPathProfiles } from "@jgengine/core/world"`
291
+ - `withPathProfiles` (function) · `import { withPathProfiles } from "@jgengine/core/world"`
292
+
293
+ ## patrol-order — waypoint-route order that cycles a path, looping or completing at the end
294
+
295
+ - `definePatrolOrder` (function) · `import { definePatrolOrder } from "@jgengine/core/world"`
296
+
297
+ ## piece-sockets-from-model — derive build-piece snap sockets from a model's named attach points
298
+
299
+ - `pieceSocketsFromModel` (function) · `import { pieceSocketsFromModel } from "@jgengine/core/world/buildSockets"`
300
+
301
+ ## place-asset — resolve a placement commit into a shared asset placement payload
302
+
303
+ - `PlaceAssetResult` (interface) · `import { PlaceAssetResult } from "@jgengine/core/world"`
304
+ - `placeAssetFromCommit` (function) · `import { placeAssetFromCommit } from "@jgengine/core/world"`
305
+ - `resolvePlaceAsset` (function) · `import { resolvePlaceAsset } from "@jgengine/core/world"`
306
+
307
+ ## placement-controller — interactive build-mode ghost preview and commit
308
+
309
+ - `createPlacementController` (function) · `import { createPlacementController } from "@jgengine/core/world"`
310
+
311
+ ## placement-math — grid/surface footprint validity for build mode
312
+
313
+ - `validatePlacement` (function) · `import { validatePlacement } from "@jgengine/core/world"`
314
+
315
+ ## placement-rotation — apply a rotation policy to a candidate placement heading
316
+
317
+ - `applyRotationPolicy` (function) · `import { applyRotationPolicy } from "@jgengine/core/world"`
318
+ - `parseRotationPolicy` (function) · `import { parseRotationPolicy } from "@jgengine/core/world"`
319
+ - `snapHeading` (function) · `import { snapHeading } from "@jgengine/core/world"`
320
+
321
+ ## pole-line — editor-authorable poles + sagging cables along a path
322
+
323
+ - `POLE_LINE_KIND` (const) · `import { POLE_LINE_KIND } from "@jgengine/core/world/poleLineKind"`
324
+
325
+ ## population-director — ambient per-region creature population manager with timed weighted respawns and caps
326
+
327
+ - `createPopulationDirector` (function) · `import { createPopulationDirector } from "@jgengine/core/ai/populationDirector"`
328
+
329
+ ## portable-marker-source — project caller-owned arrays or subscribable stores into cached minimap marker snapshots without a MarkerSet
330
+
331
+ - `createMarkerSource` (function) · `import { createMarkerSource } from "@jgengine/core/world"`
332
+
333
+ ## proximity-prompt — a "press E" contextual prompt shown near an interactable
334
+
335
+ - `resolveActivePrompt` (function) · `import { resolveActivePrompt } from "@jgengine/core/world"`
336
+
337
+ ## pursuit — chase-to-reach cooldown-gated attack with optional leash-to-home; owns the attack cooldown
338
+
339
+ - `advancePursuit` (function) · `import { advancePursuit } from "@jgengine/core/ai/pursuit"`
340
+
341
+ ## qte — a quick-time-event timed input sequence with hit windows
342
+
343
+ - `evaluateQteSequence` (function) · `import { evaluateQteSequence } from "@jgengine/core/world"`
344
+
345
+ ## reputation — faction standing that crosses named reputation tiers
346
+
347
+ - `tierForStanding` (function) · `import { tierForStanding } from "@jgengine/core/world"`
348
+
349
+ ## resource-node — depletable, respawning harvest nodes with tool-dependent yields
350
+
351
+ - `createResourceNodeField` (function) · `import { createResourceNodeField } from "@jgengine/core/world/resourceNode"`
352
+
353
+ ## rts-control-groups — map Ctrl+digit / digit / double-tap presses onto selection-bookmark bind / recall / focus intents
354
+
355
+ - `controlGroupKey` (function) · `import { controlGroupKey } from "@jgengine/core/world"`
356
+ - `resolveControlGroupIntent` (function) · `import { resolveControlGroupIntent } from "@jgengine/core/world"`
357
+
358
+ ## selection-bookmark-recall — fold a saved set into the active selection with stale-ref pruning and a caller focus hook
359
+
360
+ - `recallSelectionBookmark` (function) · `import { recallSelectionBookmark } from "@jgengine/core/world"`
361
+
362
+ ## selection-bookmarks — keyed saved-set store (RTS control groups, camera bookmarks, saved squads) with prune + serialize
363
+
364
+ - `createSelectionBookmarks` (function) · `import { createSelectionBookmarks } from "@jgengine/core/world"`
365
+
366
+ ## skill-check — a timing-bar skill check where you release inside a zone
367
+
368
+ - `skillCheckZoneAt` (function) · `import { skillCheckZoneAt } from "@jgengine/core/world"`
369
+
370
+ ## soil-patch — editor-authorable terrain crack/moss material variation
371
+
372
+ - `SOIL_KIND` (const) · `import { SOIL_KIND } from "@jgengine/core/world"`
373
+
374
+ ## spatial-region-box — sample uniformly within an axis-aligned 3D box
375
+
376
+ - `boxRegion` (function) · `import { boxRegion } from "@jgengine/core/world"`
377
+
378
+ ## spatial-region-custom — wrap a caller-defined sampler and bounds test as a region
379
+
380
+ - `customRegion` (function) · `import { customRegion } from "@jgengine/core/world"`
381
+
382
+ ## spatial-region-point-set — sample from a fixed, optionally weighted candidate point table
383
+
384
+ - `pointSetRegion` (function) · `import { pointSetRegion } from "@jgengine/core/world"`
385
+
386
+ ## spatial-region-polygon — sample within an arbitrary closed polygon on the XZ plane
387
+
388
+ - `polygonRegion` (function) · `import { polygonRegion } from "@jgengine/core/world"`
389
+
390
+ ## spatial-region-shell — sample within a 3D spherical shell, volume- or radius-uniform
391
+
392
+ - `shellRegion` (function) · `import { shellRegion } from "@jgengine/core/world"`
393
+
394
+ ## spatial-region-sphere — sample within a filled 3D ball, volume- or radius-uniform
395
+
396
+ - `sphereRegion` (function) · `import { sphereRegion } from "@jgengine/core/world"`
397
+
398
+ ## spatial-region-weighted — compose sub-regions behind a weighted selection policy
399
+
400
+ - `weightedRegion` (function) · `import { weightedRegion } from "@jgengine/core/world"`
401
+
402
+ ## spatial-sample — draw one deterministic position from a region under include/exclude/distance constraints
403
+
404
+ - `samplePoint` (function) · `import { samplePoint } from "@jgengine/core/world"`
405
+
406
+ ## spatial-sample-batch — place many deterministic spaced points from a region with minimum separation
407
+
408
+ - `sampleBatch` (function) · `import { sampleBatch } from "@jgengine/core/world"`
409
+
410
+ ## spatial-sample-stratified — evenly cover an area with one jittered point per grid cell, deterministic
411
+
412
+ - `sampleStratified` (function) · `import { sampleStratified } from "@jgengine/core/world"`
413
+
414
+ ## stop-order — halt-and-complete order that brings a unit to an immediate standstill
415
+
416
+ - `defineStopOrder` (function) · `import { defineStopOrder } from "@jgengine/core/world"`
417
+
418
+ ## surface-drape — lift an XZ polyline onto sculpted terrain
419
+
420
+ - `drapePolyline` (function) · `import { drapePolyline } from "@jgengine/core/world"`
421
+
422
+ ## surface-grid — terrain-following reference grid that is not occluded by relief
423
+
424
+ - `surfaceGridLines` (function) · `import { surfaceGridLines } from "@jgengine/core/world"`
425
+
426
+ ## surface-ring — surface-following placement guide ring
427
+
428
+ - `surfaceRing` (function) · `import { surfaceRing } from "@jgengine/core/world"`
429
+
430
+ ## target-acquirer — stateful held-target wrapper over an acquisition policy with retention
431
+
432
+ - `createTargetAcquirer` (function) · `import { createTargetAcquirer } from "@jgengine/core/world"`
433
+
434
+ ## target-acquisition — composable candidate/eligibility/range/perception/score/tie-break/retention target pick
435
+
436
+ - `acquireTarget` (function) · `import { acquireTarget } from "@jgengine/core/world"`
437
+
438
+ ## targeted-order — pursue-a-target order with leash/standoff that ends when the target is gone
439
+
440
+ - `defineTargetedOrder` (function) · `import { defineTargetedOrder } from "@jgengine/core/world"`
441
+
442
+ ## terrain-contours — iso-elevation contour lines that drape on sculpted terrain
443
+
444
+ - `extractContours` (function) · `import { extractContours } from "@jgengine/core/world"`
445
+
446
+ ## terrain-guides — one-call adaptive contours for a terrain field
447
+
448
+ - `terrainContourGuides` (function) · `import { terrainContourGuides } from "@jgengine/core/world"`
449
+
450
+ ## terrain-raycast — pick a point on a heightfield along a camera/pointer ray
451
+
452
+ - `raycastHeightField` (function) · `import { raycastHeightField } from "@jgengine/core/world/terrain"`
453
+
454
+ ## touch-controls — default on-screen button silhouette for a touch action
455
+
456
+ - `touchButtonShape` (function) · `import { touchButtonShape } from "@jgengine/core/input/touchScheme"`
457
+
458
+ ## visibility-field — per-viewer-group observed/remembered/hidden fog-of-war knowledge with terrain memory and authoritative entity disclosure
459
+
460
+ - `createVisibilityField` (function) · `import { createVisibilityField } from "@jgengine/core/world"`
461
+
462
+ ## volumetric-clouds — raymarched cloud layer sky option
463
+
464
+ - `VolumetricCloudsConfig` (interface) · `import { VolumetricCloudsConfig } from "@jgengine/core/world"`
465
+
466
+ ## world-environment — compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
467
+
468
+ - `environment` (function) · `import { environment } from "@jgengine/core/world"`
469
+
470
+ ## world-place — declare the place a game happens in — flat/round/voxel/board ground, surface laws, per-place physics
471
+
472
+ - `world` (function) · `import { world } from "@jgengine/core/world"`
473
+
474
+ ## world-seed — derive a deterministic generator/scatter seed from world id + save/run seed
475
+
476
+ - `seedForPlace` (function) · `import { seedForPlace } from "@jgengine/core/world"`
@@ -0,0 +1,128 @@
1
+ # Recipe — commanding entities (select → order → tick → resolve)
2
+
3
+ **What this wires:** direct command over a group of entities — pick some, issue
4
+ intent, watch them carry it out and interact on arrival. This is a *composition*,
5
+ not a genre. The exact same wiring is the command layer of a base-defense wave, a
6
+ squad-tactics turn, a creature-herding puzzle, or the topdown-survival phase of a
7
+ game that was a card game a minute ago. You swap content, camera, and
8
+ win-condition — never this architecture.
9
+
10
+ It composes four primitives across three seams. The engine never touches your
11
+ entity store directly; you supply narrow adapters, so the same command loop runs
12
+ over any movement/combat model.
13
+
14
+ ## The seams
15
+
16
+ - **Pick → ids.** `createSelectionSet` is an ordered, de-duplicated set of entity
17
+ ids. What *fills* it is up to you — a pointer marquee, a card that names a lane,
18
+ an ability that grabs everything in a radius, an AI planner. Selection is just
19
+ ids; it does not know or care how they were chosen.
20
+ - **Intent → per-entity queue.** Build one shared `createOrderRegistry` and give
21
+ each commandable entity its own `createOrderQueue`. Register verbs as *data*
22
+ (`defineMoveOrder`, `defineAttackMoveOrder`, `defineTargetedOrder`, or your
23
+ own). Every verb composes over two adapters **you** implement against your
24
+ entity store: `OrderMover` (`position` / `moveToward` / `halt`) and
25
+ `OrderTargeting` (`acquire` / `positionOf`). This adapter boundary is what makes
26
+ the loop genre-free.
27
+ - **Resolve → your effect.** In `onTick`, advance each queue. Engagement verbs
28
+ write `{ engaging, inRange }` into `order.state`; you read that flag and resolve
29
+ the actual interaction your way — damage, harvest, repair, heal, dialogue —
30
+ through the combat seam `ctx.scene.entity.effect(...)`. Orders decide *when*;
31
+ the game decides *what*.
32
+
33
+ ## Connected wiring
34
+
35
+ ```ts
36
+ import { createSelectionSet } from "@jgengine/core/scene/selection";
37
+ import {
38
+ createOrderRegistry,
39
+ createOrderQueue,
40
+ defineMoveOrder,
41
+ defineAttackMoveOrder,
42
+ defineTargetedOrder,
43
+ } from "@jgengine/core/world";
44
+
45
+ // --- once, at setup -------------------------------------------------------
46
+
47
+ // Adapters bind orders to YOUR entity store — the only game-specific glue.
48
+ const mover = {
49
+ position: (id) => entities.get(id).pos,
50
+ moveToward: (id, to, dt) => stepToward(entities.get(id), to, dt), // your movement
51
+ halt: (id) => (entities.get(id).vel = [0, 0, 0]),
52
+ };
53
+ const targeting = {
54
+ positionOf: (id) => entities.get(id)?.pos,
55
+ acquire: (id) => nearestEnemyOf(id), // your target pick (kd-tree, grid, faction…)
56
+ };
57
+
58
+ const registry = createOrderRegistry();
59
+ registry.register(defineMoveOrder({ kind: "move", mover }));
60
+ registry.register(defineAttackMoveOrder({ kind: "attack-move", mover, targeting }));
61
+ registry.register(defineTargetedOrder({ kind: "attack", mover, targeting }));
62
+
63
+ const queues = new Map(); // entityId -> OrderQueue
64
+ const queueOf = (id) => {
65
+ let q = queues.get(id);
66
+ if (!q) queues.set(id, (q = createOrderQueue(registry)));
67
+ return q;
68
+ };
69
+
70
+ const selection = createSelectionSet();
71
+
72
+ // --- on a command (pointer marquee, a card play, an ability, an AI plan) --
73
+
74
+ function commandSelection(kind, payload) {
75
+ for (const id of selection) {
76
+ queueOf(id).issue({ kind, payload, policy: "replace" }); // shift-queue => "append"
77
+ }
78
+ }
79
+ // e.g. commandSelection("attack-move", { point: worldHit });
80
+
81
+ // --- every frame ----------------------------------------------------------
82
+
83
+ function onTick(ctx, dt) {
84
+ for (const [id, q] of queues) {
85
+ q.tick(ctx, dt); // activates/advances/completes orders, drives the mover
86
+ const active = q.active;
87
+ if (active?.state?.inRange) {
88
+ // Engagement verb says a target is in range — resolve it the game's way.
89
+ ctx.scene.entity.effect({ from: id, to: active.state.target, effect: "damage" });
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ That is the whole command loop. Everything genre-specific lives in the three
96
+ functions you supplied (`stepToward`, `nearestEnemyOf`, and the `"damage"` effect)
97
+ — never in the order/selection primitives.
98
+
99
+ ## Composing it into different games (and hybrids)
100
+
101
+ The wiring above is fixed; four independent knobs turn it into different play:
102
+
103
+ - **Who fills the selection.** Pointer marquee for an RTS; a targeting card for a
104
+ card-driven skirmish; an AoE ability for a spell; an AI director for autobattle.
105
+ Same `selection`, different caller.
106
+ - **Which camera renders it.** `topDown`, `rts`, `shoulder`, or `first` — camera is
107
+ presentation and reads none of this. Swapping the rig never touches the loop.
108
+ - **What the effect does.** `"damage"` for combat; register a `defineTargetedOrder`
109
+ with a `"harvest"` / `"repair"` / `"talk"` effect for non-combat command. The
110
+ engagement seam is generic; combat is one instance.
111
+ - **When intent arrives.** A **mutating** game reuses one set of queues across
112
+ phases: the card-game phase calls `issue()` from card plays; when it turns into
113
+ a topdown-survival phase, the *same* queues now take `move` / `attack-move` from
114
+ pointer input. You changed who calls `issue()`, not the architecture.
115
+
116
+ ## Where to go next
117
+
118
+ - Marquee/box-select and right-click-to-command come from the shell pointer seam
119
+ (`PlayableGame.pointer`: `select`, `selectFilter`, `orderCommand`) — that is the
120
+ pointer *picker* that fills `selection` and calls `commandSelection`; see
121
+ `jgengine-ui` for the pointer wiring.
122
+ - Pathing for `moveToward` can use `findPath` (`@jgengine/core/nav/navGrid`) over a
123
+ walkable grid; the mover adapter is where it plugs in.
124
+ - Formations, order preemption policies, save/replication of in-flight orders, and
125
+ the full order-kind contract are in [../reference.md](../reference.md) under
126
+ *Entity orders (command queue)*.
127
+ - Damage numbers, death, and rewards are `jgengine-combat`; the effect call above
128
+ is the seam into it.