@series-inc/rundot-syncplay 5.27.0 → 5.28.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.d.ts CHANGED
@@ -24,8 +24,9 @@ export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from
24
24
  export { createSyncplayRunner } from './runner.js';
25
25
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
26
26
  export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D } from './physics2d.js';
27
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
28
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
27
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
28
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
29
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
29
30
  export { cylinderHullVertices } from './physics3d-hull.js';
30
31
  export { createDeterministicCosmeticPhysicsWorld3D, setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D, stepDeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
31
32
  export { stepDeterministicVehicle3D } from './physics3d-vehicle.js';
@@ -65,8 +66,9 @@ export type { CookedDeterministicNavmesh, DeterministicNavmeshAgent, Determinist
65
66
  export type { ConfirmedSyncplayPresentationFrame, KinetixRuntimeFactory, NetworkedClientTransport, NetworkedSyncplayClient, NetworkedSyncplayClientInputDelayOptions, NetworkedSyncplayClientNetStats, NetworkedSyncplayClientOptions, NetworkedSyncplayClientPacingOptions, NetworkedSyncplayPreparationOptions, NetworkedSyncplaySessionDescriptor, NetworkedSyncplaySlotPresence, PreparedNetworkedSyncplayTransport, SyncplayPredictionMode, SyncplayRemoteInputPrediction } from './networked-client.js';
66
67
  export type { SyncplayRunner, SyncplayRunnerConfig, SyncplayRunnerConnectionEvent, SyncplayRunnerOccupancy, SyncplayRunnerOfflineOptions, SyncplayRunnerPresentation, SyncplayRunnerSnapshot, SyncplayRunnerStatus, SyncplayRunnerTransport } from './runner.js';
67
68
  export type { DeterministicBodyKind, DeterministicContactEvent2D, DeterministicContactEventType, DeterministicPhysicsAabbQuery2D, DeterministicPhysicsActivePair2D, DeterministicPhysicsBody2D, DeterministicPhysicsCircleCastQuery2D, DeterministicPhysicsConstraint2D, DeterministicPhysicsHit2D, DeterministicPhysicsQueryOptions2D, DeterministicPhysicsRaycastQuery2D, DeterministicPhysicsShape2D, DeterministicPhysicsShapeOverlapQuery2D, DeterministicPhysicsStepOptions2D, DeterministicPhysicsStepResult2D, DeterministicPhysicsWorld2D } from './physics2d.js';
68
- export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D } from './physics3d.js';
69
- export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D } from './physics3d-voxel.js';
69
+ export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicKinematicTransformBuffer3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D } from './physics3d.js';
70
+ export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D, VoxelCarveRegion3D } from './physics3d-voxel.js';
71
+ export type { PhysicsWorldDebugMesh, PhysicsWorldDebugMeshOptions } from './debug-wireframe.js';
70
72
  export type { DeterministicAuthoritativeBodyProxy3D, DeterministicCosmeticPhysicsBody3D, DeterministicCosmeticPhysicsStepOptions3D, DeterministicCosmeticPhysicsStepResult3D, DeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
71
73
  export type { DeterministicPhysicsJoint3D } from './physics3d-joints.js';
72
74
  export type { DeterministicVehicle3D, DeterministicVehicleImpulse3D, DeterministicVehicleInput3D, DeterministicVehicleStepOptions3D, DeterministicVehicleStepResult3D, DeterministicVehicleWheel3D, DeterministicVehicleWheelTelemetry3D } from './physics3d-vehicle.js';
package/dist/browser.js CHANGED
@@ -25,8 +25,9 @@ export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from
25
25
  export { createSyncplayRunner } from './runner.js';
26
26
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
27
27
  export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D } from './physics2d.js';
28
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
29
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
28
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
29
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
30
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
30
31
  export { cylinderHullVertices } from './physics3d-hull.js';
31
32
  export { createDeterministicCosmeticPhysicsWorld3D, setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D, stepDeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
32
33
  export { stepDeterministicVehicle3D } from './physics3d-vehicle.js';
package/dist/creator.d.ts CHANGED
@@ -12,12 +12,14 @@ export type { RecordedChecksum, RecordedCommandFrame, RecordedDebugEvent, Record
12
12
  export type { ReplayRuntimeFactory, ReplayVerificationConfig, ReplayVerificationExecution } from './replay.js';
13
13
  export type { SyncplaySession, SyncplaySessionPolicy } from './sdk-session.js';
14
14
  export type { InstantReplayInputFrame, InstantReplayResult, InstantReplayRunner, InstantReplayRunnerOptions, InstantReplayRunOptions, RunInstantReplayOptions, } from './instant-replay.js';
15
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D, } from './physics3d.js';
16
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
15
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D, } from './physics3d.js';
16
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D, } from './physics3d-voxel.js';
17
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
17
18
  export { cylinderHullVertices } from './physics3d-hull.js';
18
19
  export { stepDeterministicVehicle3D } from './physics3d-vehicle.js';
19
- export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D, } from './physics3d.js';
20
- export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D } from './physics3d-voxel.js';
20
+ export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicKinematicTransformBuffer3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D, } from './physics3d.js';
21
+ export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D, VoxelCarveRegion3D, } from './physics3d-voxel.js';
22
+ export type { PhysicsWorldDebugMesh, PhysicsWorldDebugMeshOptions } from './debug-wireframe.js';
21
23
  export type { DeterministicPhysicsJoint3D } from './physics3d-joints.js';
22
24
  export type { DeterministicVehicle3D, DeterministicVehicleImpulse3D, DeterministicVehicleInput3D, DeterministicVehicleStepOptions3D, DeterministicVehicleStepResult3D, DeterministicVehicleWheel3D, DeterministicVehicleWheelTelemetry3D, } from './physics3d-vehicle.js';
23
25
  export type { DeterministicPhysicsMaterial } from './deterministic-primitives.js';
package/dist/creator.js CHANGED
@@ -9,7 +9,8 @@ export { runSyncplaySynctest } from './synctest.js';
9
9
  // create/step/edit, impulses, queries, vehicles, and voxel-chunk collider
10
10
  // cooking. Cosmetic physics, KCC (movement3d), and the destruction-cert runner
11
11
  // stay off it — the first two are not requested, the third reads wall clock.
12
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D, } from './physics3d.js';
13
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
12
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D, } from './physics3d.js';
13
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D, } from './physics3d-voxel.js';
14
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
14
15
  export { cylinderHullVertices } from './physics3d-hull.js';
15
16
  export { stepDeterministicVehicle3D } from './physics3d-vehicle.js';
