@irtio/runtime 3.1.1 → 4.0.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.
@@ -3,7 +3,7 @@ import {
3
3
  parseHibernationBlob,
4
4
  sameSchemaHash,
5
5
  writeHibernationBlob
6
- } from "./chunk-2L3RGWXM.js";
6
+ } from "./chunk-S4D472RL.js";
7
7
 
8
8
  // src/migrate.ts
9
9
  import { PRESENCE_COLLECTION, withBuiltins } from "@irtio/protocol";
@@ -578,12 +578,12 @@ import {
578
578
  SERVER_OWNER as SERVER_OWNER2,
579
579
  decodeFields,
580
580
  encodeFields,
581
- validateValue
581
+ validateValue as validateValue2
582
582
  } from "@irtio/schema";
583
583
  import { DenyError } from "@irtio/server";
584
584
 
585
585
  // src/core/ownership.ts
586
- import { SERVER_OWNER, defaultRecord } from "@irtio/schema";
586
+ import { SERVER_OWNER, cloneValue, defaultRecord, validateValue } from "@irtio/schema";
587
587
  var HOLD_ACTIONS = /* @__PURE__ */ new Set([
588
588
  "release",
589
589
  "nearest",
@@ -735,7 +735,7 @@ function nearestConnected(core, collection, id) {
735
735
  }
736
736
  return best;
737
737
  }
738
- function addPerPlayerRecords(core, clientId) {
738
+ function addPerPlayerRecords(core, clientId, seeds) {
739
739
  for (const c of core.ext.collections) {
740
740
  if (c.kind !== "entity" || !c.perPlayer) continue;
741
741
  const coll = plainEntity(core.plain, c.name);
@@ -746,7 +746,23 @@ function addPerPlayerRecords(core, clientId) {
746
746
  continue;
747
747
  }
748
748
  try {
749
- trackedEntity(core, c.name).add(clientId, defaultRecord(c), { owner: clientId });
749
+ const record = defaultRecord(c);
750
+ const seed = seeds?.get(c.name);
751
+ if (seed && c.persist) {
752
+ for (const field of c.persist) {
753
+ const value = seed[field];
754
+ if (value === void 0) continue;
755
+ const desc = c.fields[c.fieldIndex.get(field) ?? -1];
756
+ if (!desc) continue;
757
+ const err = validateValue(desc.type, value, `${c.name}.${field}`);
758
+ if (err) {
759
+ core.log("warn", `persisted ${c.name}.${field} for ${clientId} dropped: ${err}`);
760
+ continue;
761
+ }
762
+ record[field] = cloneValue(value);
763
+ }
764
+ }
765
+ trackedEntity(core, c.name).add(clientId, record, { owner: clientId });
750
766
  } catch (err) {
751
767
  core.log("error", `perPlayer add on ${c.name} failed for ${clientId}:`, err);
752
768
  }
@@ -942,7 +958,7 @@ function handleCall(core, clientId, payload) {
942
958
  return true;
943
959
  }
944
960
  for (const f of desc.params) {
945
- const problem = validateValue(f.type, params[f.name], f.name);
961
+ const problem = validateValue2(f.type, params[f.name], f.name);
946
962
  if (problem) {
947
963
  traceEarly?.(errorText("E_RPC_BAD_PARAMS", problem));
948
964
  sendReply(core, clientId, call.reqId, null, errorText("E_RPC_BAD_PARAMS", problem));
@@ -1353,7 +1369,7 @@ function rejectAllHostCalls(core, reason) {
1353
1369
  // src/core/writes.ts
1354
1370
  import {
1355
1371
  SERVER_OWNER as SERVER_OWNER3,
1356
- cloneValue,
1372
+ cloneValue as cloneValue2,
1357
1373
  decodeDelta,
1358
1374
  defaultValue,
1359
1375
  encodeDelta as encodeDelta2,
@@ -1407,7 +1423,7 @@ function applyMaskedPatch(fields, target, patch, mask) {
1407
1423
  continue;
1408
1424
  }
1409
1425
  }
1410
- target[f.name] = cloneValue(value);
1426
+ target[f.name] = cloneValue2(value);
1411
1427
  }
1412
1428
  }
1413
1429
  function assignChanged(desc, target, key, prev, next) {
@@ -1532,17 +1548,17 @@ function applyOp(core, clientId, c, op) {
1532
1548
  const fields = fieldList(c);
1533
1549
  const growth = updateGrowth(c, leafPaths(fields, op.mask));
1534
1550
  if (growth > 0 && !admitGrowth(core, clientId, growth)) return;
1535
- const prev = cloneValue(current);
1536
- const next = cloneValue(current);
1551
+ const prev = cloneValue2(current);
1552
+ const next = cloneValue2(current);
1537
1553
  applyMaskedPatch(fields, next, op.patch, op.mask);
1538
- const requested = cloneValue(next);
1554
+ const requested = cloneValue2(next);
1539
1555
  if (c.physics || c.serverFields) {
1540
1556
  const refused2 = [];
1541
1557
  for (const leaf of leafPaths(fields, op.mask)) {
1542
1558
  const field = leaf.names[0];
1543
1559
  const why = ownerMayNotWrite(c, field);
1544
1560
  if (why === void 0) continue;
1545
- next[field] = cloneValue(prev[field]);
1561
+ next[field] = cloneValue2(prev[field]);
1546
1562
  refused2.push(why);
1547
1563
  }
1548
1564
  if (refused2.length > 0) {
@@ -1580,7 +1596,7 @@ function applyOp(core, clientId, c, op) {
1580
1596
  map = /* @__PURE__ */ new Map();
1581
1597
  entry.accepted.set(key, map);
1582
1598
  }
1583
- for (const leaf of written) map.set(leafKey(leaf), cloneValue(valueAt(result, leaf.names)));
1599
+ for (const leaf of written) map.set(leafKey(leaf), cloneValue2(valueAt(result, leaf.names)));
1584
1600
  }
1585
1601
  const corrected = written.filter(
1586
1602
  (leaf) => !deepEqual(valueAt(result, leaf.names), valueAt(requested, leaf.names))
@@ -3774,7 +3790,7 @@ import {
3774
3790
  withBuiltins as withBuiltins2
3775
3791
  } from "@irtio/protocol";
3776
3792
  import {
3777
- cloneValue as cloneValue2,
3793
+ cloneValue as cloneValue3,
3778
3794
  createDirtySet as createDirtySet3,
3779
3795
  createState,
3780
3796
  decodeSnapshot as decodeSnapshot3,
@@ -6141,7 +6157,7 @@ function ownJoinCapture(plain, name, added, clientId) {
6141
6157
  for (const id of added) {
6142
6158
  const owner = coll.ownerOf(id);
6143
6159
  if (name === PRESENCE_COLLECTION ? id !== clientId : owner !== clientId) continue;
6144
- (mine ??= /* @__PURE__ */ new Map()).set(id, { value: cloneValue2(coll.get(id)), owner });
6160
+ (mine ??= /* @__PURE__ */ new Map()).set(id, { value: cloneValue3(coll.get(id)), owner });
6145
6161
  }
6146
6162
  return mine;
6147
6163
  }
@@ -6905,7 +6921,7 @@ var RoomCore = class _RoomCore {
6905
6921
  this.clients.set(clientId, entry);
6906
6922
  this.invalidateClients();
6907
6923
  reclaimHolds(this.internals, clientId, entry.playerId);
6908
- addPerPlayerRecords(this.internals, clientId);
6924
+ addPerPlayerRecords(this.internals, clientId, options.persisted);
6909
6925
  const onJoin = this.definition.config.onJoin;
6910
6926
  if (onJoin) {
6911
6927
  const ctx = this.ctxFor(clientId, reconnecting);
@@ -6928,7 +6944,7 @@ var RoomCore = class _RoomCore {
6928
6944
  const captured = mine ?? /* @__PURE__ */ new Map();
6929
6945
  for (const id of cd.added) {
6930
6946
  if (!visible.has(id) || captured.has(id)) continue;
6931
- captured.set(id, { value: cloneValue2(coll.get(id)), owner: coll.ownerOf(id) });
6947
+ captured.set(id, { value: cloneValue3(coll.get(id)), owner: coll.ownerOf(id) });
6932
6948
  }
6933
6949
  if (captured.size > 0) pending.set(name2, captured);
6934
6950
  } else if (mine) pending.set(name2, mine);
@@ -6969,6 +6985,30 @@ var RoomCore = class _RoomCore {
6969
6985
  this.invalidateClients();
6970
6986
  this.eventFlush();
6971
6987
  }
6988
+ // ---- M8 proposal 13: identity-keyed player persistence ----
6989
+ /**
6990
+ * The current values of every `persist` field this client's `perPlayer` records hold, or
6991
+ * `undefined` when the schema declares none and when the client has no records.
6992
+ *
6993
+ * Read by the relay host just before `leave`, which is the last moment the records exist: the
6994
+ * declared leave rules remove a `perPlayer` record.
6995
+ */
6996
+ persistedFieldsOf(clientId) {
6997
+ let out;
6998
+ for (const c of this.ext.collections) {
6999
+ if (c.kind !== "entity" || !c.perPlayer || !c.persist || c.persist.length === 0) continue;
7000
+ const record = plainEntity(this.plain, c.name).get(clientId);
7001
+ if (!record) continue;
7002
+ const picked = {};
7003
+ for (const field of c.persist) {
7004
+ const value = record[field];
7005
+ if (value !== void 0) picked[field] = cloneValue3(value);
7006
+ }
7007
+ if (Object.keys(picked).length > 0) (out ??= /* @__PURE__ */ new Map()).set(c.name, picked);
7008
+ }
7009
+ return out;
7010
+ }
7011
+ // ---- end M8 proposal 13 ----
6972
7012
  markDisconnected(clientId) {
6973
7013
  const entry = this.clients.get(clientId);
6974
7014
  if (!entry) {
@@ -552,6 +552,12 @@ interface JoinOptions {
552
552
  * therefore the only thing `room.ban` can key a cooldown on honestly.
553
553
  */
554
554
  readonly subject?: string;
555
+ /**
556
+ * Seed values for this client's fresh `perPlayer` records, from the relay host's persistence
557
+ * blob: collection name → partial field values. Applied only where a new record is created; a
558
+ * reclaimed or reconnected record keeps what it has.
559
+ */
560
+ readonly persisted?: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
555
561
  }
556
562
  interface JoinResult {
557
563
  readonly tick: number;
@@ -657,6 +663,13 @@ interface RoomCoreApi<S extends AnySchema = AnySchema> {
657
663
  leave(clientId: string, reason: LeaveReason): void;
658
664
  /** Grace window opened by the host: presence `connected = false`; frames are no longer sent. */
659
665
  markDisconnected(clientId: string): void;
666
+ /**
667
+ * M8 proposal 13: the current values of every `persist` field this client's `perPlayer` records
668
+ * hold, or `undefined` when the schema declares none and when the client has no records.
669
+ *
670
+ * Read by the relay host just before `leave`, to write the player's persistence blob.
671
+ */
672
+ persistedFieldsOf(clientId: string): ReadonlyMap<string, Record<string, unknown>> | undefined;
660
673
  /** One inbound protocol frame (`WRITE` | `CALL` | `REPLY` | `MSG`). Anything else → host.kick(E_BAD_FRAME). */
661
674
  receive(clientId: string, frame: Uint8Array): void;
662
675
  /** Full state + tick + rng for hibernation. Runs `onSleep`. Clears timers. */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { A as AdmissionError, D as DEFAULT_RECORDS_PER_COLLECTION, a as DEFAULT_TIMELINE_MAX_RECORDS, b as DEFAULT_TIMELINE_MAX_TICKS, E as EVENT_RING_SIZE, H as HOST_CALL_TIMEOUT_MS, c as HostCall, d as HostCallResult, J as JoinOptions, e as JoinResult, L as LogLevel, P as PHYSICS_STEP_EMA_ALPHA, R as RELAY_RECORDS_PER_COLLECTION, f as RELAY_STATE_BYTES, g as RELAY_WRITES_PER_SECOND, h as RELAY_WRITE_CAPS, i as RPC_TRACE_SIZE, j as RPC_TRACE_SUMMARY_MAX, k as RoomCoreApi, l as RoomCoreOptions, m as RoomEvent, n as RoomEventKind, o as RoomFullError, p as RoomHost, q as RoomInspection, r as RoomStats, s as RpcOutcome, t as RpcTraceDump, u as RpcTraceEntry, v as RpcTraceRing, S as StampLag, T as TimelineDump, w as TimelineFrame, x as TimelineRecorder, y as TimelineRecorderOptions, W as WriteCaps, z as inspectState, B as summarizeRpcResult } from './contract-BoCNAPZT.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-CGbiPxi3.js';
1
+ export { A as AdmissionError, D as DEFAULT_RECORDS_PER_COLLECTION, a as DEFAULT_TIMELINE_MAX_RECORDS, b as DEFAULT_TIMELINE_MAX_TICKS, E as EVENT_RING_SIZE, H as HOST_CALL_TIMEOUT_MS, c as HostCall, d as HostCallResult, J as JoinOptions, e as JoinResult, L as LogLevel, P as PHYSICS_STEP_EMA_ALPHA, R as RELAY_RECORDS_PER_COLLECTION, f as RELAY_STATE_BYTES, g as RELAY_WRITES_PER_SECOND, h as RELAY_WRITE_CAPS, i as RPC_TRACE_SIZE, j as RPC_TRACE_SUMMARY_MAX, k as RoomCoreApi, l as RoomCoreOptions, m as RoomEvent, n as RoomEventKind, o as RoomFullError, p as RoomHost, q as RoomInspection, r as RoomStats, s as RpcOutcome, t as RpcTraceDump, u as RpcTraceEntry, v as RpcTraceRing, S as StampLag, T as TimelineDump, w as TimelineFrame, x as TimelineRecorder, y as TimelineRecorderOptions, W as WriteCaps, z as inspectState, B as summarizeRpcResult } from './contract-CpBkqkn7.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-B9h9dc4e.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-XPRLQCNF.js";
5
+ } from "./chunk-G2XKCXRO.js";
6
6
  import {
7
7
  AdmissionError,
8
8
  CRASH_AFTER_THROWS,
@@ -58,7 +58,7 @@ import {
58
58
  visibleNames,
59
59
  visibleTo,
60
60
  writeHibernationBlob
61
- } from "./chunk-2L3RGWXM.js";
61
+ } from "./chunk-S4D472RL.js";
62
62
  export {
63
63
  AdmissionError,
64
64
  CRASH_AFTER_THROWS,
@@ -1,7 +1,7 @@
1
1
  import { PlatformNotice, AttributeOptions, ProfileSnapshot } from '@irtio/protocol';
2
2
  import { DirtySet, AnySchema, PlainState, Tracked, State } from '@irtio/schema';
3
3
  import { RoomDefinition, RoomMode, Room, RewindView, Ctx, MatterModule, MatterEngine, MatterBody, RapierModule, RapierWorld, RapierRigidBody, Rapier2dModule, Rapier2dWorld, Rapier2dRigidBody, ResolvedRoomConfig, LeaveReason } from '@irtio/server';
4
- import { p as RoomHost, r as RoomStats, u as RpcTraceEntry, L as LogLevel, k as RoomCoreApi, l as RoomCoreOptions, n as RoomEventKind, y as TimelineRecorderOptions, T as TimelineDump, t as RpcTraceDump, q as RoomInspection, J as JoinOptions, e as JoinResult, d as HostCallResult } from './contract-BoCNAPZT.js';
4
+ import { p as RoomHost, r as RoomStats, u as RpcTraceEntry, L as LogLevel, k as RoomCoreApi, l as RoomCoreOptions, n as RoomEventKind, y as TimelineRecorderOptions, T as TimelineDump, t as RpcTraceDump, q as RoomInspection, J as JoinOptions, e as JoinResult, d as HostCallResult } from './contract-CpBkqkn7.js';
5
5
 
6
6
  declare class Mulberry32 {
7
7
  /** Current internal state (u32). Survives hibernation. */
@@ -1152,6 +1152,14 @@ declare class RoomCore<S extends AnySchema = AnySchema> implements RoomCoreApi<S
1152
1152
  /** Event mode only: presence/lifecycle changes are their own event. No-op in tick mode. */
1153
1153
  private eventFlush;
1154
1154
  leave(clientId: string, reason: LeaveReason): void;
1155
+ /**
1156
+ * The current values of every `persist` field this client's `perPlayer` records hold, or
1157
+ * `undefined` when the schema declares none and when the client has no records.
1158
+ *
1159
+ * Read by the relay host just before `leave`, which is the last moment the records exist: the
1160
+ * declared leave rules remove a `perPlayer` record.
1161
+ */
1162
+ persistedFieldsOf(clientId: string): ReadonlyMap<string, Record<string, unknown>> | undefined;
1155
1163
  markDisconnected(clientId: string): void;
1156
1164
  ctxFor(clientId: string, reconnecting?: boolean): Ctx;
1157
1165
  /**
@@ -1,8 +1,8 @@
1
- import { R as RoomCore } from '../room-CGbiPxi3.js';
2
- export { m as initMatter, n as initPhysics, o as initRapier2d } from '../room-CGbiPxi3.js';
1
+ import { R as RoomCore } from '../room-B9h9dc4e.js';
2
+ export { m as initMatter, n as initPhysics, o as initRapier2d } from '../room-B9h9dc4e.js';
3
3
  import { ErrorCodeName, FrameType } from '@irtio/protocol';
4
4
  import { NpcConfig, LeaveReason, Room, RoomDefinition } from '@irtio/server';
5
- import { p as RoomHost, L as LogLevel, k as RoomCoreApi, c as HostCall, d as HostCallResult, W as WriteCaps, r as RoomStats } from '../contract-BoCNAPZT.js';
5
+ import { p as RoomHost, L as LogLevel, k as RoomCoreApi, c as HostCall, d as HostCallResult, W as WriteCaps, r as RoomStats } from '../contract-CpBkqkn7.js';
6
6
  import { AnySchema, PlainState, EntityCollection, State } from '@irtio/schema';
7
7
 
8
8
  /**
@@ -20,6 +20,14 @@ declare class FakeClock {
20
20
  clearTimeout(handle: unknown): void;
21
21
  /** Number of timers still armed (a room that is ticking always has at least one). */
22
22
  get pending(): number;
23
+ /**
24
+ * The `at` of the earliest armed timer, or `undefined` when nothing is armed. Read-only: it
25
+ * changes nothing. It exists for callers that need to advance to the next timer rather than
26
+ * over it — `testRoom`'s `t.run(ms)` uses it to hop timer by timer, so a script parked on an
27
+ * `await` (whose continuation only runs once `advance` has returned and microtasks drain) can
28
+ * arm its next timer and keep going inside a single long run.
29
+ */
30
+ nextDueAt(): number | undefined;
23
31
  /**
24
32
  * Advances to `time + ms`, firing every timer that comes due in order (earliest `at` first,
25
33
  * ties broken by creation order). A timer that arms another timer inside the window fires too.
@@ -361,6 +369,11 @@ interface JoinSpec {
361
369
  * `onAdmit` that requires identity needs to be tested against.
362
370
  */
363
371
  readonly subject?: string;
372
+ /**
373
+ * The persistence blob this join arrives with: collection name → persisted field values. What
374
+ * the relay host reads from the store for an identified player, without a store or a socket.
375
+ */
376
+ readonly persisted?: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
364
377
  }
365
378
  interface UntilOptions {
366
379
  /** Default 1000. */
@@ -5,7 +5,7 @@ import {
5
5
  initPhysics,
6
6
  initRapier2d,
7
7
  visibleNames
8
- } from "../chunk-2L3RGWXM.js";
8
+ } from "../chunk-S4D472RL.js";
9
9
 
10
10
  // src/test/clock.ts
11
11
  var FakeClock = class {
@@ -28,6 +28,22 @@ var FakeClock = class {
28
28
  get pending() {
29
29
  return this.timers.size;
30
30
  }
31
+ /**
32
+ * The `at` of the earliest armed timer, or `undefined` when nothing is armed. Read-only: it
33
+ * changes nothing. It exists for callers that need to advance to the next timer rather than
34
+ * over it — `testRoom`'s `t.run(ms)` uses it to hop timer by timer, so a script parked on an
35
+ * `await` (whose continuation only runs once `advance` has returned and microtasks drain) can
36
+ * arm its next timer and keep going inside a single long run.
37
+ */
38
+ nextDueAt() {
39
+ let earliest;
40
+ for (const t of this.timers.values()) {
41
+ if (!earliest || t.at < earliest.at || t.at === earliest.at && t.id < earliest.id) {
42
+ earliest = t;
43
+ }
44
+ }
45
+ return earliest?.at;
46
+ }
31
47
  /**
32
48
  * Advances to `time + ms`, firing every timer that comes due in order (earliest `at` first,
33
49
  * ties broken by creation order). A timer that arms another timer inside the window fires too.
@@ -966,8 +982,11 @@ var Harness = class {
966
982
  ...spec.playerId !== void 0 ? { playerId: spec.playerId } : {},
967
983
  // ---- end M6 lane K ----
968
984
  // ---- M8 lane 5: moderation ----
969
- ...spec.subject !== void 0 ? { subject: spec.subject } : {}
985
+ ...spec.subject !== void 0 ? { subject: spec.subject } : {},
970
986
  // ---- end M8 lane 5 ----
987
+ // ---- M8 proposal 13 ----
988
+ ...spec.persisted !== void 0 ? { persisted: spec.persisted } : {}
989
+ // ---- end M8 proposal 13 ----
971
990
  };
972
991
  const client = new FakeClientImpl(this.bridge, id, options);
973
992
  this.byId.set(id, client);
@@ -1,4 +1,4 @@
1
- import { L as LogLevel, t as RpcTraceDump, T as TimelineDump, r as RoomStats, c as HostCall, d as HostCallResult, k as RoomCoreApi, p as RoomHost } from '../contract-BoCNAPZT.js';
1
+ import { L as LogLevel, t as RpcTraceDump, T as TimelineDump, r as RoomStats, c as HostCall, d as HostCallResult, k as RoomCoreApi, p as RoomHost } from '../contract-CpBkqkn7.js';
2
2
  import { ErrorCodeName, ProfileSnapshot, PlatformNotice } from '@irtio/protocol';
3
3
  import { NpcConfig, LeaveReason } from '@irtio/server';
4
4
  import '@irtio/schema';
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  migrateSnapshot
3
- } from "../chunk-XPRLQCNF.js";
3
+ } from "../chunk-G2XKCXRO.js";
4
4
  import {
5
5
  AdmissionError,
6
6
  RoomCore,
@@ -10,7 +10,7 @@ import {
10
10
  initRapier2d,
11
11
  onFirstRapierStep,
12
12
  rapierHasStepped
13
- } from "../chunk-2L3RGWXM.js";
13
+ } from "../chunk-S4D472RL.js";
14
14
 
15
15
  // src/worker/index.ts
16
16
  import { getHeapStatistics } from "v8";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@irtio/runtime",
3
- "version": "3.1.1",
3
+ "version": "4.0.0",
4
4
  "description": "irtio room runtime: RoomCore, worker_threads host, in-process test harness",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,9 +36,9 @@
36
36
  "@dimforge/rapier2d-compat": "0.20.0",
37
37
  "@dimforge/rapier3d-compat": "0.20.0",
38
38
  "matter-js": "0.20.0",
39
- "@irtio/protocol": "3.1.1",
40
- "@irtio/schema": "3.1.1",
41
- "@irtio/server": "3.1.1"
39
+ "@irtio/protocol": "^4.0.0",
40
+ "@irtio/schema": "^4.0.0",
41
+ "@irtio/server": "^4.0.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/matter-js": "0.20.2"