@irtio/runtime 3.1.0 → 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.
- package/dist/{chunk-3BCTP4YS.js → chunk-G2XKCXRO.js} +1 -1
- package/dist/{chunk-NPRIYYNM.js → chunk-S4D472RL.js} +59 -17
- package/dist/{contract-BoCNAPZT.d.ts → contract-CpBkqkn7.d.ts} +13 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{room-CGbiPxi3.d.ts → room-B9h9dc4e.d.ts} +9 -1
- package/dist/test/index.d.ts +16 -3
- package/dist/test/index.js +21 -2
- package/dist/worker/index.d.ts +1 -1
- package/dist/worker/index.js +2 -2
- package/package.json +4 -4
|
@@ -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
|
-
|
|
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 =
|
|
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] =
|
|
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 =
|
|
1536
|
-
const next =
|
|
1551
|
+
const prev = cloneValue2(current);
|
|
1552
|
+
const next = cloneValue2(current);
|
|
1537
1553
|
applyMaskedPatch(fields, next, op.patch, op.mask);
|
|
1538
|
-
const requested =
|
|
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] =
|
|
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),
|
|
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))
|
|
@@ -3652,7 +3668,9 @@ function parseHibernationBlob(bytes) {
|
|
|
3652
3668
|
const r = new ByteReader3(bytes);
|
|
3653
3669
|
const version = r.u8();
|
|
3654
3670
|
if (!READABLE_SNAPSHOT_VERSIONS.includes(version)) {
|
|
3655
|
-
throw new Error(
|
|
3671
|
+
throw new Error(
|
|
3672
|
+
`RoomCore.restore: unsupported snapshot format version ${version} \u2014 this blob was written by a different irtio release`
|
|
3673
|
+
);
|
|
3656
3674
|
}
|
|
3657
3675
|
const seed = r.u32();
|
|
3658
3676
|
const rngState = r.u32();
|
|
@@ -3772,7 +3790,7 @@ import {
|
|
|
3772
3790
|
withBuiltins as withBuiltins2
|
|
3773
3791
|
} from "@irtio/protocol";
|
|
3774
3792
|
import {
|
|
3775
|
-
cloneValue as
|
|
3793
|
+
cloneValue as cloneValue3,
|
|
3776
3794
|
createDirtySet as createDirtySet3,
|
|
3777
3795
|
createState,
|
|
3778
3796
|
decodeSnapshot as decodeSnapshot3,
|
|
@@ -6139,7 +6157,7 @@ function ownJoinCapture(plain, name, added, clientId) {
|
|
|
6139
6157
|
for (const id of added) {
|
|
6140
6158
|
const owner = coll.ownerOf(id);
|
|
6141
6159
|
if (name === PRESENCE_COLLECTION ? id !== clientId : owner !== clientId) continue;
|
|
6142
|
-
(mine ??= /* @__PURE__ */ new Map()).set(id, { value:
|
|
6160
|
+
(mine ??= /* @__PURE__ */ new Map()).set(id, { value: cloneValue3(coll.get(id)), owner });
|
|
6143
6161
|
}
|
|
6144
6162
|
return mine;
|
|
6145
6163
|
}
|
|
@@ -6903,7 +6921,7 @@ var RoomCore = class _RoomCore {
|
|
|
6903
6921
|
this.clients.set(clientId, entry);
|
|
6904
6922
|
this.invalidateClients();
|
|
6905
6923
|
reclaimHolds(this.internals, clientId, entry.playerId);
|
|
6906
|
-
addPerPlayerRecords(this.internals, clientId);
|
|
6924
|
+
addPerPlayerRecords(this.internals, clientId, options.persisted);
|
|
6907
6925
|
const onJoin = this.definition.config.onJoin;
|
|
6908
6926
|
if (onJoin) {
|
|
6909
6927
|
const ctx = this.ctxFor(clientId, reconnecting);
|
|
@@ -6926,7 +6944,7 @@ var RoomCore = class _RoomCore {
|
|
|
6926
6944
|
const captured = mine ?? /* @__PURE__ */ new Map();
|
|
6927
6945
|
for (const id of cd.added) {
|
|
6928
6946
|
if (!visible.has(id) || captured.has(id)) continue;
|
|
6929
|
-
captured.set(id, { value:
|
|
6947
|
+
captured.set(id, { value: cloneValue3(coll.get(id)), owner: coll.ownerOf(id) });
|
|
6930
6948
|
}
|
|
6931
6949
|
if (captured.size > 0) pending.set(name2, captured);
|
|
6932
6950
|
} else if (mine) pending.set(name2, mine);
|
|
@@ -6967,6 +6985,30 @@ var RoomCore = class _RoomCore {
|
|
|
6967
6985
|
this.invalidateClients();
|
|
6968
6986
|
this.eventFlush();
|
|
6969
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 ----
|
|
6970
7012
|
markDisconnected(clientId) {
|
|
6971
7013
|
const entry = this.clients.get(clientId);
|
|
6972
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
/**
|
package/dist/test/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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-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-
|
|
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. */
|
package/dist/test/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
initPhysics,
|
|
6
6
|
initRapier2d,
|
|
7
7
|
visibleNames
|
|
8
|
-
} from "../chunk-
|
|
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);
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -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-
|
|
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';
|
package/dist/worker/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
migrateSnapshot
|
|
3
|
-
} from "../chunk-
|
|
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-
|
|
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
|
+
"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": "
|
|
40
|
-
"@irtio/schema": "
|
|
41
|
-
"@irtio/server": "
|
|
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"
|