@@ -0,0 +1,22 @@
1
+ import type { DeterministicPhysicsWorld3D } from './physics3d.js';
2
+ export interface PhysicsWorldDebugMesh {
3
+ /** Flat vertex positions [x0, y0, z0, x1, y1, z1, ...] for gl.LINES. */
4
+ readonly positions: Float32Array;
5
+ /** Line segment index pairs [start0, end0, start1, end1, ...] for gl.LINES / Three.js LineSegments. */
6
+ readonly indices: Uint32Array;
7
+ }
8
+ export interface PhysicsWorldDebugMeshOptions {
9
+ readonly includeStatics?: boolean;
10
+ readonly includeKinematics?: boolean;
11
+ readonly includeDynamics?: boolean;
12
+ readonly includeTriggers?: boolean;
13
+ readonly includeSensors?: boolean;
14
+ readonly sphereSegments?: number;
15
+ readonly capsuleSegments?: number;
16
+ }
17
+ /**
18
+ * Generates flat position and index buffers of line segments representing all
19
+ * colliders in a deterministic physics world, compatible with Three.js LineSegments
20
+ * and WebGL line rendering pipelines.
21
+ */
22
+ export declare function generatePhysicsWorldDebugMesh(world: DeterministicPhysicsWorld3D, options?: PhysicsWorldDebugMeshOptions): PhysicsWorldDebugMesh;
@@ -0,0 +1,226 @@
1
+ import { canonicalQuarterTurns, quaternionFromQuarterTurns, rotatePointByQuat, } from './physics3d-shared.js';
2
+ import { buildSolverHull } from './physics3d-hull.js';
3
+ function createCircleLines(radius, segments, plane, center = { x: 0, y: 0, z: 0 }) {
4
+ const vertices = [];
5
+ const indices = [];
6
+ const step = (Math.PI * 2) / segments;
7
+ for (let i = 0; i < segments; i += 1) {
8
+ const angle = i * step;
9
+ const cos = Math.cos(angle) * radius;
10
+ const sin = Math.sin(angle) * radius;
11
+ if (plane === 'xy') {
12
+ vertices.push({ x: center.x + cos, y: center.y + sin, z: center.z });
13
+ }
14
+ else if (plane === 'xz') {
15
+ vertices.push({ x: center.x + cos, y: center.y, z: center.z + sin });
16
+ }
17
+ else {
18
+ vertices.push({ x: center.x, y: center.y + cos, z: center.z + sin });
19
+ }
20
+ indices.push(i, (i + 1) % segments);
21
+ }
22
+ return { vertices, indices };
23
+ }
24
+ function createArcLines(radius, segments, plane, center, startAngle, endAngle) {
25
+ const vertices = [];
26
+ const indices = [];
27
+ const span = endAngle - startAngle;
28
+ for (let i = 0; i <= segments; i += 1) {
29
+ const angle = startAngle + (i / segments) * span;
30
+ const cos = Math.cos(angle) * radius;
31
+ const sin = Math.sin(angle) * radius;
32
+ if (plane === 'xy') {
33
+ vertices.push({ x: center.x + cos, y: center.y + sin, z: center.z });
34
+ }
35
+ else {
36
+ vertices.push({ x: center.x, y: center.y + cos, z: center.z + sin });
37
+ }
38
+ if (i < segments) {
39
+ indices.push(i, i + 1);
40
+ }
41
+ }
42
+ return { vertices, indices };
43
+ }
44
+ function appendGeometry(target, source, transform) {
45
+ const vertexOffset = target.vertices.length;
46
+ for (const vertex of source.vertices) {
47
+ let transformed = vertex;
48
+ if (transform?.orientation !== undefined) {
49
+ transformed = rotatePointByQuat(transform.orientation, transformed);
50
+ }
51
+ if (transform?.offset !== undefined) {
52
+ transformed = {
53
+ x: transformed.x + transform.offset.x,
54
+ y: transformed.y + transform.offset.y,
55
+ z: transformed.z + transform.offset.z,
56
+ };
57
+ }
58
+ target.vertices.push(transformed);
59
+ }
60
+ for (const idx of source.indices) {
61
+ target.indices.push(vertexOffset + idx);
62
+ }
63
+ }
64
+ function buildShapeLines(shape, options) {
65
+ const result = { vertices: [], indices: [] };
66
+ const sphereSegs = options.sphereSegments ?? 16;
67
+ const capsuleSegs = options.capsuleSegments ?? 12;
68
+ if (shape.type === 'box') {
69
+ const { halfX, halfY, halfZ } = shape;
70
+ const verts = [
71
+ { x: -halfX, y: -halfY, z: -halfZ },
72
+ { x: halfX, y: -halfY, z: -halfZ },
73
+ { x: halfX, y: -halfY, z: halfZ },
74
+ { x: -halfX, y: -halfY, z: halfZ },
75
+ { x: -halfX, y: halfY, z: -halfZ },
76
+ { x: halfX, y: halfY, z: -halfZ },
77
+ { x: halfX, y: halfY, z: halfZ },
78
+ { x: -halfX, y: halfY, z: halfZ },
79
+ ];
80
+ const indices = [
81
+ 0, 1, 1, 2, 2, 3, 3, 0, // bottom
82
+ 4, 5, 5, 6, 6, 7, 7, 4, // top
83
+ 0, 4, 1, 5, 2, 6, 3, 7, // pillars
84
+ ];
85
+ return { vertices: verts, indices };
86
+ }
87
+ if (shape.type === 'sphere') {
88
+ appendGeometry(result, createCircleLines(shape.radius, sphereSegs, 'xy'));
89
+ appendGeometry(result, createCircleLines(shape.radius, sphereSegs, 'xz'));
90
+ appendGeometry(result, createCircleLines(shape.radius, sphereSegs, 'yz'));
91
+ return result;
92
+ }
93
+ if (shape.type === 'capsule') {
94
+ const { radius: r, halfHeight: h } = shape;
95
+ const halfSegs = Math.max(4, Math.floor(capsuleSegs / 2));
96
+ // 4 cylinder side pillars
97
+ const baseIndex = result.vertices.length;
98
+ result.vertices.push({ x: -r, y: -h, z: 0 }, { x: -r, y: h, z: 0 }, { x: r, y: -h, z: 0 }, { x: r, y: h, z: 0 }, { x: 0, y: -h, z: -r }, { x: 0, y: h, z: -r }, { x: 0, y: -h, z: r }, { x: 0, y: h, z: r });
99
+ result.indices.push(baseIndex, baseIndex + 1, baseIndex + 2, baseIndex + 3, baseIndex + 4, baseIndex + 5, baseIndex + 6, baseIndex + 7);
100
+ // 2 horizontal equator rings
101
+ appendGeometry(result, createCircleLines(r, capsuleSegs, 'xz', { x: 0, y: h, z: 0 }));
102
+ appendGeometry(result, createCircleLines(r, capsuleSegs, 'xz', { x: 0, y: -h, z: 0 }));
103
+ // Top dome arcs
104
+ appendGeometry(result, createArcLines(r, halfSegs, 'xy', { x: 0, y: h, z: 0 }, Math.PI, 0));
105
+ appendGeometry(result, createArcLines(r, halfSegs, 'yz', { x: 0, y: h, z: 0 }, -Math.PI / 2, Math.PI / 2));
106
+ // Bottom dome arcs
107
+ appendGeometry(result, createArcLines(r, halfSegs, 'xy', { x: 0, y: -h, z: 0 }, Math.PI, Math.PI * 2));
108
+ appendGeometry(result, createArcLines(r, halfSegs, 'yz', { x: 0, y: -h, z: 0 }, Math.PI / 2, (3 * Math.PI) / 2));
109
+ return result;
110
+ }
111
+ if (shape.type === 'hull') {
112
+ const hullData = buildSolverHull(shape.vertices);
113
+ const vertices = [...hullData.vertices];
114
+ const indices = [];
115
+ for (const face of hullData.faces) {
116
+ const len = face.verts.length;
117
+ for (let i = 0; i < len; i += 1) {
118
+ indices.push(face.verts[i], face.verts[(i + 1) % len]);
119
+ }
120
+ }
121
+ return { vertices, indices };
122
+ }
123
+ if (shape.type === 'mesh') {
124
+ const vertices = [...shape.vertices];
125
+ const indices = [];
126
+ for (let i = 0; i < vertices.length; i += 3) {
127
+ indices.push(i, i + 1, i + 1, i + 2, i + 2, i);
128
+ }
129
+ return { vertices, indices };
130
+ }
131
+ if (shape.type === 'heightfield') {
132
+ const { columns, rows, scale, heights } = shape;
133
+ const vertices = [];
134
+ const indices = [];
135
+ for (let r = 0; r < rows; r += 1) {
136
+ for (let c = 0; c < columns; c += 1) {
137
+ const h = heights[c + columns * r] ?? 0;
138
+ vertices.push({ x: c * scale.x, y: h * scale.y, z: r * scale.z });
139
+ }
140
+ }
141
+ for (let r = 0; r < rows; r += 1) {
142
+ for (let c = 0; c < columns; c += 1) {
143
+ const curr = c + columns * r;
144
+ if (c + 1 < columns) {
145
+ indices.push(curr, curr + 1);
146
+ }
147
+ if (r + 1 < rows) {
148
+ indices.push(curr, curr + columns);
149
+ }
150
+ if (c + 1 < columns && r + 1 < rows) {
151
+ indices.push(curr + columns, curr + 1);
152
+ }
153
+ }
154
+ }
155
+ return { vertices, indices };
156
+ }
157
+ if (shape.type === 'compound') {
158
+ for (const child of shape.children) {
159
+ const childLines = buildShapeLines(child.shape, options);
160
+ const orientation = child.quarterTurns !== undefined
161
+ ? quaternionFromQuarterTurns({
162
+ x: canonicalQuarterTurns(child.quarterTurns.x),
163
+ y: canonicalQuarterTurns(child.quarterTurns.y),
164
+ z: canonicalQuarterTurns(child.quarterTurns.z),
165
+ })
166
+ : undefined;
167
+ appendGeometry(result, childLines, {
168
+ offset: child.offset,
169
+ orientation,
170
+ });
171
+ }
172
+ return result;
173
+ }
174
+ return result;
175
+ }
176
+ function bodyMatchesFilter(body, options) {
177
+ if (body.kind === 'static' && options.includeStatics === false)
178
+ return false;
179
+ if (body.kind === 'kinematic' && options.includeKinematics === false)
180
+ return false;
181
+ if (body.kind === 'dynamic' && options.includeDynamics === false)
182
+ return false;
183
+ if (body.trigger === true && options.includeTriggers === false)
184
+ return false;
185
+ if (body.sensor === true && options.includeSensors === false)
186
+ return false;
187
+ return true;
188
+ }
189
+ /**
190
+ * Generates flat position and index buffers of line segments representing all
191
+ * colliders in a deterministic physics world, compatible with Three.js LineSegments
192
+ * and WebGL line rendering pipelines.
193
+ */
194
+ export function generatePhysicsWorldDebugMesh(world, options = {}) {
195
+ const worldVertices = [];
196
+ const worldIndices = [];
197
+ let vertexIndexOffset = 0;
198
+ for (const body of world.bodies) {
199
+ if (!bodyMatchesFilter(body, options)) {
200
+ continue;
201
+ }
202
+ const localGeometry = buildShapeLines(body.shape, options);
203
+ const orientation = body.orientation ?? (body.rx !== undefined || body.ry !== undefined || body.rz !== undefined
204
+ ? quaternionFromQuarterTurns({
205
+ x: canonicalQuarterTurns(body.rx ?? 0),
206
+ y: canonicalQuarterTurns(body.ry ?? 0),
207
+ z: canonicalQuarterTurns(body.rz ?? 0),
208
+ })
209
+ : undefined);
210
+ for (const vertex of localGeometry.vertices) {
211
+ let worldPos = vertex;
212
+ if (orientation !== undefined) {
213
+ worldPos = rotatePointByQuat(orientation, worldPos);
214
+ }
215
+ worldVertices.push(worldPos.x + body.x, worldPos.y + body.y, worldPos.z + body.z);
216
+ }
217
+ for (const idx of localGeometry.indices) {
218
+ worldIndices.push(vertexIndexOffset + idx);
219
+ }
220
+ vertexIndexOffset += localGeometry.vertices.length;
221
+ }
222
+ return {
223
+ positions: new Float32Array(worldVertices),
224
+ indices: new Uint32Array(worldIndices),
225
+ };
226
+ }
package/dist/index.d.ts CHANGED
@@ -27,8 +27,9 @@ export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from
27
27
  export { createSyncplayRunner } from './runner.js';
