@irtio/runtime 0.9.0 → 0.10.1
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/{chunk-ADZZEVJU.js → chunk-EENJ37KK.js} +195 -34
- package/dist/{chunk-SBDZ45JG.js → chunk-WNAEE4EP.js} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/{room-C4RZJ2KO.d.ts → room-Db3iPBKM.d.ts} +4 -4
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +1 -1
- package/dist/worker/index.js +2 -2
- package/package.json +4 -4
|
@@ -1079,7 +1079,8 @@ var MatterRuntime = class {
|
|
|
1079
1079
|
const plainColl = plainEntity(this.core.plain, desc.name);
|
|
1080
1080
|
for (const id of plainColl.ids()) {
|
|
1081
1081
|
const attached = this.bodies.get(bodyKey(desc.name, id));
|
|
1082
|
-
if (attached)
|
|
1082
|
+
if (attached)
|
|
1083
|
+
fn(desc.name, id, attached.body, plainColl.get(id));
|
|
1083
1084
|
}
|
|
1084
1085
|
}
|
|
1085
1086
|
}
|
|
@@ -1534,7 +1535,7 @@ var PhysicsRuntime = class {
|
|
|
1534
1535
|
const plainColl = plainEntity(this.core.plain, desc.name);
|
|
1535
1536
|
for (const id of plainColl.ids()) {
|
|
1536
1537
|
const body = this.bodies.get(bodyKey2(desc.name, id));
|
|
1537
|
-
if (body) fn(desc.name, id, body);
|
|
1538
|
+
if (body) fn(desc.name, id, body, plainColl.get(id));
|
|
1538
1539
|
}
|
|
1539
1540
|
}
|
|
1540
1541
|
}
|
|
@@ -1939,7 +1940,7 @@ var Rapier2dRuntime = class {
|
|
|
1939
1940
|
const plainColl = plainEntity(this.core.plain, desc.name);
|
|
1940
1941
|
for (const id of plainColl.ids()) {
|
|
1941
1942
|
const body = this.bodies.get(bodyKey3(desc.name, id));
|
|
1942
|
-
if (body) fn(desc.name, id, body);
|
|
1943
|
+
if (body) fn(desc.name, id, body, plainColl.get(id));
|
|
1943
1944
|
}
|
|
1944
1945
|
}
|
|
1945
1946
|
}
|
|
@@ -2456,23 +2457,45 @@ import {
|
|
|
2456
2457
|
|
|
2457
2458
|
// src/core/history.ts
|
|
2458
2459
|
var HISTORY_MAX_TICKS = 240;
|
|
2460
|
+
var HISTORY_MAX_CHANNELS = 8;
|
|
2459
2461
|
var STRIDE = 13;
|
|
2460
2462
|
function emptyPose() {
|
|
2461
2463
|
return { x: 0, y: 0, z: 0, qx: 0, qy: 0, qz: 0, qw: 1, vx: 0, vy: 0, vz: 0, wx: 0, wy: 0, wz: 0 };
|
|
2462
2464
|
}
|
|
2463
2465
|
function newEntry() {
|
|
2464
|
-
return {
|
|
2466
|
+
return {
|
|
2467
|
+
tick: -1,
|
|
2468
|
+
count: 0,
|
|
2469
|
+
collections: [],
|
|
2470
|
+
ids: [],
|
|
2471
|
+
values: new Float64Array(0),
|
|
2472
|
+
channels: new Float32Array(0)
|
|
2473
|
+
};
|
|
2465
2474
|
}
|
|
2466
2475
|
var PoseHistory = class {
|
|
2467
2476
|
depth;
|
|
2477
|
+
/** Declared channels by collection. Empty in a room that declared none. */
|
|
2478
|
+
channels;
|
|
2479
|
+
/**
|
|
2480
|
+
* Slots per body in `entry.channels`: the widest declared count, so a body's channels sit at
|
|
2481
|
+
* `i * channelStride` under the same body index the pose uses. `0` when nothing is declared, and
|
|
2482
|
+
* that zero is what short-circuits the whole channel path per body.
|
|
2483
|
+
*/
|
|
2484
|
+
channelStride;
|
|
2468
2485
|
entries = [];
|
|
2469
2486
|
/** Index of the newest entry in `entries`, or -1 when nothing has been captured. */
|
|
2470
2487
|
head = -1;
|
|
2471
2488
|
size = 0;
|
|
2472
2489
|
/** Reused across every body of every capture: the capture path allocates nothing per body. */
|
|
2473
2490
|
scratchPose = emptyPose();
|
|
2474
|
-
|
|
2491
|
+
/** Collections whose `read` hook has already thrown, so the log is one line, not one per tick. */
|
|
2492
|
+
hookFailed = /* @__PURE__ */ new Set();
|
|
2493
|
+
constructor(depth, channels) {
|
|
2475
2494
|
this.depth = Math.max(1, Math.min(HISTORY_MAX_TICKS, Math.floor(depth)));
|
|
2495
|
+
this.channels = channels ?? /* @__PURE__ */ new Map();
|
|
2496
|
+
let stride = 0;
|
|
2497
|
+
for (const spec of this.channels.values()) stride = Math.max(stride, spec.count);
|
|
2498
|
+
this.channelStride = stride;
|
|
2476
2499
|
for (let i = 0; i < this.depth; i++) this.entries.push(newEntry());
|
|
2477
2500
|
}
|
|
2478
2501
|
get length() {
|
|
@@ -2502,14 +2525,14 @@ var PoseHistory = class {
|
|
|
2502
2525
|
entry.count = 0;
|
|
2503
2526
|
const pose = this.scratchPose;
|
|
2504
2527
|
const kind = physics.engineKind;
|
|
2505
|
-
physics.eachTrackedBody((collection, id, body) => {
|
|
2528
|
+
physics.eachTrackedBody((collection, id, body, instance) => {
|
|
2506
2529
|
if (kind === "rapier3d") readRapierPose(body, pose);
|
|
2507
2530
|
else if (kind === "rapier2d") readRapier2dPose(body, pose);
|
|
2508
2531
|
else readMatterPose(body, pose);
|
|
2509
|
-
this.push(entry, collection, id, pose);
|
|
2532
|
+
this.push(entry, collection, id, pose, instance);
|
|
2510
2533
|
});
|
|
2511
2534
|
}
|
|
2512
|
-
push(entry, collection, id, pose) {
|
|
2535
|
+
push(entry, collection, id, pose, instance) {
|
|
2513
2536
|
const i = entry.count;
|
|
2514
2537
|
const need = (i + 1) * STRIDE;
|
|
2515
2538
|
if (entry.values.length < need) {
|
|
@@ -2517,6 +2540,34 @@ var PoseHistory = class {
|
|
|
2517
2540
|
grown.set(entry.values);
|
|
2518
2541
|
entry.values = grown;
|
|
2519
2542
|
}
|
|
2543
|
+
const stride = this.channelStride;
|
|
2544
|
+
if (stride > 0) {
|
|
2545
|
+
const want = (i + 1) * stride;
|
|
2546
|
+
if (entry.channels.length < want) {
|
|
2547
|
+
const grown = new Float32Array(Math.max(want, entry.channels.length * 2, stride * 8));
|
|
2548
|
+
grown.set(entry.channels);
|
|
2549
|
+
entry.channels = grown;
|
|
2550
|
+
}
|
|
2551
|
+
const o2 = i * stride;
|
|
2552
|
+
entry.channels.fill(0, o2, o2 + stride);
|
|
2553
|
+
const spec = this.channels.get(collection);
|
|
2554
|
+
if (spec) {
|
|
2555
|
+
const scratch = spec.scratch;
|
|
2556
|
+
scratch.fill(0);
|
|
2557
|
+
try {
|
|
2558
|
+
spec.read(instance, scratch);
|
|
2559
|
+
entry.channels.set(scratch, o2);
|
|
2560
|
+
} catch (err) {
|
|
2561
|
+
if (!this.hookFailed.has(collection)) {
|
|
2562
|
+
this.hookFailed.add(collection);
|
|
2563
|
+
console.error(
|
|
2564
|
+
`physics.history.channels.${collection}.read threw; that body's channels are zeros`,
|
|
2565
|
+
err
|
|
2566
|
+
);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2520
2571
|
entry.collections[i] = collection;
|
|
2521
2572
|
entry.ids[i] = id;
|
|
2522
2573
|
const v = entry.values;
|
|
@@ -2587,6 +2638,10 @@ function poseAt(entry, index, into) {
|
|
|
2587
2638
|
into.wy = v[o + 11];
|
|
2588
2639
|
into.wz = v[o + 12];
|
|
2589
2640
|
}
|
|
2641
|
+
function channelsAt(entry, index, stride, count) {
|
|
2642
|
+
const o = index * stride;
|
|
2643
|
+
return entry.channels.subarray(o, o + count);
|
|
2644
|
+
}
|
|
2590
2645
|
function readRapierPose(body, into) {
|
|
2591
2646
|
const t = body.translation();
|
|
2592
2647
|
const r = body.rotation();
|
|
@@ -2639,10 +2694,20 @@ function readMatterPose(body, into) {
|
|
|
2639
2694
|
into.wy = 0;
|
|
2640
2695
|
into.wz = body.angularVelocity;
|
|
2641
2696
|
}
|
|
2642
|
-
function
|
|
2697
|
+
function historyOf(config) {
|
|
2643
2698
|
const declared = config?.history;
|
|
2644
|
-
|
|
2645
|
-
|
|
2699
|
+
const raw = typeof declared === "number" ? declared : typeof declared === "object" && declared !== null ? declared.depth : void 0;
|
|
2700
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || raw <= 0) return void 0;
|
|
2701
|
+
const depth = Math.min(HISTORY_MAX_TICKS, Math.floor(raw));
|
|
2702
|
+
const channels = /* @__PURE__ */ new Map();
|
|
2703
|
+
if (typeof declared === "object" && declared !== null) {
|
|
2704
|
+
const spec = declared.channels;
|
|
2705
|
+
for (const [name, s] of Object.entries(spec ?? {})) {
|
|
2706
|
+
const count = Math.min(HISTORY_MAX_CHANNELS, Math.floor(s.count));
|
|
2707
|
+
channels.set(name, { count, read: s.read, scratch: new Float32Array(count) });
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
return { depth, channels };
|
|
2646
2711
|
}
|
|
2647
2712
|
function keyOf(collection, id) {
|
|
2648
2713
|
return `${collection} ${id}`;
|
|
@@ -2650,6 +2715,9 @@ function keyOf(collection, id) {
|
|
|
2650
2715
|
function angleOf(qz, qw) {
|
|
2651
2716
|
return 2 * Math.atan2(qz, qw);
|
|
2652
2717
|
}
|
|
2718
|
+
function mixSignature(h, v) {
|
|
2719
|
+
return Math.imul(h ^ (Math.round(v * 1024) | 0), 2654435761);
|
|
2720
|
+
}
|
|
2653
2721
|
var BaseScratch = class {
|
|
2654
2722
|
constructor(physics, depth, tickNow) {
|
|
2655
2723
|
this.physics = physics;
|
|
@@ -2680,7 +2748,8 @@ var BaseScratch = class {
|
|
|
2680
2748
|
}
|
|
2681
2749
|
/**
|
|
2682
2750
|
* Brings the scratch's body set in step with the live world: a double for every live body that
|
|
2683
|
-
* has none, a rebuild for one whose collider
|
|
2751
|
+
* has none, a rebuild for one whose collider layout changed (count, handles, body-local
|
|
2752
|
+
* offsets, shape type or extents, sensor flags — see `signatureOf`), and a prune for one that
|
|
2684
2753
|
* has been gone longer than the history is deep and so can no longer appear in any entry.
|
|
2685
2754
|
*
|
|
2686
2755
|
* The prune is conservative rather than exact: `lastLive` only advances when a rewind happens,
|
|
@@ -2693,9 +2762,9 @@ var BaseScratch = class {
|
|
|
2693
2762
|
this.physics.eachTrackedBody((collection, id, body) => {
|
|
2694
2763
|
const key = keyOf(collection, id);
|
|
2695
2764
|
seen.add(key);
|
|
2696
|
-
const
|
|
2765
|
+
const signature = this.signatureOf(body);
|
|
2697
2766
|
const existing = this.bodies.get(key);
|
|
2698
|
-
if (existing && existing.
|
|
2767
|
+
if (existing && existing.signature === signature) {
|
|
2699
2768
|
existing.lastLive = now;
|
|
2700
2769
|
return;
|
|
2701
2770
|
}
|
|
@@ -2703,7 +2772,7 @@ var BaseScratch = class {
|
|
|
2703
2772
|
this.bodies.delete(key);
|
|
2704
2773
|
this.destroy(existing);
|
|
2705
2774
|
}
|
|
2706
|
-
const made = this.clone(collection, id, body,
|
|
2775
|
+
const made = this.clone(collection, id, body, signature);
|
|
2707
2776
|
if (!made) return;
|
|
2708
2777
|
made.lastLive = now;
|
|
2709
2778
|
this.bodies.set(key, made);
|
|
@@ -2744,16 +2813,46 @@ var RapierScratch = class extends BaseScratch {
|
|
|
2744
2813
|
this.world = new this.rapier.World({ x: 0, y: 0, z: 0 });
|
|
2745
2814
|
this.world.timestep = 0;
|
|
2746
2815
|
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2816
|
+
signatureOf(body) {
|
|
2817
|
+
const live = body;
|
|
2818
|
+
const n = live.numColliders();
|
|
2819
|
+
const origin = live.translation();
|
|
2820
|
+
const inv = qConj(live.rotation());
|
|
2821
|
+
let h = mixSignature(0, n);
|
|
2822
|
+
for (let i = 0; i < n; i++) {
|
|
2823
|
+
const c = live.collider(i);
|
|
2824
|
+
h = mixSignature(h, c.handle);
|
|
2825
|
+
h = mixSignature(h, c.isSensor() ? 1 : 0);
|
|
2826
|
+
const w = c.translation();
|
|
2827
|
+
const local = qRotate(inv, { x: w.x - origin.x, y: w.y - origin.y, z: w.z - origin.z });
|
|
2828
|
+
h = mixSignature(h, local.x);
|
|
2829
|
+
h = mixSignature(h, local.y);
|
|
2830
|
+
h = mixSignature(h, local.z);
|
|
2831
|
+
const r = qMul(inv, c.rotation());
|
|
2832
|
+
h = mixSignature(h, r.x);
|
|
2833
|
+
h = mixSignature(h, r.y);
|
|
2834
|
+
h = mixSignature(h, r.z);
|
|
2835
|
+
h = mixSignature(h, r.w);
|
|
2836
|
+
const s = c.shape;
|
|
2837
|
+
h = mixSignature(h, s.type);
|
|
2838
|
+
h = mixSignature(h, s.radius ?? 0);
|
|
2839
|
+
h = mixSignature(h, s.halfHeight ?? 0);
|
|
2840
|
+
if (s.halfExtents) {
|
|
2841
|
+
h = mixSignature(h, s.halfExtents.x);
|
|
2842
|
+
h = mixSignature(h, s.halfExtents.y);
|
|
2843
|
+
h = mixSignature(h, s.halfExtents.z);
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
return h;
|
|
2749
2847
|
}
|
|
2750
|
-
clone(collection, id, body,
|
|
2848
|
+
clone(collection, id, body, signature) {
|
|
2751
2849
|
const live = body;
|
|
2752
2850
|
this.trackedLive.add(live.handle);
|
|
2753
2851
|
const made = this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed());
|
|
2754
2852
|
const origin = live.translation();
|
|
2755
2853
|
const rot = live.rotation();
|
|
2756
2854
|
const inv = qConj(rot);
|
|
2855
|
+
const parts = live.numColliders();
|
|
2757
2856
|
for (let i = 0; i < parts; i++) {
|
|
2758
2857
|
const c = live.collider(i);
|
|
2759
2858
|
const desc = new this.rapier.ColliderDesc(c.shape);
|
|
@@ -2765,7 +2864,7 @@ var RapierScratch = class extends BaseScratch {
|
|
|
2765
2864
|
this.world.createCollider(desc, made);
|
|
2766
2865
|
}
|
|
2767
2866
|
this.owners.set(made.handle, { collection, id });
|
|
2768
|
-
return { collection, id, body: made,
|
|
2867
|
+
return { collection, id, body: made, signature, lastLive: -1 };
|
|
2769
2868
|
}
|
|
2770
2869
|
place(entry, pose) {
|
|
2771
2870
|
const b = entry.body;
|
|
@@ -2841,10 +2940,36 @@ var Rapier2dScratch = class extends BaseScratch {
|
|
|
2841
2940
|
this.world = new this.rapier.World({ x: 0, y: 0 });
|
|
2842
2941
|
this.world.timestep = 0;
|
|
2843
2942
|
}
|
|
2844
|
-
|
|
2845
|
-
|
|
2943
|
+
signatureOf(body) {
|
|
2944
|
+
const live = body;
|
|
2945
|
+
const n = live.numColliders();
|
|
2946
|
+
const origin = live.translation();
|
|
2947
|
+
const angle = live.rotation();
|
|
2948
|
+
const cos = Math.cos(-angle);
|
|
2949
|
+
const sin = Math.sin(-angle);
|
|
2950
|
+
let h = mixSignature(0, n);
|
|
2951
|
+
for (let i = 0; i < n; i++) {
|
|
2952
|
+
const c = live.collider(i);
|
|
2953
|
+
h = mixSignature(h, c.handle);
|
|
2954
|
+
h = mixSignature(h, c.isSensor() ? 1 : 0);
|
|
2955
|
+
const w = c.translation();
|
|
2956
|
+
const dx = w.x - origin.x;
|
|
2957
|
+
const dy = w.y - origin.y;
|
|
2958
|
+
h = mixSignature(h, dx * cos - dy * sin);
|
|
2959
|
+
h = mixSignature(h, dx * sin + dy * cos);
|
|
2960
|
+
h = mixSignature(h, c.rotation() - angle);
|
|
2961
|
+
const s = c.shape;
|
|
2962
|
+
h = mixSignature(h, s.type);
|
|
2963
|
+
h = mixSignature(h, s.radius ?? 0);
|
|
2964
|
+
h = mixSignature(h, s.halfHeight ?? 0);
|
|
2965
|
+
if (s.halfExtents) {
|
|
2966
|
+
h = mixSignature(h, s.halfExtents.x);
|
|
2967
|
+
h = mixSignature(h, s.halfExtents.y);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
return h;
|
|
2846
2971
|
}
|
|
2847
|
-
clone(collection, id, body,
|
|
2972
|
+
clone(collection, id, body, signature) {
|
|
2848
2973
|
const live = body;
|
|
2849
2974
|
this.trackedLive.add(live.handle);
|
|
2850
2975
|
const made = this.world.createRigidBody(this.rapier.RigidBodyDesc.fixed());
|
|
@@ -2852,6 +2977,7 @@ var Rapier2dScratch = class extends BaseScratch {
|
|
|
2852
2977
|
const angle = live.rotation();
|
|
2853
2978
|
const cos = Math.cos(-angle);
|
|
2854
2979
|
const sin = Math.sin(-angle);
|
|
2980
|
+
const parts = live.numColliders();
|
|
2855
2981
|
for (let i = 0; i < parts; i++) {
|
|
2856
2982
|
const c = live.collider(i);
|
|
2857
2983
|
const desc = new this.rapier.ColliderDesc(c.shape);
|
|
@@ -2864,7 +2990,7 @@ var Rapier2dScratch = class extends BaseScratch {
|
|
|
2864
2990
|
this.world.createCollider(desc, made);
|
|
2865
2991
|
}
|
|
2866
2992
|
this.owners.set(made.handle, { collection, id });
|
|
2867
|
-
return { collection, id, body: made,
|
|
2993
|
+
return { collection, id, body: made, signature, lastLive: -1 };
|
|
2868
2994
|
}
|
|
2869
2995
|
place(entry, pose) {
|
|
2870
2996
|
const b = entry.body;
|
|
@@ -2926,10 +3052,23 @@ var MatterScratch = class extends BaseScratch {
|
|
|
2926
3052
|
super(physics, depth, tickNow);
|
|
2927
3053
|
this.matter = physics.matter;
|
|
2928
3054
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
3055
|
+
signatureOf(body) {
|
|
3056
|
+
const live = body;
|
|
3057
|
+
const cos = Math.cos(-live.angle);
|
|
3058
|
+
const sin = Math.sin(-live.angle);
|
|
3059
|
+
let h = mixSignature(0, live.parts.length);
|
|
3060
|
+
for (const p of live.parts) {
|
|
3061
|
+
h = mixSignature(h, p.area);
|
|
3062
|
+
h = mixSignature(h, p.vertices.length);
|
|
3063
|
+
h = mixSignature(h, p.isSensor ? 1 : 0);
|
|
3064
|
+
const dx = p.position.x - live.position.x;
|
|
3065
|
+
const dy = p.position.y - live.position.y;
|
|
3066
|
+
h = mixSignature(h, dx * cos - dy * sin);
|
|
3067
|
+
h = mixSignature(h, dx * sin + dy * cos);
|
|
3068
|
+
}
|
|
3069
|
+
return h;
|
|
3070
|
+
}
|
|
3071
|
+
clone(collection, id, body, signature) {
|
|
2933
3072
|
const M = this.matter;
|
|
2934
3073
|
const live = body;
|
|
2935
3074
|
const made = live.parts.length > 1 ? M.Body.create({ parts: live.parts.slice(1).map((p) => this.clonePart(p, live.angle)) }) : this.clonePart(live, live.angle);
|
|
@@ -2937,7 +3076,7 @@ var MatterScratch = class extends BaseScratch {
|
|
|
2937
3076
|
made.angle = 0;
|
|
2938
3077
|
for (const p of made.parts) p.angle = 0;
|
|
2939
3078
|
this.owners.set(made, { collection, id });
|
|
2940
|
-
return { collection, id, body: made,
|
|
3079
|
+
return { collection, id, body: made, signature, lastLive: -1 };
|
|
2941
3080
|
}
|
|
2942
3081
|
/** One part, un-rotated by the parent's angle so the double starts at angle 0. */
|
|
2943
3082
|
clonePart(part, parentAngle) {
|
|
@@ -2992,8 +3131,8 @@ var RewindState = class {
|
|
|
2992
3131
|
history;
|
|
2993
3132
|
scratch;
|
|
2994
3133
|
inside = false;
|
|
2995
|
-
constructor(
|
|
2996
|
-
this.history = new PoseHistory(depth);
|
|
3134
|
+
constructor(setup) {
|
|
3135
|
+
this.history = new PoseHistory(setup.depth, setup.channels);
|
|
2997
3136
|
}
|
|
2998
3137
|
free() {
|
|
2999
3138
|
this.scratch?.free();
|
|
@@ -3012,7 +3151,29 @@ var RewindState = class {
|
|
|
3012
3151
|
);
|
|
3013
3152
|
}
|
|
3014
3153
|
this.scratch ??= physics.engineKind === "rapier3d" ? new RapierScratch(physics, this.history.depth, tickNow) : physics.engineKind === "rapier2d" ? new Rapier2dScratch(physics, this.history.depth, tickNow) : new MatterScratch(physics, this.history.depth, tickNow);
|
|
3015
|
-
const
|
|
3154
|
+
const engineView = this.scratch.view(
|
|
3155
|
+
resolved.entry,
|
|
3156
|
+
resolved.tick,
|
|
3157
|
+
requested,
|
|
3158
|
+
resolved.clamped
|
|
3159
|
+
);
|
|
3160
|
+
const entry = resolved.entry;
|
|
3161
|
+
const history = this.history;
|
|
3162
|
+
const view = {
|
|
3163
|
+
...engineView,
|
|
3164
|
+
// A linear scan of the entry rather than an index: an entry holds one room's tracked bodies,
|
|
3165
|
+
// and building a map per rewind would cost more than the scan it saved.
|
|
3166
|
+
channels: (collection, id) => {
|
|
3167
|
+
const spec = history.channels.get(collection);
|
|
3168
|
+
if (!spec) return void 0;
|
|
3169
|
+
for (let i = 0; i < entry.count; i++) {
|
|
3170
|
+
if (entry.collections[i] === collection && entry.ids[i] === id) {
|
|
3171
|
+
return channelsAt(entry, i, history.channelStride, spec.count);
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
return void 0;
|
|
3175
|
+
}
|
|
3176
|
+
};
|
|
3016
3177
|
this.inside = true;
|
|
3017
3178
|
try {
|
|
3018
3179
|
return fn(view);
|
|
@@ -3896,8 +4057,8 @@ var RoomCore = class _RoomCore {
|
|
|
3896
4057
|
this.loop = new Loop(self);
|
|
3897
4058
|
this.api = createRoomApi(self, options.publicUrl ?? DEFAULT_PUBLIC_URL);
|
|
3898
4059
|
this.physics = this.buildPhysics(restored);
|
|
3899
|
-
const
|
|
3900
|
-
this.rewindState =
|
|
4060
|
+
const historySetup = this.physics ? historyOf(definition.config.physics) : void 0;
|
|
4061
|
+
this.rewindState = historySetup === void 0 ? void 0 : new RewindState(historySetup);
|
|
3901
4062
|
this.subscribeDeclaredChannels();
|
|
3902
4063
|
if (restored) {
|
|
3903
4064
|
const onWake = definition.config.onWake;
|
|
@@ -3984,7 +4145,7 @@ var RoomCore = class _RoomCore {
|
|
|
3984
4145
|
const engine4 = loadedPhysics();
|
|
3985
4146
|
if (!engine4) {
|
|
3986
4147
|
throw new Error(
|
|
3987
|
-
"RoomCore: this room declares physics but the engine is not initialized \u2014 the host must `await initPhysics()` (from '@irtio/
|
|
4148
|
+
"RoomCore: this room declares physics but the engine is not initialized \u2014 the host must `await initPhysics()` (in tests: from '@irtio/testing') before constructing the room; handlers are synchronous, so the WASM cannot be loaded later"
|
|
3988
4149
|
);
|
|
3989
4150
|
}
|
|
3990
4151
|
let section;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { D as DEFAULT_TIMELINE_MAX_RECORDS, a as DEFAULT_TIMELINE_MAX_TICKS, E as EVENT_RING_SIZE, H as HOST_CALL_TIMEOUT_MS, b as HostCall, c as HostCallResult, J as JoinOptions, d as JoinResult, L as LogLevel, R as RoomCoreApi, e as RoomCoreOptions, f as RoomEvent, g as RoomEventKind, h as RoomFullError, i as RoomHost, j as RoomInspection, k as RoomStats, T as TimelineDump, l as TimelineFrame, m as TimelineRecorder, n as TimelineRecorderOptions, o as inspectState } from './contract-C5aqs49-.js';
|
|
2
|
-
export { C as CRASH_AFTER_THROWS, M as MAX_CATCHUP, a as MatterBodyRecord, b as MatterSection, c as Mulberry32, P as PhysicsEngineTag, d as PhysicsSection, R as RoomCore, e as decodeMatterBodies, f as decodeMatterSectionEnvelope, g as decodePhysicsSection, h as decodeRapier2dSectionEnvelope, i as encodeMatterBodies, j as encodeMatterSectionEnvelope, k as encodePhysicsSection, l as encodeRapier2dSectionEnvelope, m as initMatter, n as initPhysics, o as initRapier2d, p as loadedMatter, q as loadedPhysics, r as loadedRapier2d, s as physicsSectionEngine, t as resetMatterForTests, u as resetPhysicsForTests, v as resetRapier2dForTests } from './room-
|
|
2
|
+
export { C as CRASH_AFTER_THROWS, M as MAX_CATCHUP, a as MatterBodyRecord, b as MatterSection, c as Mulberry32, P as PhysicsEngineTag, d as PhysicsSection, R as RoomCore, e as decodeMatterBodies, f as decodeMatterSectionEnvelope, g as decodePhysicsSection, h as decodeRapier2dSectionEnvelope, i as encodeMatterBodies, j as encodeMatterSectionEnvelope, k as encodePhysicsSection, l as encodeRapier2dSectionEnvelope, m as initMatter, n as initPhysics, o as initRapier2d, p as loadedMatter, q as loadedPhysics, r as loadedRapier2d, s as physicsSectionEngine, t as resetMatterForTests, u as resetPhysicsForTests, v as resetRapier2dForTests } from './room-Db3iPBKM.js';
|
|
3
3
|
import { CollectionDesc, AnySchema, PlainState, DirtySet } from '@irtio/schema';
|
|
4
4
|
import '@irtio/protocol';
|
|
5
5
|
import '@irtio/server';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
fromMigrationState,
|
|
3
3
|
migrateSnapshot,
|
|
4
4
|
toMigrationState
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WNAEE4EP.js";
|
|
6
6
|
import {
|
|
7
7
|
CRASH_AFTER_THROWS,
|
|
8
8
|
DEFAULT_TIMELINE_MAX_RECORDS,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
visibleNames,
|
|
48
48
|
visibleTo,
|
|
49
49
|
writeHibernationBlob
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-EENJ37KK.js";
|
|
51
51
|
export {
|
|
52
52
|
CRASH_AFTER_THROWS,
|
|
53
53
|
DEFAULT_TIMELINE_MAX_RECORDS,
|
|
@@ -105,7 +105,7 @@ interface PhysicsApi {
|
|
|
105
105
|
* the only thing outside the engine runtimes that sees a live body other than through
|
|
106
106
|
* `bodyFor`, and it never hands out the map itself.
|
|
107
107
|
*/
|
|
108
|
-
eachTrackedBody(fn: (collection: string, id: string, body: unknown) => void): void;
|
|
108
|
+
eachTrackedBody(fn: (collection: string, id: string, body: unknown, instance: Record<string, unknown>) => void): void;
|
|
109
109
|
/** rapier3d and rapier2d: the engine namespace. `engineKind` says which module it is. */
|
|
110
110
|
readonly rapier: unknown;
|
|
111
111
|
/** rapier3d and rapier2d: the live `World`. */
|
|
@@ -363,7 +363,7 @@ declare class MatterRuntime {
|
|
|
363
363
|
* D72: every tracked body, in the order `sync()` walks them. The matter half of the same
|
|
364
364
|
* read-only accessor `PhysicsRuntime` carries; see its comment for what calls it and when.
|
|
365
365
|
*/
|
|
366
|
-
eachTrackedBody(fn: (collection: string, id: string, body: MatterBody) => void): void;
|
|
366
|
+
eachTrackedBody(fn: (collection: string, id: string, body: MatterBody, instance: Record<string, unknown>) => void): void;
|
|
367
367
|
private applyState;
|
|
368
368
|
private applyRecordToBody;
|
|
369
369
|
reconcile(): void;
|
|
@@ -533,7 +533,7 @@ declare class PhysicsRuntime {
|
|
|
533
533
|
* The pose history calls this once per tick and the rewind scratch calls it per rewind; a room
|
|
534
534
|
* that declares no `physics.history` never calls it at all.
|
|
535
535
|
*/
|
|
536
|
-
eachTrackedBody(fn: (collection: string, id: string, body: RapierRigidBody) => void): void;
|
|
536
|
+
eachTrackedBody(fn: (collection: string, id: string, body: RapierRigidBody, instance: Record<string, unknown>) => void): void;
|
|
537
537
|
private applyRecordToBody;
|
|
538
538
|
/**
|
|
539
539
|
* Creates bodies for new instances and destroys bodies whose instance is gone. Runs once per
|
|
@@ -650,7 +650,7 @@ declare class Rapier2dRuntime {
|
|
|
650
650
|
* D72: every tracked body, in the order `sync()` walks them (collection order, then instance
|
|
651
651
|
* order). The rapier2d third of the same read-only accessor the other two runtimes carry.
|
|
652
652
|
*/
|
|
653
|
-
eachTrackedBody(fn: (collection: string, id: string, body: Rapier2dRigidBody) => void): void;
|
|
653
|
+
eachTrackedBody(fn: (collection: string, id: string, body: Rapier2dRigidBody, instance: Record<string, unknown>) => void): void;
|
|
654
654
|
private applyRecordToBody;
|
|
655
655
|
/**
|
|
656
656
|
* Creates bodies for new instances and destroys bodies whose instance is gone. Runs once per
|
package/dist/test/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RoomCore } from '../room-
|
|
2
|
-
export { m as initMatter, n as initPhysics, o as initRapier2d } from '../room-
|
|
1
|
+
import { R as RoomCore } from '../room-Db3iPBKM.js';
|
|
2
|
+
export { m as initMatter, n as initPhysics, o as initRapier2d } from '../room-Db3iPBKM.js';
|
|
3
3
|
import { ErrorCodeName, FrameType } from '@irtio/protocol';
|
|
4
4
|
import { NpcConfig, LeaveReason, Room, RoomDefinition } from '@irtio/server';
|
|
5
5
|
import { i as RoomHost, L as LogLevel, R as RoomCoreApi, b as HostCall, c as HostCallResult, k as RoomStats } from '../contract-C5aqs49-.js';
|
package/dist/test/index.js
CHANGED
package/dist/worker/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
migrateSnapshot
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-WNAEE4EP.js";
|
|
4
4
|
import {
|
|
5
5
|
RoomCore,
|
|
6
6
|
RoomFullError,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
initRapier2d,
|
|
10
10
|
onFirstRapierStep,
|
|
11
11
|
rapierHasStepped
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-EENJ37KK.js";
|
|
13
13
|
|
|
14
14
|
// src/worker/index.ts
|
|
15
15
|
import { getHeapStatistics } from "v8";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@irtio/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "irtio room runtime: RoomCore, worker_threads host, in-process test harness",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@dimforge/rapier2d-compat": "0.20.0",
|
|
32
32
|
"@dimforge/rapier3d-compat": "0.20.0",
|
|
33
33
|
"matter-js": "0.20.0",
|
|
34
|
-
"@irtio/
|
|
35
|
-
"@irtio/
|
|
36
|
-
"@irtio/
|
|
34
|
+
"@irtio/protocol": "0.10.1",
|
|
35
|
+
"@irtio/schema": "0.10.1",
|
|
36
|
+
"@irtio/server": "0.10.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/matter-js": "0.20.2"
|