@irtio/runtime 4.3.0 → 4.4.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-ZGJY4E3G.js → chunk-GK53BSWK.js} +1 -1
- package/dist/{chunk-KJN62J37.js → chunk-JFC5BQ2N.js} +2690 -2338
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{room-Bpo_nqlO.d.ts → room-BYhsLgQV.d.ts} +129 -5
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +1 -1
- package/dist/worker/index.js +4 -3
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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-DHWlURaq.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-BYhsLgQV.js';
|
|
3
3
|
import { CollectionDesc, AnySchema, PlainState, DirtySet } from '@irtio/schema';
|
|
4
4
|
import '@irtio/protocol';
|
|
5
5
|
import '@irtio/server';
|
|
@@ -155,7 +155,7 @@ interface DecodedSave extends SnapshotHeader {
|
|
|
155
155
|
* there is no section at all. A pre-D45 blob has no discriminant and reads as `'rapier3d'`,
|
|
156
156
|
* which is what it is.
|
|
157
157
|
*/
|
|
158
|
-
readonly physicsEngine: 'rapier3d' | 'matter2d' | 'rapier2d' | undefined;
|
|
158
|
+
readonly physicsEngine: 'rapier3d' | 'matter2d' | 'rapier2d' | 'custom' | undefined;
|
|
159
159
|
/**
|
|
160
160
|
* The room's authoritative state, in exactly the shape `inspectState` and the recorded
|
|
161
161
|
* timeline use: entity collections as `{ id: { owner, value } }`, singletons as their value.
|
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-GK53BSWK.js";
|
|
6
6
|
import {
|
|
7
7
|
AdmissionError,
|
|
8
8
|
CRASH_AFTER_THROWS,
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
visibleNames,
|
|
60
60
|
visibleTo,
|
|
61
61
|
writeHibernationBlob
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-JFC5BQ2N.js";
|
|
63
63
|
export {
|
|
64
64
|
AdmissionError,
|
|
65
65
|
CRASH_AFTER_THROWS,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PlatformNotice, AttributeOptions, ProfileSnapshot } from '@irtio/protocol';
|
|
2
2
|
import { DirtySet, AnySchema, PlainState, Tracked, State } from '@irtio/schema';
|
|
3
|
-
import { RoomDefinition, RoomMode, Room, RewindView, Ctx, MatterModule, MatterEngine, MatterBody, RapierModule, RapierWorld, RapierRigidBody, Rapier2dModule, Rapier2dWorld, Rapier2dRigidBody, ResolvedRoomConfig, LeaveReason } from '@irtio/server';
|
|
3
|
+
import { RoomDefinition, RoomMode, Room, RewindView, Ctx, CustomStepper, CustomPose, MatterModule, MatterEngine, MatterBody, RapierModule, RapierWorld, RapierRigidBody, Rapier2dModule, Rapier2dWorld, Rapier2dRigidBody, ResolvedRoomConfig, LeaveReason } from '@irtio/server';
|
|
4
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-DHWlURaq.js';
|
|
5
5
|
|
|
6
6
|
declare class Mulberry32 {
|
|
@@ -123,10 +123,29 @@ interface UnsyncedRegistry {
|
|
|
123
123
|
keys(): IterableIterator<string>;
|
|
124
124
|
[Symbol.iterator](): IterableIterator<readonly [string, unknown]>;
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* One body's pose in the thirteen canonical channels. Structurally `Pose` in `core/history.ts` and
|
|
128
|
+
* `CustomPose` in `@irtio/server`; restated here so this seam declares no dependency on either.
|
|
129
|
+
*/
|
|
130
|
+
interface PosePlain {
|
|
131
|
+
x: number;
|
|
132
|
+
y: number;
|
|
133
|
+
z: number;
|
|
134
|
+
qx: number;
|
|
135
|
+
qy: number;
|
|
136
|
+
qz: number;
|
|
137
|
+
qw: number;
|
|
138
|
+
vx: number;
|
|
139
|
+
vy: number;
|
|
140
|
+
vz: number;
|
|
141
|
+
wx: number;
|
|
142
|
+
wy: number;
|
|
143
|
+
wz: number;
|
|
144
|
+
}
|
|
126
145
|
/** What the core modules may do with the physics world (`core/physics.ts` implements it). */
|
|
127
146
|
interface PhysicsApi {
|
|
128
|
-
/** D45: which
|
|
129
|
-
readonly engineKind: 'rapier3d' | 'matter2d' | 'rapier2d';
|
|
147
|
+
/** D45: which engine this room is running. `'custom'` is the game's own stepper, not an engine. */
|
|
148
|
+
readonly engineKind: 'rapier3d' | 'matter2d' | 'rapier2d' | 'custom';
|
|
130
149
|
readonly timestep: number;
|
|
131
150
|
/** Creates bodies for new instances, destroys bodies whose instance is gone. */
|
|
132
151
|
reconcile(): void;
|
|
@@ -147,6 +166,12 @@ interface PhysicsApi {
|
|
|
147
166
|
* `bodyFor`, and it never hands out the map itself.
|
|
148
167
|
*/
|
|
149
168
|
eachTrackedBody(fn: (collection: string, id: string, body: unknown, instance: Record<string, unknown>) => void): void;
|
|
169
|
+
/**
|
|
170
|
+
* D72: this runtime's own engine-neutral pose read, when it has one. The pose history prefers it
|
|
171
|
+
* over its per-engine switch, which is how an engine the history file knows nothing about — the
|
|
172
|
+
* custom stepper — gets rewind without `history.ts` gaining a branch that can read a body.
|
|
173
|
+
*/
|
|
174
|
+
readPose?(body: unknown, out: PosePlain): void;
|
|
150
175
|
/** rapier3d and rapier2d: the engine namespace. `engineKind` says which module it is. */
|
|
151
176
|
readonly rapier: unknown;
|
|
152
177
|
/** rapier3d and rapier2d: the live `World`. */
|
|
@@ -247,6 +272,99 @@ interface RoomInternals {
|
|
|
247
272
|
invalidateClients(): void;
|
|
248
273
|
}
|
|
249
274
|
|
|
275
|
+
/**
|
|
276
|
+
* The fourth engine: the game's own, as a plain-function stepper.
|
|
277
|
+
*
|
|
278
|
+
* It sits in exactly the place `core/physics.ts` describes — reconcile, step, sync, between the
|
|
279
|
+
* `tick()` handler and the flush — and writes the same schema channels. What differs is that there
|
|
280
|
+
* is no engine underneath at all, and three consequences follow.
|
|
281
|
+
*
|
|
282
|
+
* ## There is nothing to load and nothing to snapshot
|
|
283
|
+
*
|
|
284
|
+
* No WASM, no module, no `init*()` before the room is constructed: `config.world(room)` builds the
|
|
285
|
+
* stepper out of code the bundle already has. And there is no world state to serialize — a custom
|
|
286
|
+
* room's physics section is a tag and no payload. A woken room rebuilds its bodies from schema
|
|
287
|
+
* state on the first reconcile, which is faithful to whatever the body channels carry, and loses
|
|
288
|
+
* whatever the stepper kept that the schema does not name. That is the same contract a matter2d
|
|
289
|
+
* room already lives under, said with less machinery.
|
|
290
|
+
*
|
|
291
|
+
* ## Intents are applied here, unlike the blessed engines
|
|
292
|
+
*
|
|
293
|
+
* `physics.intents` on a Rapier or matter2d room is a *naming*: the runtime never calls it and the
|
|
294
|
+
* room's `tick()` does. A stepper's `applyIntent` is different — the runtime runs it over every
|
|
295
|
+
* tracked body immediately before `step()`. The reason is that the shared-code argument is the
|
|
296
|
+
* whole of why the field exists, and the client's predictor already calls `applyIntent` per body
|
|
297
|
+
* per step; a server that left it to `tick()` would make "same code both sides" a thing the room
|
|
298
|
+
* author has to get right by hand, on the one engine where nothing else is checkable. A room that
|
|
299
|
+
* would rather steer from `tick()` simply does not define `applyIntent`.
|
|
300
|
+
*
|
|
301
|
+
* ## Poses are the whole seam
|
|
302
|
+
*
|
|
303
|
+
* `readPose`/`writePose` speak the thirteen canonical channels by name, so `sync()` is a copy and
|
|
304
|
+
* the pose history needs no engine-specific reader — which is what makes `room.rewind` work here
|
|
305
|
+
* for free. See `core/history.ts`.
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
interface CustomRuntimeOptions {
|
|
309
|
+
readonly defaultTimestep: number;
|
|
310
|
+
}
|
|
311
|
+
declare class CustomRuntime {
|
|
312
|
+
readonly engineKind: "custom";
|
|
313
|
+
/** The three blessed-engine handles, present so every runtime satisfies one internal shape. */
|
|
314
|
+
readonly rapier: undefined;
|
|
315
|
+
readonly world: undefined;
|
|
316
|
+
readonly matter: undefined;
|
|
317
|
+
readonly matterEngine: undefined;
|
|
318
|
+
/** Always: a custom room has no world snapshot, so its bodies are always rebuilt from state. */
|
|
319
|
+
readonly rebuilt = true;
|
|
320
|
+
readonly needsSetup = false;
|
|
321
|
+
private readonly core;
|
|
322
|
+
private readonly config;
|
|
323
|
+
private readonly collections;
|
|
324
|
+
private readonly stepSeconds;
|
|
325
|
+
private readonly bodies;
|
|
326
|
+
/** See `PhysicsRuntime.sourceRecords`: identity, so a pooled re-add rebuilds its body. */
|
|
327
|
+
private readonly sourceRecords;
|
|
328
|
+
private readonly skippedKeys;
|
|
329
|
+
private readonly scratch;
|
|
330
|
+
private stepper;
|
|
331
|
+
/**
|
|
332
|
+
* M7 pf3 (a): a custom room's unsynced bodies are the stepper's own — it created them, it steps
|
|
333
|
+
* them, and nothing here knows what one is — so the registry keeps names for them and calls no
|
|
334
|
+
* engine. It does not survive hibernation, for the same reason nothing else here does.
|
|
335
|
+
*/
|
|
336
|
+
private readonly unsyncedBodies;
|
|
337
|
+
readonly unsynced: UnsyncedRegistry;
|
|
338
|
+
constructor(core: RoomInternals, options: CustomRuntimeOptions);
|
|
339
|
+
get timestep(): number;
|
|
340
|
+
/**
|
|
341
|
+
* Builds the stepper. Named `runSetup` because that is the hook `RoomCore` calls at the same
|
|
342
|
+
* point for every engine; for this one it is the world's construction and not a hook on top of
|
|
343
|
+
* one, which is why it runs before the first reconcile rather than optionally.
|
|
344
|
+
*/
|
|
345
|
+
runSetup(room: Room): void;
|
|
346
|
+
free(): void;
|
|
347
|
+
/** `room.physicsCustom.stepper`. Throws rather than handing back `undefined` half a world. */
|
|
348
|
+
get liveStepper(): CustomStepper;
|
|
349
|
+
setSkipped(collection: string, id: string, on: boolean): void;
|
|
350
|
+
isSkipped(collection: string, id: string): boolean;
|
|
351
|
+
bodyFor(collection: string, id: string): object | undefined;
|
|
352
|
+
private create;
|
|
353
|
+
/** The schema's mapped channels, written onto the body over whatever it already held. */
|
|
354
|
+
private applyRecordToBody;
|
|
355
|
+
eachTrackedBody(fn: (collection: string, id: string, body: object, instance: Record<string, unknown>) => void): void;
|
|
356
|
+
/**
|
|
357
|
+
* D72's engine-neutral pose read, implemented rather than switched on. The history ring prefers
|
|
358
|
+
* this hook when a runtime carries one, which is what keeps `core/history.ts` from having to
|
|
359
|
+
* know what a custom body is.
|
|
360
|
+
*/
|
|
361
|
+
readPose(body: unknown, out: CustomPose): void;
|
|
362
|
+
reconcile(): void;
|
|
363
|
+
step(): void;
|
|
364
|
+
/** Body → schema, through the tracked proxies, `Math.fround`ed for f32 fields as Rapier's is. */
|
|
365
|
+
sync(): void;
|
|
366
|
+
}
|
|
367
|
+
|
|
250
368
|
/**
|
|
251
369
|
* Scheduling: the tick-mode fixed-step loop with catch-up, event-mode idle detection, and
|
|
252
370
|
* `room.setTimeout` / `room.setInterval`.
|
|
@@ -617,7 +735,7 @@ declare function encodePhysicsSection(section: PhysicsSection): Uint8Array;
|
|
|
617
735
|
* pre-D45 blob is therefore byte-identical and reads as Rapier without a version bump, which is
|
|
618
736
|
* what the recommendation in the plan asked for and why format 3 was not needed.
|
|
619
737
|
*/
|
|
620
|
-
type PhysicsEngineTag = 'rapier3d' | 'matter2d' | 'rapier2d';
|
|
738
|
+
type PhysicsEngineTag = 'rapier3d' | 'matter2d' | 'rapier2d' | 'custom';
|
|
621
739
|
/**
|
|
622
740
|
* Reads the engine out of an encoded section without decoding the rest of it.
|
|
623
741
|
*
|
|
@@ -941,7 +1059,7 @@ declare class RoomCore<S extends AnySchema = AnySchema> implements RoomCoreApi<S
|
|
|
941
1059
|
* where an unsynced body belongs — it is static geometry with a handle — and it is the only
|
|
942
1060
|
* place a matter2d room can put one and have it come back after a wake.
|
|
943
1061
|
*/
|
|
944
|
-
physics: PhysicsRuntime | MatterRuntime | Rapier2dRuntime | undefined;
|
|
1062
|
+
physics: PhysicsRuntime | MatterRuntime | Rapier2dRuntime | CustomRuntime | undefined;
|
|
945
1063
|
readonly stats: RoomStats;
|
|
946
1064
|
tick: number;
|
|
947
1065
|
stopped: boolean;
|
|
@@ -1049,6 +1167,12 @@ declare class RoomCore<S extends AnySchema = AnySchema> implements RoomCoreApi<S
|
|
|
1049
1167
|
* again. The only thing that differs from `buildPhysics` is which engine and which envelope.
|
|
1050
1168
|
*/
|
|
1051
1169
|
private buildRapier2d;
|
|
1170
|
+
/**
|
|
1171
|
+
* The custom half. There is no engine to check for, no world to restore and no `setup` beyond
|
|
1172
|
+
* building the stepper itself, so this is the shortest of the four: build it, say so if a blob
|
|
1173
|
+
* arrived carrying somebody else's world, reconcile the bodies out of schema state.
|
|
1174
|
+
*/
|
|
1175
|
+
private buildCustom;
|
|
1052
1176
|
/** Convenience for hosts: `RoomCore.restore(def, bytes, host, opts)`. */
|
|
1053
1177
|
static restore<S2 extends AnySchema>(definition: RoomDefinition<S2>, bytes: Uint8Array, host: RoomHost, options: Omit<RoomCoreOptions, 'restoreFrom'>): RoomCore<S2>;
|
|
1054
1178
|
get schema(): S;
|
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-BYhsLgQV.js';
|
|
2
|
+
export { m as initMatter, n as initPhysics, o as initRapier2d } from '../room-BYhsLgQV.js';
|
|
3
3
|
import { ErrorCodeName, FrameType } from '@irtio/protocol';
|
|
4
4
|
import { NpcConfig, LeaveReason, Room, RoomDefinition } from '@irtio/server';
|
|
5
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-DHWlURaq.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-GK53BSWK.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-JFC5BQ2N.js";
|
|
14
14
|
|
|
15
15
|
// src/worker/index.ts
|
|
16
16
|
import { getHeapStatistics } from "v8";
|
|
@@ -157,7 +157,8 @@ async function handleMessage(state, host, post, msg) {
|
|
|
157
157
|
}
|
|
158
158
|
if (def.config.physics) {
|
|
159
159
|
try {
|
|
160
|
-
if (def.config.physics.engine === "
|
|
160
|
+
if (def.config.physics.engine === "custom") {
|
|
161
|
+
} else if (def.config.physics.engine === "matter2d") await initMatter();
|
|
161
162
|
else {
|
|
162
163
|
if (def.config.physics.engine === "rapier2d") await initRapier2d();
|
|
163
164
|
else await initPhysics();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@irtio/runtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.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": "^4.
|
|
40
|
-
"@irtio/schema": "^4.
|
|
41
|
-
"@irtio/server": "^4.
|
|
39
|
+
"@irtio/protocol": "^4.4.0",
|
|
40
|
+
"@irtio/schema": "^4.4.0",
|
|
41
|
+
"@irtio/server": "^4.4.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/matter-js": "0.20.2"
|