@jgengine/core 0.7.0 → 0.8.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 (159) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +2 -0
  3. package/dist/ai/spawnDirector.d.ts +5 -0
  4. package/dist/ai/spawnDirector.js +13 -1
  5. package/dist/anim/easing.d.ts +14 -0
  6. package/dist/anim/easing.js +55 -0
  7. package/dist/behaviour/behaviour.d.ts +136 -0
  8. package/dist/behaviour/behaviour.js +388 -0
  9. package/dist/cards/cardPile.d.ts +1 -0
  10. package/dist/cards/cardPile.js +12 -3
  11. package/dist/combat/abilityKit.d.ts +5 -0
  12. package/dist/combat/abilityKit.js +10 -0
  13. package/dist/combat/effects.d.ts +1 -1
  14. package/dist/combat/effects.js +9 -6
  15. package/dist/combat/projectiles.d.ts +42 -5
  16. package/dist/combat/projectiles.js +98 -12
  17. package/dist/combat/telegraph.d.ts +5 -1
  18. package/dist/combat/telegraph.js +14 -0
  19. package/dist/commands/commandRegistry.d.ts +1 -1
  20. package/dist/commands/commandRegistry.js +2 -1
  21. package/dist/data/dataSource.d.ts +26 -0
  22. package/dist/data/dataSource.js +93 -0
  23. package/dist/data/devProxy.d.ts +11 -0
  24. package/dist/data/devProxy.js +38 -0
  25. package/dist/data/fetchJson.d.ts +20 -0
  26. package/dist/data/fetchJson.js +43 -0
  27. package/dist/data/jsonDataSource.d.ts +4 -0
  28. package/dist/data/jsonDataSource.js +6 -0
  29. package/dist/devtools/devtools.d.ts +157 -0
  30. package/dist/devtools/devtools.js +484 -0
  31. package/dist/devtools/transformTunables.d.ts +14 -0
  32. package/dist/devtools/transformTunables.js +38 -0
  33. package/dist/game/chat.d.ts +66 -0
  34. package/dist/game/chat.js +165 -0
  35. package/dist/game/defineGame.d.ts +8 -2
  36. package/dist/game/defineGame.js +2 -1
  37. package/dist/game/events.d.ts +25 -0
  38. package/dist/game/levelSequence.d.ts +44 -0
  39. package/dist/game/levelSequence.js +78 -0
  40. package/dist/game/playableGame.d.ts +237 -6
  41. package/dist/game/playableGame.js +6 -1
  42. package/dist/game/progression.d.ts +1 -0
  43. package/dist/game/progression.js +23 -2
  44. package/dist/game/race.d.ts +5 -0
  45. package/dist/game/race.js +20 -0
  46. package/dist/game/social.d.ts +42 -0
  47. package/dist/game/social.js +122 -0
  48. package/dist/game/spawnPoints.d.ts +19 -0
  49. package/dist/game/spawnPoints.js +23 -0
  50. package/dist/game/worldItem.d.ts +3 -0
  51. package/dist/game/worldItem.js +12 -6
  52. package/dist/input/actionBindings.d.ts +10 -0
  53. package/dist/input/actionBindings.js +14 -0
  54. package/dist/input/gestureSurface.d.ts +31 -0
  55. package/dist/input/gestureSurface.js +120 -0
  56. package/dist/input/pointer.d.ts +45 -0
  57. package/dist/input/pointer.js +48 -0
  58. package/dist/input/touchScheme.d.ts +83 -0
  59. package/dist/input/touchScheme.js +115 -0
  60. package/dist/item/affix.d.ts +1 -1
  61. package/dist/item/affix.js +1 -19
  62. package/dist/meta/changelog.d.ts +1 -1
  63. package/dist/meta/changelog.js +37 -1
  64. package/dist/movement/movementModel.d.ts +36 -3
  65. package/dist/movement/movementModel.js +81 -5
  66. package/dist/movement/voxelController.d.ts +61 -0
  67. package/dist/movement/voxelController.js +229 -0
  68. package/dist/multiplayer/chatContract.d.ts +42 -0
  69. package/dist/multiplayer/chatContract.js +57 -0
  70. package/dist/multiplayer/identity.d.ts +13 -0
  71. package/dist/multiplayer/identity.js +20 -0
  72. package/dist/multiplayer/poseSyncGate.d.ts +1 -0
  73. package/dist/multiplayer/poseSyncGate.js +13 -1
  74. package/dist/multiplayer/presenceModel.d.ts +3 -0
  75. package/dist/multiplayer/presenceModel.js +15 -1
  76. package/dist/multiplayer/voiceContract.d.ts +44 -0
  77. package/dist/multiplayer/voiceContract.js +108 -0
  78. package/dist/nav/navConstrain.d.ts +14 -0
  79. package/dist/nav/navConstrain.js +26 -0
  80. package/dist/nav/navFromEnvironment.d.ts +11 -0
  81. package/dist/nav/navFromEnvironment.js +16 -0
  82. package/dist/nav/navGrid.d.ts +10 -0
  83. package/dist/nav/navGrid.js +18 -1
  84. package/dist/nav/pathFollow.d.ts +4 -2
  85. package/dist/nav/pathFollow.js +5 -3
  86. package/dist/physics/ballisticSweep.d.ts +18 -0
  87. package/dist/physics/ballisticSweep.js +49 -0
  88. package/dist/physics/forceVolume.js +5 -5
  89. package/dist/physics/physicsWorld.d.ts +41 -2
  90. package/dist/physics/physicsWorld.js +232 -40
  91. package/dist/physics/spatialGrid.d.ts +1 -1
  92. package/dist/physics/spatialGrid.js +5 -0
  93. package/dist/physics/vehicleBody.d.ts +6 -0
  94. package/dist/physics/vehicleBody.js +16 -17
  95. package/dist/puzzle/cellGrid.d.ts +26 -0
  96. package/dist/puzzle/cellGrid.js +110 -0
  97. package/dist/puzzle/fallingPiece.d.ts +24 -0
  98. package/dist/puzzle/fallingPiece.js +51 -0
  99. package/dist/random/nameGen.d.ts +18 -0
  100. package/dist/random/nameGen.js +35 -0
  101. package/dist/random/rng.d.ts +2 -0
  102. package/dist/random/rng.js +23 -0
  103. package/dist/runtime/adapter.d.ts +35 -0
  104. package/dist/runtime/adapter.js +37 -1
  105. package/dist/runtime/cameraDirector.d.ts +10 -0
  106. package/dist/runtime/cameraDirector.js +25 -0
  107. package/dist/runtime/gameContext.d.ts +44 -2
  108. package/dist/runtime/gameContext.js +100 -4
  109. package/dist/runtime/hostPersistence.d.ts +21 -0
  110. package/dist/runtime/hostPersistence.js +50 -0
  111. package/dist/runtime/inputSnapshot.d.ts +7 -0
  112. package/dist/runtime/inputSnapshot.js +12 -0
  113. package/dist/runtime/motionIntents.d.ts +25 -0
  114. package/dist/runtime/motionIntents.js +25 -0
  115. package/dist/runtime/transport.d.ts +32 -0
  116. package/dist/scene/entityStore.d.ts +8 -0
  117. package/dist/scene/entityStore.js +25 -2
  118. package/dist/scene/movementSpeed.d.ts +35 -0
  119. package/dist/scene/movementSpeed.js +20 -0
  120. package/dist/scene/objectQuery.d.ts +18 -0
  121. package/dist/scene/objectQuery.js +108 -0
  122. package/dist/scene/objectStore.d.ts +11 -0
  123. package/dist/scene/objectStore.js +109 -4
  124. package/dist/scene/paintLayer.d.ts +15 -0
  125. package/dist/scene/paintLayer.js +53 -0
  126. package/dist/scene/spatial.d.ts +21 -0
  127. package/dist/scene/spatial.js +63 -1
  128. package/dist/sensor/concealment.d.ts +21 -0
  129. package/dist/sensor/concealment.js +63 -0
  130. package/dist/sensor/freezeMonitor.d.ts +17 -0
  131. package/dist/sensor/freezeMonitor.js +35 -0
  132. package/dist/session/roles.d.ts +6 -0
  133. package/dist/session/roles.js +32 -0
  134. package/dist/session/roundState.d.ts +41 -17
  135. package/dist/session/roundState.js +67 -38
  136. package/dist/tactics/fallingGrid.d.ts +62 -0
  137. package/dist/tactics/fallingGrid.js +158 -0
  138. package/dist/tactics/tacticalGrid.d.ts +11 -0
  139. package/dist/tactics/tacticalGrid.js +17 -0
  140. package/dist/time/simClock.d.ts +25 -1
  141. package/dist/time/simClock.js +28 -3
  142. package/dist/turn/intent.d.ts +14 -0
  143. package/dist/turn/intent.js +29 -0
  144. package/dist/turn/turnLoop.d.ts +2 -0
  145. package/dist/turn/turnLoop.js +8 -1
  146. package/dist/world/environmentSummary.d.ts +53 -0
  147. package/dist/world/environmentSummary.js +129 -0
  148. package/dist/world/features.d.ts +87 -6
  149. package/dist/world/features.js +52 -2
  150. package/dist/world/gridInstances.d.ts +13 -0
  151. package/dist/world/gridInstances.js +22 -0
  152. package/dist/world/placementController.d.ts +22 -1
  153. package/dist/world/placementController.js +56 -0
  154. package/dist/world/terrain.d.ts +23 -1
  155. package/dist/world/terrain.js +64 -1
  156. package/dist/world/voxelField.d.ts +54 -0
  157. package/dist/world/voxelField.js +241 -0
  158. package/llms.txt +4102 -0
  159. package/package.json +3 -2