28
28
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
29
29
  export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D } from './physics2d.js';
30
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
31
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
30
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
31
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
32
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
32
33
  export { cylinderHullVertices } from './physics3d-hull.js';
33
34
  export { runDeterministicPhysics3DDestructionCert } from './physics3d-destruction-cert.js';
34
35
  export { createDeterministicCosmeticPhysicsWorld3D, setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D, stepDeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
@@ -77,8 +78,9 @@ export type { CookedDeterministicNavmesh, DeterministicNavmeshAgent, Determinist
77
78
  export type { ConfirmedSyncplayPresentationFrame, KinetixRuntimeFactory, NetworkedClientTransport, NetworkedSyncplayClient, NetworkedSyncplayClientInputDelayOptions, NetworkedSyncplayClientNetStats, NetworkedSyncplayClientOptions, NetworkedSyncplayClientPacingOptions, NetworkedSyncplayPreparationOptions, NetworkedSyncplaySessionDescriptor, PreparedNetworkedSyncplayTransport, SyncplayPredictionMode, SyncplayRemoteInputPrediction } from './networked-client.js';
78
79
  export type { SyncplayRunner, SyncplayRunnerConfig, SyncplayRunnerConnectionEvent, SyncplayRunnerOccupancy, SyncplayRunnerOfflineOptions, SyncplayRunnerPresentation, SyncplayRunnerSnapshot, SyncplayRunnerStatus, SyncplayRunnerTransport } from './runner.js';
79
80
  export type { DeterministicBodyKind, DeterministicContactEvent2D, DeterministicContactEventType, DeterministicPhysicsAabbQuery2D, DeterministicPhysicsBody2D, DeterministicPhysicsCircleCastQuery2D, DeterministicPhysicsConstraint2D, DeterministicPhysicsHit2D, DeterministicPhysicsQueryOptions2D, DeterministicPhysicsRaycastQuery2D, DeterministicPhysicsShape2D, DeterministicPhysicsShapeOverlapQuery2D, DeterministicPhysicsStepOptions2D, DeterministicPhysicsStepResult2D, DeterministicPhysicsWorld2D } from './physics2d.js';
80
- export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D } from './physics3d.js';
81
- export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D } from './physics3d-voxel.js';
81
+ export type { DeterministicContactCacheEntry3D, DeterministicJointCacheEntry3D, DeterministicKinematicPose3D, DeterministicKinematicTransformBuffer3D, DeterministicPhysicsActivePair3D, DeterministicPhysicsAxisLock3D, DeterministicPhysicsBody3D, DeterministicPhysicsCallbackMask3D, DeterministicPhysicsCompoundChild3D, DeterministicPhysicsCompoundChildShape3D, DeterministicPhysicsConstraint3D, DeterministicPhysicsContactDetail3D, DeterministicPhysicsContactEvent3D, DeterministicPhysicsDetailedHit3D, DeterministicPhysicsHit3D, DeterministicPhysicsHullShape3D, DeterministicPhysicsImpulseApplication3D, DeterministicPhysicsOverlapQuery3D, DeterministicPhysicsPrimitiveShape3D, DeterministicPhysicsQuaternion3D, DeterministicPhysicsQueryOptions3D, DeterministicPhysicsRaycastQuery3D, DeterministicPhysicsScheduledQuery3D, DeterministicPhysicsShape3D, DeterministicPhysicsShapeCastQuery3D, DeterministicPhysicsStepResult3D, DeterministicPhysicsVec3, DeterministicPhysicsWorld3D, DeterministicPhysicsWorldEdit3D } from './physics3d.js';
82
+ export type { DeterministicVoxelChunk3D, DeterministicVoxelCompoundShape3D, DeterministicVoxelRayHit3D, VoxelCarveRegion3D } from './physics3d-voxel.js';
83
+ export type { PhysicsWorldDebugMesh, PhysicsWorldDebugMeshOptions } from './debug-wireframe.js';
82
84
  export type { DeterministicDestructionCertOptions, DeterministicDestructionCertResult } from './physics3d-destruction-cert.js';
