@series-inc/rundot-syncplay 5.26.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/core/native/physics/physics.cpp +129 -3
- package/core/native/physics/physics.hpp +1 -1
- package/core/physics.d.ts +1 -0
- package/core/scripts/build-wasm-physics.mjs +1 -1
- package/core/src/physics/index.mjs +20 -9
- package/core/src/physics/physics-wasm-module.generated.mjs +4 -4
- package/dist/browser.d.ts +6 -4
- package/dist/browser.js +3 -2
- package/dist/creator.d.ts +6 -4
- package/dist/creator.js +3 -2
- package/dist/debug-wireframe.d.ts +22 -0
- package/dist/debug-wireframe.js +226 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +3 -2
- package/dist/physics3d-voxel.d.ts +52 -1
- package/dist/physics3d-voxel.js +337 -0
- package/dist/physics3d.d.ts +57 -0
- package/dist/physics3d.js +295 -1
- package/package.json +7 -2
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,6 +348,145 @@ export function applyDeterministicWorldEdit3D(world, edit) {
|
|
|
281
348
|
: world.jointCache.filter((entry) => !removeJointIds.has(entry.jointId)),
|
|
282
349
|
};
|
|
283
350
|
}
|
|
351
|
+
function applyKinematicUpdatesInternal(world, poseById, dt, callerName) {
|
|
352
|
+
const updatedIds = new Set();
|
|
353
|
+
const movedBodies = new Map();
|
|
354
|
+
const newBodies = world.bodies.map((body) => {
|
|
355
|
+
const pose = poseById.get(body.id);
|
|
356
|
+
if (pose === undefined) {
|
|
357
|
+
return body;
|
|
358
|
+
}
|
|
359
|
+
if (body.kind !== 'kinematic') {
|
|
360
|
+
throw new Error(`${callerName}: body ${body.id} is ${body.kind}, expected kinematic`);
|
|
361
|
+
}
|
|
362
|
+
updatedIds.add(body.id);
|
|
363
|
+
let vx = pose.vx;
|
|
364
|
+
let vy = pose.vy;
|
|
365
|
+
let vz = pose.vz;
|
|
366
|
+
if (vx === undefined || vy === undefined || vz === undefined) {
|
|
367
|
+
if (dt !== undefined) {
|
|
368
|
+
vx = vx ?? (pose.x - body.x) / dt;
|
|
369
|
+
vy = vy ?? (pose.y - body.y) / dt;
|
|
370
|
+
vz = vz ?? (pose.z - body.z) / dt;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
vx = vx ?? body.vx;
|
|
374
|
+
vy = vy ?? body.vy;
|
|
375
|
+
vz = vz ?? body.vz;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
let angularVel = body.angularVel;
|
|
379
|
+
if (pose.angularVelX !== undefined || pose.angularVelY !== undefined || pose.angularVelZ !== undefined) {
|
|
380
|
+
angularVel = {
|
|
381
|
+
x: pose.angularVelX ?? body.angularVel?.x ?? 0,
|
|
382
|
+
y: pose.angularVelY ?? body.angularVel?.y ?? 0,
|
|
383
|
+
z: pose.angularVelZ ?? body.angularVel?.z ?? 0,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const updated = {
|
|
387
|
+
...body,
|
|
388
|
+
x: pose.x,
|
|
389
|
+
y: pose.y,
|
|
390
|
+
z: pose.z,
|
|
391
|
+
vx,
|
|
392
|
+
vy,
|
|
393
|
+
vz,
|
|
394
|
+
rx: pose.rx ?? body.rx,
|
|
395
|
+
ry: pose.ry ?? body.ry,
|
|
396
|
+
rz: pose.rz ?? body.rz,
|
|
397
|
+
orientation: pose.orientation ?? body.orientation,
|
|
398
|
+
angularVel,
|
|
399
|
+
};
|
|
400
|
+
movedBodies.set(body.id, updated);
|
|
401
|
+
return updated;
|
|
402
|
+
});
|
|
403
|
+
for (const id of poseById.keys()) {
|
|
404
|
+
if (!updatedIds.has(id)) {
|
|
405
|
+
throw new Error(`${callerName}: cannot update unknown kinematic body ${id}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// Wake any dynamic bodies that share active pairs with updated kinematics
|
|
409
|
+
const wokenDynamicIds = new Set();
|
|
410
|
+
for (const pair of world.activePairMetadata) {
|
|
411
|
+
if (movedBodies.has(pair.a)) {
|
|
412
|
+
for (const member of contactIslandFor(world, pair.b)) {
|
|
413
|
+
wokenDynamicIds.add(member);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
else if (movedBodies.has(pair.b)) {
|
|
417
|
+
for (const member of contactIslandFor(world, pair.a)) {
|
|
418
|
+
wokenDynamicIds.add(member);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const finalBodies = wokenDynamicIds.size === 0
|
|
423
|
+
? newBodies
|
|
424
|
+
: newBodies.map((body) => (wokenDynamicIds.has(body.id) && body.kind === 'dynamic' && body.sleeping
|
|
425
|
+
? { ...body, sleeping: false, lowVelFrames: 0 }
|
|
426
|
+
: body));
|
|
427
|
+
return {
|
|
428
|
+
...world,
|
|
429
|
+
bodies: finalBodies,
|
|
430
|
+
};
|
|
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
|
+
}
|
|
284
490
|
/**
|
|
285
491
|
* Apply a deterministic impulse to a body (linear + angular via lever arm),
|
|
286
492
|
* waking the body and its contact island. Returns a new canonical world.
|
|
@@ -3112,6 +3318,27 @@ function rayBodyDistance(body, query) {
|
|
|
3112
3318
|
if (body.shape.type === 'hull') {
|
|
3113
3319
|
return rayHullBodyDistance(body, body.shape, query);
|
|
3114
3320
|
}
|
|
3321
|
+
if (body.shape.type === 'compound') {
|
|
3322
|
+
let closestDistance;
|
|
3323
|
+
for (let index = 0; index < body.shape.children.length; index += 1) {
|
|
3324
|
+
const child = body.shape.children[index];
|
|
3325
|
+
const childBody = {
|
|
3326
|
+
...body,
|
|
3327
|
+
x: (body.x ?? 0) + (child.offset?.x ?? 0),
|
|
3328
|
+
y: (body.y ?? 0) + (child.offset?.y ?? 0),
|
|
3329
|
+
z: (body.z ?? 0) + (child.offset?.z ?? 0),
|
|
3330
|
+
shape: child.shape,
|
|
3331
|
+
rx: (body.rx ?? 0) + canonicalQuarterTurns(child.quarterTurns?.x ?? 0) / 4,
|
|
3332
|
+
ry: (body.ry ?? 0) + canonicalQuarterTurns(child.quarterTurns?.y ?? 0) / 4,
|
|
3333
|
+
rz: (body.rz ?? 0) + canonicalQuarterTurns(child.quarterTurns?.z ?? 0) / 4,
|
|
3334
|
+
};
|
|
3335
|
+
const childDistance = rayBodyDistance(childBody, query);
|
|
3336
|
+
if (childDistance !== undefined && (closestDistance === undefined || childDistance < closestDistance)) {
|
|
3337
|
+
closestDistance = childDistance;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
return closestDistance;
|
|
3341
|
+
}
|
|
3115
3342
|
return rayAabbDistance(toBounds(body), query);
|
|
3116
3343
|
}
|
|
3117
3344
|
function rayHullBodyDistance(body, shape, query) {
|
|
@@ -3425,13 +3652,61 @@ function countCandidatePairs(bodies) {
|
|
|
3425
3652
|
countCandidatePairsCalls += 1;
|
|
3426
3653
|
return broadphaseCandidatePairs(bodies).length;
|
|
3427
3654
|
}
|
|
3655
|
+
function compoundChildDetailedHit(body, query, distance) {
|
|
3656
|
+
if (body.shape.type !== 'compound') {
|
|
3657
|
+
return undefined;
|
|
3658
|
+
}
|
|
3659
|
+
let bestChildIndex;
|
|
3660
|
+
let bestNormal;
|
|
3661
|
+
let bestDistDiff = Infinity;
|
|
3662
|
+
for (let index = 0; index < body.shape.children.length; index += 1) {
|
|
3663
|
+
const child = body.shape.children[index];
|
|
3664
|
+
const childBody = {
|
|
3665
|
+
...body,
|
|
3666
|
+
x: (body.x ?? 0) + (child.offset?.x ?? 0),
|
|
3667
|
+
y: (body.y ?? 0) + (child.offset?.y ?? 0),
|
|
3668
|
+
z: (body.z ?? 0) + (child.offset?.z ?? 0),
|
|
3669
|
+
shape: child.shape,
|
|
3670
|
+
rx: (body.rx ?? 0) + canonicalQuarterTurns(child.quarterTurns?.x ?? 0) / 4,
|
|
3671
|
+
ry: (body.ry ?? 0) + canonicalQuarterTurns(child.quarterTurns?.y ?? 0) / 4,
|
|
3672
|
+
rz: (body.rz ?? 0) + canonicalQuarterTurns(child.quarterTurns?.z ?? 0) / 4,
|
|
3673
|
+
};
|
|
3674
|
+
const childDist = 'dx' in query ? rayBodyDistance(childBody, query) : undefined;
|
|
3675
|
+
if (childDist !== undefined) {
|
|
3676
|
+
const diff = Math.abs(childDist - distance);
|
|
3677
|
+
if (diff < bestDistDiff) {
|
|
3678
|
+
bestDistDiff = diff;
|
|
3679
|
+
bestChildIndex = index;
|
|
3680
|
+
const center = quantizePoint({
|
|
3681
|
+
x: query.x + query.dx * childDist,
|
|
3682
|
+
y: query.y + query.dy * childDist,
|
|
3683
|
+
z: query.z + query.dz * childDist,
|
|
3684
|
+
});
|
|
3685
|
+
bestNormal = hitNormalForBody(childBody, center);
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
if (bestChildIndex !== undefined && bestNormal !== undefined) {
|
|
3690
|
+
return { childIndex: bestChildIndex, normal: bestNormal };
|
|
3691
|
+
}
|
|
3692
|
+
return undefined;
|
|
3693
|
+
}
|
|
3428
3694
|
function detailedHitForBody(body, query, distance, castRadius) {
|
|
3429
3695
|
const center = quantizePoint({
|
|
3430
3696
|
x: query.x + query.dx * distance,
|
|
3431
3697
|
y: query.y + query.dy * distance,
|
|
3432
3698
|
z: query.z + query.dz * distance,
|
|
3433
3699
|
});
|
|
3434
|
-
|
|
3700
|
+
let normal;
|
|
3701
|
+
let childIndex;
|
|
3702
|
+
if (body.shape.type === 'compound') {
|
|
3703
|
+
const compoundHit = compoundChildDetailedHit(body, query, distance);
|
|
3704
|
+
childIndex = compoundHit?.childIndex;
|
|
3705
|
+
normal = compoundHit?.normal ?? hitNormalForBody(body, center);
|
|
3706
|
+
}
|
|
3707
|
+
else {
|
|
3708
|
+
normal = hitNormalForBody(body, center);
|
|
3709
|
+
}
|
|
3435
3710
|
const point = quantizePoint({
|
|
3436
3711
|
x: center.x - normal.x * castRadius,
|
|
3437
3712
|
y: center.y - normal.y * castRadius,
|
|
@@ -3443,6 +3718,7 @@ function detailedHitForBody(body, query, distance, castRadius) {
|
|
|
3443
3718
|
point,
|
|
3444
3719
|
normal,
|
|
3445
3720
|
penetration: distance === 0 ? penetrationAtPoint(body, center, castRadius) : 0,
|
|
3721
|
+
childIndex,
|
|
3446
3722
|
};
|
|
3447
3723
|
}
|
|
3448
3724
|
function hitNormalForBody(body, point) {
|
|
@@ -3453,6 +3729,24 @@ function hitNormalForBody(body, point) {
|
|
|
3453
3729
|
z: point.z - body.z,
|
|
3454
3730
|
});
|
|
3455
3731
|
}
|
|
3732
|
+
if (body.shape.type === 'capsule') {
|
|
3733
|
+
const halfHeight = body.shape.halfHeight;
|
|
3734
|
+
let localPoint = { x: point.x - body.x, y: point.y - body.y, z: point.z - body.z };
|
|
3735
|
+
if (body.orientation !== undefined) {
|
|
3736
|
+
localPoint = rotatePointByQuatInverse(body.orientation, localPoint);
|
|
3737
|
+
}
|
|
3738
|
+
const clampedY = Math.max(-halfHeight, Math.min(halfHeight, localPoint.y));
|
|
3739
|
+
const localDelta = {
|
|
3740
|
+
x: localPoint.x,
|
|
3741
|
+
y: localPoint.y - clampedY,
|
|
3742
|
+
z: localPoint.z,
|
|
3743
|
+
};
|
|
3744
|
+
const localNormal = normalizePoint(localDelta);
|
|
3745
|
+
if (body.orientation !== undefined) {
|
|
3746
|
+
return normalizePoint(rotatePointByQuat(body.orientation, localNormal));
|
|
3747
|
+
}
|
|
3748
|
+
return localNormal;
|
|
3749
|
+
}
|
|
3456
3750
|
const bounds = toBounds(body);
|
|
3457
3751
|
const candidates = [
|
|
3458
3752
|
{ normal: { x: -1, y: 0, z: 0 }, distance: Math.abs(point.x - bounds.minX), axis: 'x-' },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-inc/rundot-syncplay",
|
|
3
|
-
"version": "5.
|
|
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-mass.test.ts tests/physics3d-materials.test.ts tests/physics3d-mesh-onesided.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.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",
|