@@ -15,6 +15,8 @@ export interface FindPathOptions {
15
15
  smooth?: boolean;
16
16
  /** Diameter of the mover in world units — blocks cells within this margin of an obstacle. Default 0. */
17
17
  clearance?: number;
18
+ /** Multiplier (>=1) applied to the base cost of stepping from one cell center to a neighbour's. Use to penalize slopes, terrain, etc. */
19
+ stepCost?: (from: NavPoint, to: NavPoint) => number;
18
20
  }
19
21
  export interface NavGrid {
20
22
  readonly cols: number;
@@ -42,5 +44,13 @@ export declare function createNavGrid(config: NavGridConfig): NavGrid;
42
44
  * the nearest walkable cell so a click on an obstacle still routes to its edge.
43
45
  */
44
46
  export declare function findPath(grid: NavGrid, from: NavPoint, to: NavPoint, options?: FindPathOptions): NavPoint[] | null;
47
+ /**
48
+ * `FindPathOptions.stepCost` factory that penalizes steep terrain: cost is
49
+ * `1 + weight * |Δheight| / horizontalDistance`, so with the default weight a
50
+ * 45° slope roughly doubles the step cost.
51
+ */
52
+ export declare function slopeStepCost(field: {
53
+ sampleHeight(x: number, z: number): number;
54
+ }, weight?: number): (from: NavPoint, to: NavPoint) => number;
45
55
  /** Remove waypoints the mover can skip because it has clear line-of-sight past them. */
46
56
  export declare function smoothPath(grid: NavGrid, points: readonly NavPoint[]): NavPoint[];
@@ -149,6 +149,7 @@ function withClearance(grid, clearance) {
149
149
  */
150
150
  export function findPath(grid, from, to, options = {}) {
151
151
  const passable = withClearance(grid, options.clearance ?? 0);
152
+ const stepCost = options.stepCost;
152
153
  const startCell = grid.cellAt(from);
153
154
  const goalCell = grid.cellAt(to);
154
155
  const start = passable(startCell.col, startCell.row) ? startCell : grid.nearestWalkable(from);
@@ -209,7 +210,8 @@ export function findPath(grid, from, to, options = {}) {
209
210
  const nKey = keyOf(nc, nr);
210
211
  if (closed.has(nKey))
211
212
  continue;
212
- const tentative = g + step;
213
+ const multiplier = stepCost === undefined ? 1 : Math.max(1, stepCost(grid.center(col, row), grid.center(nc, nr)));
214
+ const tentative = g + step * multiplier;
213
215
  if (tentative < (gScore.get(nKey) ?? Number.POSITIVE_INFINITY)) {
214
216
  gScore.set(nKey, tentative);
215
217
  cameFrom.set(nKey, current.key);
@@ -231,6 +233,21 @@ export function findPath(grid, from, to, options = {}) {
231
233
  raw[raw.length - 1] = [to[0], to[1]];
232
234
  return options.smooth === false ? raw : smoothPath(grid, raw);
233
235
  }
236
+ const DEFAULT_SLOPE_STEP_WEIGHT = 1;
237
+ /**
238
+ * `FindPathOptions.stepCost` factory that penalizes steep terrain: cost is
239
+ * `1 + weight * |Δheight| / horizontalDistance`, so with the default weight a
240
+ * 45° slope roughly doubles the step cost.
241
+ */
242
+ export function slopeStepCost(field, weight = DEFAULT_SLOPE_STEP_WEIGHT) {
243
+ return (from, to) => {
244
+ const horizontal = Math.hypot(to[0] - from[0], to[1] - from[1]);
245
+ if (horizontal < 1e-6)
246
+ return 1;
247
+ const rise = field.sampleHeight(to[0], to[1]) - field.sampleHeight(from[0], from[1]);
248
+ return 1 + (weight * Math.abs(rise)) / horizontal;
249
+ };
250
+ }
234
251
  /** Remove waypoints the mover can skip because it has clear line-of-sight past them. */
235
252
  export function smoothPath(grid, points) {
236
253
  if (points.length <= 2)
@@ -17,8 +17,10 @@ export interface PathFollowState {
17
17
  /** Total world-distance covered so far — drives progress/leak logic in tower defense. */
18
18
  distanceTravelled: number;
19
19
  }
20
- /** Lift an A* / navmesh `[x, z]` polyline onto a `y` plane for a path-follower. */
21
- export declare function pathFromNav(points: readonly NavPoint[], y?: number): Waypoint[];
20
+ export interface HeightSampler {
21
+ sampleHeight(x: number, z: number): number;
22
+ }
23
+ export declare function pathFromNav(points: readonly NavPoint[], elevation?: number | HeightSampler, offset?: number): Waypoint[];
22
24
  export declare function createPathFollow(config: PathFollowConfig): PathFollowState;
23
25
  /**
24
26
  * Advance a path-follower by `speed * dt` along its authored polyline. Pure — returns
@@ -1,6 +1,8 @@
1
- /** Lift an A* / navmesh `[x, z]` polyline onto a `y` plane for a path-follower. */
2
- export function pathFromNav(points, y = 0) {
3
- return points.map((point) => [point[0], y, point[1]]);
1
+ export function pathFromNav(points, elevation = 0, offset = 0) {
2
+ if (typeof elevation === "number") {
3
+ return points.map((point) => [point[0], elevation + offset, point[1]]);
4
+ }
5
+ return points.map((point) => [point[0], elevation.sampleHeight(point[0], point[1]) + offset, point[1]]);
4
6
  }
5
7
  export function createPathFollow(config) {
6
8
  const first = config.waypoints[0];
@@ -0,0 +1,18 @@
1
+ import type { PhysicsWorld } from "./physicsWorld.js";
2
+ export interface BallisticSweepHit {
3
+ point: [number, number, number];
4
+ time: number;
5
+ }
6
+ export type BallisticSweep = (origin: readonly [number, number, number], velocity: readonly [number, number, number], gravity: number, maxTime: number) => BallisticSweepHit | null;
7
+ export interface BallisticSweepOptions {
8
+ /** Fixed march interval along the arc, in seconds. Default 1/60. */
9
+ step?: number;
10
+ /** Projectile radius; each body AABB is inflated by this before the point test. Default 0. */
11
+ radius?: number;
12
+ }
13
+ /**
14
+ * Marches the closed-form arc (constant gravity, straight lateral) through `world` and reports the
15
+ * first sample inside any live body's AABB — sleeping bodies included — refined by one bisection
16
+ * between the last clear sample and the hit sample. Returns `null` when the whole arc is clear.
17
+ */
18
+ export declare function createBallisticSweep(world: PhysicsWorld, options?: BallisticSweepOptions): BallisticSweep;
@@ -0,0 +1,49 @@
1
+ const DEFAULT_SWEEP_STEP = 1 / 60;
2
+ /**
3
+ * Marches the closed-form arc (constant gravity, straight lateral) through `world` and reports the
4
+ * first sample inside any live body's AABB — sleeping bodies included — refined by one bisection
5
+ * between the last clear sample and the hit sample. Returns `null` when the whole arc is clear.
6
+ */
7
+ export function createBallisticSweep(world, options = {}) {
8
+ const step = options.step ?? DEFAULT_SWEEP_STEP;
9
+ const radius = options.radius ?? 0;
10
+ function overlapsAnyBody(x, y, z) {
11
+ for (let i = 0; i < world.highWater; i += 1) {
12
+ if (!world.isAlive(i))
13
+ continue;
14
+ if (Math.abs(x - world.posX[i]) > world.halfX[i] + radius)
15
+ continue;
16
+ if (Math.abs(y - world.posY[i]) > world.halfY[i] + radius)
17
+ continue;
18
+ if (Math.abs(z - world.posZ[i]) > world.halfZ[i] + radius)
19
+ continue;
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ return (origin, velocity, gravity, maxTime) => {
25
+ const pointAt = (t) => [
26
+ origin[0] + velocity[0] * t,
27
+ origin[1] + velocity[1] * t - 0.5 * gravity * t * t,
28
+ origin[2] + velocity[2] * t,
29
+ ];
30
+ let lastClear = 0;
31
+ let t = 0;
32
+ for (;;) {
33
+ const sample = pointAt(t);
34
+ if (overlapsAnyBody(sample[0], sample[1], sample[2])) {
35
+ if (t === 0)
36
+ return { point: sample, time: 0 };
37
+ const mid = (lastClear + t) / 2;
38
+ const midSample = pointAt(mid);
39
+ return overlapsAnyBody(midSample[0], midSample[1], midSample[2])
40
+ ? { point: midSample, time: mid }
41
+ : { point: sample, time: t };
42
+ }
43
+ if (t >= maxTime)
44
+ return null;
45
+ lastClear = t;
46
+ t = Math.min(t + step, maxTime);
47
+ }
48
+ };
49
+ }
@@ -31,8 +31,8 @@ export class ForceVolume {
31
31
  apply(world, dt) {
32
32
  const next = this.nextMembers;
33
33
  next.clear();
34
- const count = world.count;
35
- for (let i = 0; i < count; i += 1) {
34
+ const high = world.highWater;
35
+ for (let i = 0; i < high; i += 1) {
36
36
  if (world.invMass[i] === 0)
37
37
  continue;
38
38
  if (!inside(this.bounds, world.posX[i], world.posY[i], world.posZ[i]))
@@ -99,9 +99,9 @@ export class PlatformCarry {
99
99
  return;
100
100
  const hx = w.halfX[p];
101
101
  const hz = w.halfZ[p];
102
- const count = w.count;
103
- for (let i = 0; i < count; i += 1) {
104
- if (i === p)
102
+ const high = w.highWater;
103
+ for (let i = 0; i < high; i += 1) {
104
+ if (i === p || !w.isAlive(i))
105
105
  continue;
106
106
  const base = w.posY[i] - w.halfY[i];
107
107
  if (base < topY - this.tolerance || base > topY + this.tolerance)
@@ -49,9 +49,8 @@ export interface PhysicsStats {
49
49
  substeps: number;
50
50
  stepMs: number;
51
51
  }
52
- export interface AddBodyOptions {
52
+ export interface BodyCommonOptions {
53
53
  position: readonly [number, number, number];
54
- halfExtents: readonly [number, number, number];
55
54
  velocity?: readonly [number, number, number];
56
55
  /** ≤ 0 or omitted with `static` → infinite mass (immovable collider). Default 1. */
57
56
  mass?: number;
@@ -60,6 +59,18 @@ export interface AddBodyOptions {
60
59
  /** Seed the body asleep (a settled bed pays no integration cost until woken). */
61
60
  asleep?: boolean;
62
61
  }
62
+ export interface BoxBodyOptions extends BodyCommonOptions {
63
+ shape?: "box";
64
+ halfExtents: readonly [number, number, number];
65
+ }
66
+ /** The radius fills all three half-extent columns, so broadphase and bounds see the sphere's enclosing AABB. */
67
+ export interface SphereBodyOptions extends BodyCommonOptions {
68
+ shape: "sphere";
69
+ radius: number;
70
+ }
71
+ export type AddBodyOptions = BoxBodyOptions | SphereBodyOptions;
72
+ export declare const SHAPE_BOX = 0;
73
+ export declare const SHAPE_SPHERE = 1;
63
74
  /**
64
75
  * `hinge`/`fixed`/`distance` are hard bilateral constraints; `spring` is a soft PD constraint.
65
76
  * No angular state → `hinge`/`fixed` both pin the shared anchor (`axis` is metadata), `distance`
@@ -96,6 +107,8 @@ export interface CollisionEvent {
96
107
  approachSpeed: number;
97
108
  impulse: number;
98
109
  }
110
+ /** Cap on `nx*ny*nz` broadphase cells — guards a huge-bounds/tiny-cellSize config from hanging `step()`. */
111
+ export declare const MAX_BROADPHASE_CELLS = 1000000;
99
112
  /** Grid cell containing a point, clamped into the grid. Pure — exported for tests. */
100
113
  export declare function cellCoord(value: number, min: number, cellSize: number, cells: number): number;
101
114
  /** Linear cell index from clamped 3D coords. Pure — exported for tests. */
@@ -130,6 +143,8 @@ export declare class PhysicsWorld {
130
143
  readonly halfZ: Float32Array;
131
144
  readonly invMass: Float32Array;
132
145
  readonly flags: Uint8Array;
146
+ /** `SHAPE_BOX` (0) or `SHAPE_SPHERE` (1) per body; spheres keep their radius in halfX/halfY/halfZ. */
147
+ readonly shape: Uint8Array;
133
148
  /** 1 for a body that took part in a contact this frame; reset each `step()`. Render tint reads this. */
134
149
  readonly contact: Uint8Array;
135
150
  private readonly sleepTimer;
@@ -165,6 +180,9 @@ export declare class PhysicsWorld {
165
180
  private jFreeCount;
166
181
  private jointHigh;
167
182
  private jointActiveCount;
183
+ private readonly bodyFree;
184
+ private bodyFreeCount;
185
+ private bodyHigh;
168
186
  private collisionListener;
169
187
  private collisionMinSpeed;
170
188
  private readonly collisionEvent;
@@ -175,6 +193,8 @@ export declare class PhysicsWorld {
175
193
  private addAwake;
176
194
  private removeAwake;
177
195
  get count(): number;
196
+ /** One past the highest slot `addBody` has ever handed out — the range `removeBody` leaves holes in. */
197
+ get highWater(): number;
178
198
  get cells(): {
179
199
  nx: number;
180
200
  ny: number;
@@ -196,13 +216,32 @@ export declare class PhysicsWorld {
196
216
  removeJoint(id: number): void;
197
217
  /** Move a joint's world anchor point (only meaningful when `bodyB` is a world anchor). */
198
218
  setJointAnchor(id: number, x: number, y: number, z: number): void;
219
+ /** Move a joint's local anchor offset on A (world axes, no rotation applied by the solver). */
220
+ setJointAnchorA(id: number, x: number, y: number, z: number): void;
199
221
  setJointRest(id: number, restLength: number): void;
200
222
  private jointDistance;
201
223
  /** Write [ax,ay,az,bx,by,bz] world endpoints per active joint into `out`; returns the joint count. */
202
224
  readJointSegments(out: Float32Array): number;
203
225
  addBody(options: AddBodyOptions): number;
226
+ /**
227
+ * Remove a body: it drops out of integration, the solver, and the broadphase, and its slot is
228
+ * queued for the next `addBody` to reuse. `id` and every other body's `id` stay valid — a dead
229
+ * slot is tombstoned (`FLAG_DEAD`), never swapped, since ids are handed out raw and stored as-is
230
+ * in joints and game state. There is no persistent contact set to consult, so — conservatively —
231
+ * any sleeping body whose AABB touches the removed body's (padded by `slop`) is woken; a body
232
+ * that was resting on it always qualifies.
233
+ */
234
+ removeBody(id: number): void;
235
+ private wakeTouching;
204
236
  isSleeping(i: number): boolean;
237
+ isAlive(i: number): boolean;
205
238
  wake(i: number): void;
239
+ /** Overwrite a body's velocity directly, waking it if asleep. */
240
+ setVelocity(id: number, x: number, y: number, z: number): void;
241
+ /** Move a body, keeping its current velocity, and wake it if asleep. */
242
+ setPosition(id: number, x: number, y: number, z: number): void;
243
+ /** Move a body and zero its velocity — a hard reset (respawn, teleporter) instead of a slide. */
244
+ teleport(id: number, x: number, y: number, z: number): void;
206
245
  wakeAll(): void;
207
246
  clear(): void;
208
247
  /** Advance by a real frame delta; runs whole fixed substeps and carries the remainder. */