83
85
  export type { DeterministicAuthoritativeBodyProxy3D, DeterministicCosmeticPhysicsBody3D, DeterministicCosmeticPhysicsStepOptions3D, DeterministicCosmeticPhysicsStepResult3D, DeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
84
86
  export type { DeterministicPhysicsJoint3D } from './physics3d-joints.js';
package/dist/index.js CHANGED
@@ -28,8 +28,9 @@ export { createNetworkedSyncplayClient, prepareNetworkedSyncplayTransport } from
28
28
  export { createSyncplayRunner } from './runner.js';
29
29
  export { fbm2D, hash2, hashUint32, valueNoise1D, valueNoise2D } from './noise.js';
30
30
  export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D } from './physics2d.js';
31
- export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
32
- export { cookDeterministicVoxelChunkCollider3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
31
+ export { applyDeterministicImpulse3D, applyDeterministicImpulses3D, applyDeterministicWorldEdit3D, contactDetailsDeterministicPhysics3D, createBoxShapeFromExtents, createBoxShapeFromMinMax, createCapsuleShapeFromBase, createDeterministicPhysicsWorld3D, createTrustedDeterministicPhysicsWorld3D, deriveInverseInertia, deterministicPhysicsBodyById3D, deterministicPhysicsCallback3D, overlapDeterministicPhysics3D, raycastDeterministicPhysics3D, raycastDeterministicPhysics3DDetailed, runDeterministicPhysics3DStress, setDeterministicBodyVelocity3D, setDeterministicKinematicPoses3D, setDeterministicKinematicTransforms3D, shapeCastDeterministicPhysics3D, shapeCastDeterministicPhysics3DDetailed, stepDeterministicPhysicsWorld3D } from './physics3d.js';
32
+ export { carveDeterministicVoxelChunk3D, cookDeterministicVoxelChunkCollider3D, cookDeterministicVoxelSubregion3D, raycastDeterministicVoxelChunk3D } from './physics3d-voxel.js';
33
+ export { generatePhysicsWorldDebugMesh } from './debug-wireframe.js';
33
34
  export { cylinderHullVertices } from './physics3d-hull.js';
34
35
  export { runDeterministicPhysics3DDestructionCert } from './physics3d-destruction-cert.js';
35
36
  export { createDeterministicCosmeticPhysicsWorld3D, setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D, stepDeterministicCosmeticPhysicsWorld3D } from './cosmetic-physics3d.js';
@@ -40,3 +40,32 @@ export declare function raycastDeterministicVoxelChunk3D(chunk: DeterministicVox
40
40
  * of the occupancy grid.
41
41
  */
42
42
  export declare function cookDeterministicVoxelChunkCollider3D(chunk: DeterministicVoxelChunk3D): DeterministicVoxelCompoundShape3D;
43
+ export interface VoxelCarveRegion3D {
44
+ readonly minX: number;
45
+ readonly minY: number;
46
+ readonly minZ: number;
47
+ readonly maxX: number;
48
+ readonly maxY: number;
49
+ readonly maxZ: number;
50
+ readonly operation: 'carve' | 'fill';
51
+ }
52
+ /**
53
+ * Carves or fills a 3D axis-aligned cell region in a voxel chunk occupancy grid.
54
+ * Computes interval intersection with chunk dimensions, returning chunk unchanged
55
+ * if disjoint or no-op.
56
+ */
57
+ export declare function carveDeterministicVoxelChunk3D(chunk: DeterministicVoxelChunk3D, region: VoxelCarveRegion3D): DeterministicVoxelChunk3D;
58
+ /**
59
+ * Re-cooks compound collider boxes intersecting a dirty AABB cell region,
60
+ * iteratively expanding the re-cook volume to cover any intersecting previously-merged
61
+ * boxes so uncarved solid voxels are never dropped. Preserves disjoint children
62
+ * without full-chunk re-cooking. Returns undefined if 0 voxels remain across the chunk.
63
+ */
64
+ export declare function cookDeterministicVoxelSubregion3D(chunk: DeterministicVoxelChunk3D, existingShape: DeterministicVoxelCompoundShape3D, dirtyRegion: {
65
+ readonly minX: number;
66
+ readonly minY: number;
67
+ readonly minZ: number;
68
+ readonly maxX: number;
69
+ readonly maxY: number;
70
+ readonly maxZ: number;
71
+ }): DeterministicVoxelCompoundShape3D | undefined;
@@ -227,3 +227,202 @@ export function cookDeterministicVoxelChunkCollider3D(chunk) {
227
227
  }
228
228
  return { type: 'compound', children };
229
229
  }
230
+ /**
231
+ * Carves or fills a 3D axis-aligned cell region in a voxel chunk occupancy grid.
232
+ * Computes interval intersection with chunk dimensions, returning chunk unchanged
233
+ * if disjoint or no-op.
234
+ */
235
+ export function carveDeterministicVoxelChunk3D(chunk, region) {
236
+ const { dimX, dimY, dimZ, cellSize, occupancy } = chunk;
237
+ const startX = Math.max(0, Math.min(region.minX, region.maxX));
238
+ const endX = Math.min(dimX - 1, Math.max(region.minX, region.maxX));
239
+ const startY = Math.max(0, Math.min(region.minY, region.maxY));
240
+ const endY = Math.min(dimY - 1, Math.max(region.minY, region.maxY));
241
+ const startZ = Math.max(0, Math.min(region.minZ, region.maxZ));
242
+ const endZ = Math.min(dimZ - 1, Math.max(region.minZ, region.maxZ));
243
+ if (startX > endX || startY > endY || startZ > endZ) {
244
+ return chunk;
245
+ }
246
+ const targetVal = region.operation === 'carve' ? 0 : 1;
247
+ let changed = false;
248
+ const nextOccupancy = [...occupancy];
249
+ for (let z = startZ; z <= endZ; z += 1) {
250
+ for (let y = startY; y <= endY; y += 1) {
251
+ for (let x = startX; x <= endX; x += 1) {
252
+ const index = x + dimX * (y + dimY * z);
253
+ if (nextOccupancy[index] !== targetVal) {
254
+ nextOccupancy[index] = targetVal;
255
+ changed = true;
256
+ }
257
+ }
258
+ }
259
+ }
260
+ if (!changed) {
261
+ return chunk;
262
+ }
263
+ return {
264
+ dimX,
265
+ dimY,
266
+ dimZ,
267
+ cellSize,
268
+ occupancy: nextOccupancy,
269
+ };
270
+ }
271
+ function cookSubregionBoxes(chunk, minX, minY, minZ, maxX, maxY, maxZ) {
272
+ const { dimX, dimY, dimZ, cellSize, occupancy } = chunk;
273
+ const solid = (x, y, z) => occupancy[x + dimX * (y + dimY * z)] !== 0;
274
+ const consumed = new Uint8Array(dimX * dimY * dimZ);
275
+ const free = (x, y, z) => solid(x, y, z) && consumed[x + dimX * (y + dimY * z)] === 0;
276
+ const children = [];
277
+ for (let z = minZ; z <= maxZ; z += 1) {
278
+ for (let y = minY; y <= maxY; y += 1) {
279
+ for (let x = minX; x <= maxX; x += 1) {
280
+ if (!free(x, y, z)) {
281
+ continue;
282
+ }
283
+ let x1 = x;
284
+ while (x1 + 1 <= maxX && free(x1 + 1, y, z)) {
285
+ x1 += 1;
286
+ }
287
+ const rowFree = (yy, zz) => {
288
+ for (let xx = x; xx <= x1; xx += 1) {
289
+ if (!free(xx, yy, zz)) {
290
+ return false;
291
+ }
292
+ }
293
+ return true;
294
+ };
295
+ let y1 = y;
296
+ while (y1 + 1 <= maxY && rowFree(y1 + 1, z)) {
297
+ y1 += 1;
298
+ }
299
+ const slabFree = (zz) => {
300
+ for (let yy = y; yy <= y1; yy += 1) {
301
+ if (!rowFree(yy, zz)) {
302
+ return false;
303
+ }
304
+ }
305
+ return true;
306
+ };
307
+ let z1 = z;
308
+ while (z1 + 1 <= maxZ && slabFree(z1 + 1)) {
309
+ z1 += 1;
310
+ }
311
+ for (let zz = z; zz <= z1; zz += 1) {
312
+ for (let yy = y; yy <= y1; yy += 1) {
313
+ for (let xx = x; xx <= x1; xx += 1) {
314
+ consumed[xx + dimX * (yy + dimY * zz)] = 1;
315
+ }
316
+ }
317
+ }
318
+ children.push({
319
+ shape: {
320
+ type: 'box',
321
+ halfX: ((x1 - x + 1) * cellSize) / 2,
322
+ halfY: ((y1 - y + 1) * cellSize) / 2,
323
+ halfZ: ((z1 - z + 1) * cellSize) / 2,
324
+ },
325
+ offset: {
326
+ x: ((x + x1) / 2) * cellSize,
327
+ y: ((y + y1) / 2) * cellSize,
328
+ z: ((z + z1) / 2) * cellSize,
329
+ },
330
+ });
331
+ }
332
+ }
333
+ }
334
+ return children;
335
+ }
336
+ /**
337
+ * Re-cooks compound collider boxes intersecting a dirty AABB cell region,
338
+ * iteratively expanding the re-cook volume to cover any intersecting previously-merged
339
+ * boxes so uncarved solid voxels are never dropped. Preserves disjoint children
340
+ * without full-chunk re-cooking. Returns undefined if 0 voxels remain across the chunk.
341
+ */
342
+ export function cookDeterministicVoxelSubregion3D(chunk, existingShape, dirtyRegion) {
343
+ const { dimX, dimY, dimZ, cellSize } = chunk;
344
+ let activeMinX = Math.max(0, Math.min(dirtyRegion.minX, dirtyRegion.maxX));
345
+ let activeMaxX = Math.min(dimX - 1, Math.max(dirtyRegion.minX, dirtyRegion.maxX));
346
+ let activeMinY = Math.max(0, Math.min(dirtyRegion.minY, dirtyRegion.maxY));
347
+ let activeMaxY = Math.min(dimY - 1, Math.max(dirtyRegion.minY, dirtyRegion.maxY));
348
+ let activeMinZ = Math.max(0, Math.min(dirtyRegion.minZ, dirtyRegion.maxZ));
349
+ let activeMaxZ = Math.min(dimZ - 1, Math.max(dirtyRegion.minZ, dirtyRegion.maxZ));
350
+ if (activeMinX > activeMaxX || activeMinY > activeMaxY || activeMinZ > activeMaxZ) {
351
+ return existingShape;
352
+ }
353
+ // Iterative fixed-point expansion to absorb all intersecting merged boxes
354
+ let expanded = true;
355
+ while (expanded) {
356
+ expanded = false;
357
+ for (const child of existingShape.children) {
358
+ if (child.shape.type !== 'box') {
359
+ continue;
360
+ }
361
+ const boxMinX = Math.round((child.offset.x - child.shape.halfX) / cellSize + 0.5);
362
+ const boxMaxX = Math.round((child.offset.x + child.shape.halfX) / cellSize - 0.5);
363
+ const boxMinY = Math.round((child.offset.y - child.shape.halfY) / cellSize + 0.5);
364
+ const boxMaxY = Math.round((child.offset.y + child.shape.halfY) / cellSize - 0.5);
365
+ const boxMinZ = Math.round((child.offset.z - child.shape.halfZ) / cellSize + 0.5);
366
+ const boxMaxZ = Math.round((child.offset.z + child.shape.halfZ) / cellSize - 0.5);
367
+ const overlaps = boxMinX <= activeMaxX && boxMaxX >= activeMinX
368
+ && boxMinY <= activeMaxY && boxMaxY >= activeMinY
369
+ && boxMinZ <= activeMaxZ && boxMaxZ >= activeMinZ;
370
+ if (overlaps) {
371
+ if (boxMinX < activeMinX) {
372
+ activeMinX = Math.max(0, boxMinX);
373
+ expanded = true;
374
+ }
375
+ if (boxMaxX > activeMaxX) {
376
+ activeMaxX = Math.min(dimX - 1, boxMaxX);
377
+ expanded = true;
378
+ }
379
+ if (boxMinY < activeMinY) {
380
+ activeMinY = Math.max(0, boxMinY);
381
+ expanded = true;
382
+ }
383
+ if (boxMaxY > activeMaxY) {
384
+ activeMaxY = Math.min(dimY - 1, boxMaxY);
385
+ expanded = true;
386
+ }
387
+ if (boxMinZ < activeMinZ) {
388
+ activeMinZ = Math.max(0, boxMinZ);
389
+ expanded = true;
390
+ }
391
+ if (boxMaxZ > activeMaxZ) {
392
+ activeMaxZ = Math.min(dimZ - 1, boxMaxZ);
393
+ expanded = true;
394
+ }
395
+ }
396
+ }
397
+ }
398
+ // Preserve disjoint children
399
+ const preservedChildren = [];
400
+ for (const child of existingShape.children) {
401
+ if (child.shape.type !== 'box') {
402
+ preservedChildren.push(child);
403
+ continue;
404
+ }
405
+ const boxMinX = Math.round((child.offset.x - child.shape.halfX) / cellSize + 0.5);
406
+ const boxMaxX = Math.round((child.offset.x + child.shape.halfX) / cellSize - 0.5);
407
+ const boxMinY = Math.round((child.offset.y - child.shape.halfY) / cellSize + 0.5);
408
+ const boxMaxY = Math.round((child.offset.y + child.shape.halfY) / cellSize - 0.5);
409
+ const boxMinZ = Math.round((child.offset.z - child.shape.halfZ) / cellSize + 0.5);
410
+ const boxMaxZ = Math.round((child.offset.z + child.shape.halfZ) / cellSize - 0.5);
411
+ const overlaps = boxMinX <= activeMaxX && boxMaxX >= activeMinX
412
+ && boxMinY <= activeMaxY && boxMaxY >= activeMinY
413
+ && boxMinZ <= activeMaxZ && boxMaxZ >= activeMinZ;
414
+ if (!overlaps) {
415
+ preservedChildren.push(child);
416
+ }
417
+ }
418
+ // Cook newly carved/filled subregion
419
+ const subCooked = cookSubregionBoxes(chunk, activeMinX, activeMinY, activeMinZ, activeMaxX, activeMaxY, activeMaxZ);
420
+ const finalChildren = [...preservedChildren, ...subCooked];
421
+ if (finalChildren.length === 0) {
422
+ return undefined;
423
+ }
424
+ return {
425
+ type: 'compound',
426
+ children: finalChildren,
427
+ };
428
+ }
@@ -58,6 +58,24 @@ export type DeterministicPhysicsShape3D = DeterministicPhysicsPrimitiveShape3D |
58
58
  readonly type: 'compound';
59
59
  readonly children: readonly DeterministicPhysicsCompoundChild3D[];
60
60
  };
61
+ /**
62
+ * Creates a centered axis-aligned box shape from full dimensional sizes (sizeX, sizeY, sizeZ).
63
+ */
64
+ export declare function createBoxShapeFromExtents(sizeX: number, sizeY: number, sizeZ: number): Extract<DeterministicPhysicsShape3D, {
65
+ readonly type: 'box';
66
+ }>;
67
+ /**
68
+ * Creates a box shape from min and max bounding coordinates.
69
+ * Returns a simple box if centered at (0,0,0), or a single-child compound with offset if not centered.
70
+ */
71
+ export declare function createBoxShapeFromMinMax(min: Point3D, max: Point3D): DeterministicPhysicsShape3D;
72
+ /**
73
+ * Creates an upright capsule shape anchored at its base (y = 0), matching character controller conventions.
74
+ * Encapsulates the offset into a single-child compound shape centered at y = halfHeight + radius.
75
+ */
76
+ export declare function createCapsuleShapeFromBase(radius: number, totalHeight: number): Extract<DeterministicPhysicsShape3D, {
77
+ readonly type: 'compound';
78
+ }>;
61
79
  export declare const deterministicPhysicsCallback3D: {
62
80
  readonly collisionEnter: 1;
63
81
  readonly collisionStay: 2;
@@ -220,6 +238,11 @@ export interface DeterministicKinematicPose3D {
220
238
  readonly angularVelY?: number;
221
239
  readonly angularVelZ?: number;
222
240
  }
241
+ export interface DeterministicKinematicTransformBuffer3D {
242
+ readonly bodyIds: readonly string[];
243
+ /** Flat [x, y, z, qx, qy, qz, qw] buffer per body. Length must be bodyIds.length * 7. */
244
+ readonly transforms: Float64Array | Float32Array | readonly number[];
245
+ }
223
246
  export interface DeterministicPhysicsScheduledQuery3D {
224
247
  readonly id: string;
225
248
  readonly phase: 'pre-physics' | 'post-physics';
@@ -389,6 +412,14 @@ export declare function applyDeterministicWorldEdit3D(world: DeterministicPhysic
389
412
  export declare function setDeterministicKinematicPoses3D(world: DeterministicPhysicsWorld3D, poses: readonly DeterministicKinematicPose3D[], options?: {
390
413
  readonly dtTicks?: number;
391
414
  }): DeterministicPhysicsWorld3D;
415
+ /**
416
+ * Allocation-free flat buffer batch update of kinematic body transforms.
417
+ * Accepts flat [x, y, z, qx, qy, qz, qw] arrays with stride 7 per bodyId,
418
+ * eliminating caller-side object allocations on high-frequency animation loops.
419
+ */
420
+ export declare function setDeterministicKinematicTransforms3D(world: DeterministicPhysicsWorld3D, buffer: DeterministicKinematicTransformBuffer3D, options?: {
421
+ readonly dtTicks?: number;
422
+ }): DeterministicPhysicsWorld3D;
392
423
  /**
393
424
  * Apply a deterministic impulse to a body (linear + angular via lever arm),
394
425
  * waking the body and its contact island. Returns a new canonical world.
package/dist/physics3d.js CHANGED
@@ -7,6 +7,73 @@ import { buildSolverHull, rayHullIntervalLocal, } from './physics3d-hull.js';
7
7
  import { computeShapeMassProperties } from './physics3d-mass.js';
8
8
  import { heightfieldLocalBounds, heightfieldLocalTriangles } from './physics3d-heightfield.js';
9
9
  import { conservativeToi, toiProxiesOf, toiProxyOf, } from './physics3d-toi.js';
10
+ /**
11
+ * Creates a centered axis-aligned box shape from full dimensional sizes (sizeX, sizeY, sizeZ).
12
+ */
13
+ export function createBoxShapeFromExtents(sizeX, sizeY, sizeZ) {
14
+ if (!Number.isFinite(sizeX) || sizeX <= 0 || !Number.isFinite(sizeY) || sizeY <= 0 || !Number.isFinite(sizeZ) || sizeZ <= 0) {
15
+ throw new Error(`createBoxShapeFromExtents: sizeX, sizeY, sizeZ must be positive finite numbers, received (${sizeX}, ${sizeY}, ${sizeZ})`);
16
+ }
17
+ return {
18
+ type: 'box',
19
+ halfX: sizeX / 2,
20
+ halfY: sizeY / 2,
21
+ halfZ: sizeZ / 2,
22
+ };
23
+ }
24
+ /**
25
+ * Creates a box shape from min and max bounding coordinates.
26
+ * Returns a simple box if centered at (0,0,0), or a single-child compound with offset if not centered.
27
+ */
28
+ export function createBoxShapeFromMinMax(min, max) {
29
+ if (!Number.isFinite(min.x) || !Number.isFinite(min.y) || !Number.isFinite(min.z)
30
+ || !Number.isFinite(max.x) || !Number.isFinite(max.y) || !Number.isFinite(max.z)) {
31
+ throw new Error('createBoxShapeFromMinMax: min and max coordinates must be finite numbers');
32
+ }
33
+ if (max.x <= min.x || max.y <= min.y || max.z <= min.z) {
34
+ throw new Error(`createBoxShapeFromMinMax: max must be strictly greater than min on all axes, received min (${min.x},${min.y},${min.z}) max (${max.x},${max.y},${max.z})`);
35
+ }
36
+ const halfX = (max.x - min.x) / 2;
37
+ const halfY = (max.y - min.y) / 2;
38
+ const halfZ = (max.z - min.z) / 2;
39
+ const cx = (min.x + max.x) / 2;
40
+ const cy = (min.y + max.y) / 2;
41
+ const cz = (min.z + max.z) / 2;
42
+ if (cx === 0 && cy === 0 && cz === 0) {
43
+ return { type: 'box', halfX, halfY, halfZ };
44
+ }
45
+ return {
46
+ type: 'compound',
47
+ children: [
48
+ {
49
+ shape: { type: 'box', halfX, halfY, halfZ },
50
+ offset: { x: cx, y: cy, z: cz },
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ /**
56
+ * Creates an upright capsule shape anchored at its base (y = 0), matching character controller conventions.
57
+ * Encapsulates the offset into a single-child compound shape centered at y = halfHeight + radius.
58
+ */
59
+ export function createCapsuleShapeFromBase(radius, totalHeight) {
60
+ if (!Number.isFinite(radius) || radius <= 0 || !Number.isFinite(totalHeight) || totalHeight <= 0) {
61
+ throw new Error(`createCapsuleShapeFromBase: radius and totalHeight must be positive finite numbers, received radius ${radius}, totalHeight ${totalHeight}`);
62
+ }
63
+ if (totalHeight <= 2 * radius) {
64
+ throw new Error(`createCapsuleShapeFromBase: totalHeight must be strictly greater than 2 * radius (${2 * radius}), received ${totalHeight}`);
65
+ }
66
+ const halfHeight = (totalHeight - 2 * radius) / 2;
67
+ return {
68
+ type: 'compound',
69
+ children: [
70
+ {
71
+ shape: { type: 'capsule', radius, halfHeight },
72
+ offset: { x: 0, y: halfHeight + radius, z: 0 },
73
+ },
74
+ ],
75
+ };
76
+ }
10
77
  export const deterministicPhysicsCallback3D = {
11
78
  collisionEnter: 1,
12
79
  collisionStay: 2,
@@ -281,24 +348,7 @@ export function applyDeterministicWorldEdit3D(world, edit) {
281
348
  : world.jointCache.filter((entry) => !removeJointIds.has(entry.jointId)),
282
349
  };
283
350
  }
284
- /**
285
- * Fast batch update of kinematic body transforms and velocities without
286
- * allocating Set instances or re-sorting world bodies. Wakes touching dynamic
287
- * bodies across active contact pairs. If linear velocity (vx, vy, vz) is omitted
288
- * and dtTicks (> 0) is supplied, linear velocity is derived as (newPos - oldPos) / dtTicks.
289
- */
290
- export function setDeterministicKinematicPoses3D(world, poses, options = {}) {
291
- if (poses.length === 0) {
292
- return world;
293
- }
294
- const dt = options.dtTicks !== undefined && options.dtTicks > 0 ? options.dtTicks : undefined;
295
- const poseById = new Map();
296
- for (const pose of poses) {
297
- if (!Number.isFinite(pose.x) || !Number.isFinite(pose.y) || !Number.isFinite(pose.z)) {
298
- throw new Error(`setDeterministicKinematicPoses3D: body ${pose.id} position must be finite numbers`);
299
- }
300
- poseById.set(pose.id, pose);
301
- }
351
+ function applyKinematicUpdatesInternal(world, poseById, dt, callerName) {
302
352
  const updatedIds = new Set();
303
353
  const movedBodies = new Map();
304
354
  const newBodies = world.bodies.map((body) => {
@@ -307,7 +357,7 @@ export function setDeterministicKinematicPoses3D(world, poses, options = {}) {
307
357
  return body;
308
358
  }
309
359
  if (body.kind !== 'kinematic') {
310
- throw new Error(`setDeterministicKinematicPoses3D: body ${body.id} is ${body.kind}, expected kinematic`);
360
+ throw new Error(`${callerName}: body ${body.id} is ${body.kind}, expected kinematic`);
311
361
  }
312
362
  updatedIds.add(body.id);
313
363
  let vx = pose.vx;
@@ -350,9 +400,9 @@ export function setDeterministicKinematicPoses3D(world, poses, options = {}) {
350
400
  movedBodies.set(body.id, updated);
351
401
  return updated;
352
402
  });
353
- for (const pose of poses) {
354
- if (!updatedIds.has(pose.id)) {
355
- throw new Error(`setDeterministicKinematicPoses3D: cannot update unknown kinematic body ${pose.id}`);
403
+ for (const id of poseById.keys()) {
404
+ if (!updatedIds.has(id)) {
405
+ throw new Error(`${callerName}: cannot update unknown kinematic body ${id}`);
356
406
  }
357
407
  }
358
408
  // Wake any dynamic bodies that share active pairs with updated kinematics
@@ -379,6 +429,64 @@ export function setDeterministicKinematicPoses3D(world, poses, options = {}) {
379
429
  bodies: finalBodies,
380
430
  };
381
431
  }
432
+ /**
433
+ * Fast batch update of kinematic body transforms and velocities without
434
+ * allocating Set instances or re-sorting world bodies. Wakes touching dynamic
435
+ * bodies across active contact pairs. If linear velocity (vx, vy, vz) is omitted
436
+ * and dtTicks (> 0) is supplied, linear velocity is derived as (newPos - oldPos) / dtTicks.
437
+ */
438
+ export function setDeterministicKinematicPoses3D(world, poses, options = {}) {
439
+ if (poses.length === 0) {
440
+ return world;
441
+ }
442
+ const dt = options.dtTicks !== undefined && options.dtTicks > 0 ? options.dtTicks : undefined;
443
+ const poseById = new Map();
444
+ for (const pose of poses) {
445
+ if (!Number.isFinite(pose.x) || !Number.isFinite(pose.y) || !Number.isFinite(pose.z)) {
446
+ throw new Error(`setDeterministicKinematicPoses3D: body ${pose.id} position must be finite numbers`);
447
+ }
448
+ poseById.set(pose.id, pose);
449
+ }
450
+ return applyKinematicUpdatesInternal(world, poseById, dt, 'setDeterministicKinematicPoses3D');
451
+ }
452
+ /**
453
+ * Allocation-free flat buffer batch update of kinematic body transforms.
454
+ * Accepts flat [x, y, z, qx, qy, qz, qw] arrays with stride 7 per bodyId,
455
+ * eliminating caller-side object allocations on high-frequency animation loops.
456
+ */
457
+ export function setDeterministicKinematicTransforms3D(world, buffer, options = {}) {
458
+ const { bodyIds, transforms } = buffer;
459
+ if (transforms.length !== bodyIds.length * 7) {
460
+ throw new Error(`setDeterministicKinematicTransforms3D: transforms length must equal bodyIds.length * 7 (${bodyIds.length * 7}), received ${transforms.length}`);
461
+ }
462
+ if (bodyIds.length === 0) {
463
+ return world;
464
+ }
465
+ const dt = options.dtTicks !== undefined && options.dtTicks > 0 ? options.dtTicks : undefined;
466
+ const poseById = new Map();
467
+ for (let i = 0; i < bodyIds.length; i += 1) {
468
+ const id = bodyIds[i];
469
+ const offset = i * 7;
470
+ const x = transforms[offset];
471
+ const y = transforms[offset + 1];
472
+ const z = transforms[offset + 2];
473
+ const qx = transforms[offset + 3];
474
+ const qy = transforms[offset + 4];
475
+ const qz = transforms[offset + 5];
476
+ const qw = transforms[offset + 6];
477
+ if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)
478
+ || !Number.isFinite(qx) || !Number.isFinite(qy) || !Number.isFinite(qz) || !Number.isFinite(qw)) {
479
+ throw new Error(`setDeterministicKinematicTransforms3D: body ${id} transform contains non-finite numbers`);
480
+ }
481
+ poseById.set(id, {
482
+ x,
483
+ y,
484
+ z,
485
+ orientation: { x: qx, y: qy, z: qz, w: qw },
486
+ });
487
+ }
488
+ return applyKinematicUpdatesInternal(world, poseById, dt, 'setDeterministicKinematicTransforms3D');
489
+ }
382
490
  /**
383
491
  * Apply a deterministic impulse to a body (linear + angular via lever arm),
384
492
  * waking the body and its contact island. Returns a new canonical world.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@series-inc/rundot-syncplay",
3
- "version": "5.27.0",
3
+ "version": "5.28.0-beta.0",
4
4
  "description": "Kinetix orchestration, rollback, replay, late-join, and deterministic networking for RUN.game",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,6 +42,11 @@
42
42
  "import": "./dist/tools/index.js",
43
43
  "default": "./dist/tools/index.js"
44
44
  },
45
+ "./debug": {
46
+ "types": "./dist/debug-wireframe.d.ts",
47
+ "import": "./dist/debug-wireframe.js",
48
+ "default": "./dist/debug-wireframe.js"
49
+ },
45
50
  "./modules/component-model": {
46
51
  "types": "./dist/modules/component-model.d.ts",
47
52
  "import": "./dist/modules/component-model.js",
@@ -163,7 +168,7 @@
163
168
  "test:core": "node --expose-gc --import tsx --test --test-concurrency=1 tests/canonical.test.ts tests/canonical-portability.test.ts tests/runtime-session.test.ts tests/kinetix-runtime-session.test.ts tests/runtime-support.test.ts tests/runtime-guards.test.ts tests/r3f-render-adapter.test.ts tests/snapshot-cost.test.ts tests/sdkSession.test.ts tests/input-authority.test.ts tests/session-wire.test.ts tests/runtime-room-metadata.test.ts tests/session-snapshot.test.ts tests/authority-room.test.ts tests/networked-client-snapshot.test.ts tests/runner.test.ts tests/testing.test.ts tests/browser-session.test.ts tests/secret-config.test.ts tests/secret-protocol.test.ts tests/secret-authority.test.ts tests/secret-client.test.ts tests/late-join-checksum.test.ts tests/late-join-input-backfill.test.ts tests/replay-scoring.test.ts tests/bot-backfill.test.ts tests/latency-simulation.test.ts tests/production-input-budget.test.ts tests/time-sync.test.ts tests/match-log.test.ts tests/spectator.test.ts tests/synctest.test.ts tests/instant-replay.test.ts tests/session-promotion.test.ts tests/physics3d-broadphase-stats.test.ts tests/entrypoints.test.ts tests/export-surface.test.ts tests/module-seam.test.ts tests/module-contract-portability.test.ts tests/module-identity.test.ts tests/module-corpus.test.ts tests/component-model.test.ts tests/component-model-rollback.test.ts tests/component-model-integration.test.ts tests/actors-ai.test.ts tests/character-3d.test.ts tests/character-3d-certification.test.ts tests/combat-modules.test.ts tests/combat-modules-integration.test.ts tests/firearm.test.ts tests/gameplay-effects.test.ts tests/spatial-interaction.test.ts tests/stats-abilities.test.ts tests/inventory-equipment.test.ts tests/inventory-equipment-certification.test.ts tests/platformer-2d.test.ts tests/platformer-2d-certification.test.ts tests/module-promotion.test.ts tests/module-docs.test.ts tests/module-bundle-budget.test.ts tests/published-side-effects.test.ts tests/host-timing.test.ts tests/test-manifest.test.ts tests/coarse-region.test.ts tests/input-codec.test.ts tests/command-ingress.test.ts tests/session-reconfigure.test.ts tests/prediction-mode.test.ts tests/ephemeral-channel.test.ts tests/runner-surface.test.ts tests/runner-harness.test.ts tests/effects-adapter-bounds.test.ts tests/simulated-match-secrets.test.ts tests/run-glue-surface.test.mjs core/tests/core-boundary.test.mjs tests/math-core-parity.test.ts tests/math-profile.test.ts tests/movement3d-kcc-unit-contract.test.ts tests/movement3d-static-ground.test.ts",
164
169
  "test:sdk-contract": "node --import tsx --test tests/sdk-runtime-contract.test.ts",
165
170
  "test:soak": "tsx --test tests/runtime-soak.test.ts",
166
- "test:extended": "tsx --test tests/kcc-vehicle-characterization.test.ts tests/animation.test.ts tests/asset-cooking.test.ts tests/backend-proof-checksum-vectors.test.ts tests/bot-documents.test.ts tests/bot-primitives.test.ts tests/collider-cooking.test.ts tests/collision.test.ts tests/command-timeline.test.ts tests/config-bundle.test.ts tests/cosmetic-physics3d.test.ts tests/deterministic-primitives.test.ts tests/ecs-lite.test.ts tests/effects-adapter.test.ts tests/engine-runtime.test.ts tests/errors.test.ts tests/events.test.ts tests/input-button.test.ts tests/load-128-players.test.ts tests/math.test.ts tests/movement.test.ts tests/movement3d.test.ts tests/multiclient-authority.test.ts tests/navigation.test.ts tests/noise.test.ts tests/physics-cert.test.ts tests/physics2d.test.ts tests/physics3d-ccd.test.ts tests/physics3d-coverage.test.ts tests/physics3d-destruction-cert.test.ts tests/physics3d-geometry-limits.test.ts tests/physics3d-heightfield.test.ts tests/physics3d-hull.test.ts tests/physics3d-joints.test.ts tests/physics3d-kinematic-mesh.test.ts tests/physics3d-kinematic-poses.test.ts tests/physics3d-mass.test.ts tests/physics3d-materials.test.ts tests/physics3d-mesh-onesided.test.ts tests/physics3d-queries-capsule-childindex.test.ts tests/physics3d-query-index.test.ts tests/physics3d-recipes.test.ts tests/physics3d-rotation-convention.test.ts tests/physics3d-shared.test.ts tests/physics3d-sleeping-manifold-reuse.test.ts tests/physics3d-solver.test.ts tests/physics3d-static-memoization.test.ts tests/physics3d-static-overlap-memo.test.ts tests/physics3d-cylinder-hull.test.ts tests/physics3d-stacking.test.ts tests/physics3d-toi.test.ts tests/physics3d-vehicle.test.ts tests/physics3d-voxel-dda.test.ts tests/physics3d-voxel.test.ts tests/physics3d-world-edit.test.ts tests/physics3d.test.ts tests/physics-vector-generator.test.ts tests/random.test.ts tests/rollback-history.test.ts tests/schema-artifacts.test.ts tests/schema-codegen.test.ts tests/schema-dsl-binary.test.ts tests/schema.test.ts tests/signals.test.ts tests/sparse-set.test.ts tests/static-checker.test.ts tests/system-lifecycle.test.ts tests/wire-canonical-sentinels.test.ts tests/ws-frame.test.ts",
171
+ "test:extended": "tsx --test tests/kcc-vehicle-characterization.test.ts tests/animation.test.ts tests/asset-cooking.test.ts tests/backend-proof-checksum-vectors.test.ts tests/bot-documents.test.ts tests/bot-primitives.test.ts tests/collider-cooking.test.ts tests/collision.test.ts tests/command-timeline.test.ts tests/config-bundle.test.ts tests/cosmetic-physics3d.test.ts tests/deterministic-primitives.test.ts tests/ecs-lite.test.ts tests/effects-adapter.test.ts tests/engine-runtime.test.ts tests/errors.test.ts tests/events.test.ts tests/input-button.test.ts tests/load-128-players.test.ts tests/math.test.ts tests/movement.test.ts tests/movement3d.test.ts tests/multiclient-authority.test.ts tests/navigation.test.ts tests/noise.test.ts tests/physics-cert.test.ts tests/physics2d.test.ts tests/physics3d-ccd.test.ts tests/physics3d-coverage.test.ts tests/physics3d-debug-wireframe.test.ts tests/physics3d-destruction-cert.test.ts tests/physics3d-geometry-limits.test.ts tests/physics3d-heightfield.test.ts tests/physics3d-hull.test.ts tests/physics3d-joints.test.ts tests/physics3d-kinematic-mesh.test.ts tests/physics3d-kinematic-poses.test.ts tests/physics3d-kinematic-transforms.test.ts tests/physics3d-mass.test.ts tests/physics3d-materials.test.ts tests/physics3d-mesh-onesided.test.ts tests/physics3d-queries-capsule-childindex.test.ts tests/physics3d-query-index.test.ts tests/physics3d-recipes.test.ts tests/physics3d-rotation-convention.test.ts tests/physics3d-shape-builders.test.ts tests/physics3d-shared.test.ts tests/physics3d-sleeping-manifold-reuse.test.ts tests/physics3d-solver.test.ts tests/physics3d-static-memoization.test.ts tests/physics3d-static-overlap-memo.test.ts tests/physics3d-cylinder-hull.test.ts tests/physics3d-stacking.test.ts tests/physics3d-toi.test.ts tests/physics3d-vehicle.test.ts tests/physics3d-voxel-carving.test.ts tests/physics3d-voxel-dda.test.ts tests/physics3d-voxel.test.ts tests/physics3d-world-edit.test.ts tests/physics3d.test.ts tests/physics-vector-generator.test.ts tests/random.test.ts tests/rollback-history.test.ts tests/schema-artifacts.test.ts tests/schema-codegen.test.ts tests/schema-dsl-binary.test.ts tests/schema.test.ts tests/signals.test.ts tests/sparse-set.test.ts tests/static-checker.test.ts tests/system-lifecycle.test.ts tests/wire-canonical-sentinels.test.ts tests/ws-frame.test.ts",
167
172
  "test:ci": "npm run build && npm run test",
168
173
  "build:native": "node core/scripts/build-native.mjs",
169
174
  "build:mobile-native": "node core/scripts/build-mobile-native.mjs",