@series-inc/rundot-syncplay 5.24.0-beta.0 → 5.24.0-beta.2
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/README.md +42 -14
- package/dist/authority-room.d.ts +17 -0
- package/dist/authority-room.js +48 -1
- package/dist/browser.d.ts +14 -3
- package/dist/browser.js +7 -1
- package/dist/cjs/authority-room.js +48 -1
- package/dist/cjs/browser.js +23 -2
- package/dist/cjs/cosmetic-physics3d.js +201 -0
- package/dist/cjs/creator.js +26 -1
- package/dist/cjs/engine-complete.js +10 -8
- package/dist/cjs/engine-parity-matrix.js +11 -2
- package/dist/cjs/engine-parity.js +6 -3
- package/dist/cjs/index.js +28 -2
- package/dist/cjs/input-authority.js +66 -2
- package/dist/cjs/local-authority-server-runner.js +3 -1
- package/dist/cjs/local-authority-wire.js +20 -1
- package/dist/cjs/match-log.js +27 -0
- package/dist/cjs/math.js +30 -0
- package/dist/cjs/networked-client.js +94 -13
- package/dist/cjs/node.js +19 -1
- package/dist/cjs/physics-cert.js +1 -1
- package/dist/cjs/physics3d-destruction-cert.js +279 -0
- package/dist/cjs/physics3d-heightfield.js +51 -0
- package/dist/cjs/physics3d-joints.js +92 -18
- package/dist/cjs/physics3d-mass.js +131 -0
- package/dist/cjs/physics3d-shared.js +5 -1
- package/dist/cjs/physics3d-solver.js +204 -51
- package/dist/cjs/physics3d-toi.js +23 -0
- package/dist/cjs/physics3d-voxel.js +94 -0
- package/dist/cjs/physics3d.js +327 -27
- package/dist/cjs/replay.js +25 -1
- package/dist/cjs/sdk-offline.js +9 -1
- package/dist/cjs/sdk-session.js +9 -0
- package/dist/cjs/secret-authority.js +647 -0
- package/dist/cjs/secret-client.js +615 -0
- package/dist/cjs/secret-command-classification.js +8 -0
- package/dist/cjs/secret-config.js +211 -0
- package/dist/cjs/secret-crypto.js +208 -0
- package/dist/cjs/secret-protocol.js +238 -0
- package/dist/cjs/session-build.js +7 -4
- package/dist/cjs/session-wire.js +12 -6
- package/dist/cjs/tools/static-checker.js +61 -13
- package/dist/cli.js +77 -10
- package/dist/cosmetic-physics3d.d.ts +41 -0
- package/dist/cosmetic-physics3d.js +196 -0
- package/dist/creator.d.ts +8 -0
- package/dist/creator.js +7 -0
- package/dist/deterministic-primitives.d.ts +1 -0
- package/dist/engine-complete.js +10 -8
- package/dist/engine-parity-matrix.js +11 -2
- package/dist/engine-parity.js +6 -3
- package/dist/index.d.ts +17 -2
- package/dist/index.js +9 -1
- package/dist/input-authority.d.ts +6 -0
- package/dist/input-authority.js +67 -3
- package/dist/local-authority-server-runner.d.ts +1 -0
- package/dist/local-authority-server-runner.js +2 -1
- package/dist/local-authority-wire.js +20 -1
- package/dist/match-log.d.ts +4 -1
- package/dist/match-log.js +27 -0
- package/dist/math.d.ts +4 -0
- package/dist/math.js +30 -0
- package/dist/networked-client.d.ts +17 -0
- package/dist/networked-client.js +94 -13
- package/dist/node.d.ts +5 -0
- package/dist/node.js +4 -0
- package/dist/physics-cert.js +1 -1
- package/dist/physics3d-destruction-cert.d.ts +35 -0
- package/dist/physics3d-destruction-cert.js +276 -0
- package/dist/physics3d-heightfield.d.ts +17 -0
- package/dist/physics3d-heightfield.js +47 -0
- package/dist/physics3d-joints.d.ts +6 -1
- package/dist/physics3d-joints.js +93 -19
- package/dist/physics3d-mass.d.ts +11 -0
- package/dist/physics3d-mass.js +126 -0
- package/dist/physics3d-shared.d.ts +1 -0
- package/dist/physics3d-shared.js +4 -1
- package/dist/physics3d-solver.d.ts +41 -4
- package/dist/physics3d-solver.js +202 -51
- package/dist/physics3d-toi.d.ts +9 -0
- package/dist/physics3d-toi.js +22 -0
- package/dist/physics3d-voxel.d.ts +20 -0
- package/dist/physics3d-voxel.js +91 -0
- package/dist/physics3d.d.ts +38 -3
- package/dist/physics3d.js +329 -30
- package/dist/replay.d.ts +5 -0
- package/dist/replay.js +25 -1
- package/dist/reports.d.ts +6 -1
- package/dist/sdk-offline.d.ts +4 -0
- package/dist/sdk-offline.js +9 -1
- package/dist/sdk-session.d.ts +6 -0
- package/dist/sdk-session.js +9 -0
- package/dist/secret-authority.d.ts +90 -0
- package/dist/secret-authority.js +643 -0
- package/dist/secret-client.d.ts +89 -0
- package/dist/secret-client.js +611 -0
- package/dist/secret-command-classification.d.ts +1 -0
- package/dist/secret-command-classification.js +5 -0
- package/dist/secret-config.d.ts +45 -0
- package/dist/secret-config.js +206 -0
- package/dist/secret-crypto.d.ts +29 -0
- package/dist/secret-crypto.js +190 -0
- package/dist/secret-protocol.d.ts +181 -0
- package/dist/secret-protocol.js +230 -0
- package/dist/session-build.d.ts +16 -0
- package/dist/session-build.js +7 -4
- package/dist/session-wire.js +12 -6
- package/dist/tools/static-checker.d.ts +11 -0
- package/dist/tools/static-checker.js +60 -13
- package/package.json +6 -5
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDeterministicCosmeticPhysicsWorld3D = createDeterministicCosmeticPhysicsWorld3D;
|
|
4
|
+
exports.setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D = setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D;
|
|
5
|
+
exports.stepDeterministicCosmeticPhysicsWorld3D = stepDeterministicCosmeticPhysicsWorld3D;
|
|
6
|
+
const physics3d_js_1 = require("./physics3d.js");
|
|
7
|
+
const internalPhysicsWorldByCosmeticWorld = new WeakMap();
|
|
8
|
+
function createDeterministicCosmeticPhysicsWorld3D(bodies, authoritativeBodyProxies = []) {
|
|
9
|
+
const normalized = normalizeCosmeticBodies(bodies, authoritativeBodyProxies);
|
|
10
|
+
const world = {
|
|
11
|
+
frame: 0,
|
|
12
|
+
bodies: normalized.bodies,
|
|
13
|
+
authoritativeBodyProxies: normalized.authoritativeBodyProxies,
|
|
14
|
+
};
|
|
15
|
+
internalPhysicsWorldByCosmeticWorld.set(world, createSimulationWorld(normalized));
|
|
16
|
+
return world;
|
|
17
|
+
}
|
|
18
|
+
function setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D(world, authoritativeBodyProxies) {
|
|
19
|
+
const normalized = normalizeCosmeticBodies(world.bodies, authoritativeBodyProxies);
|
|
20
|
+
const nextWorld = {
|
|
21
|
+
frame: world.frame,
|
|
22
|
+
bodies: normalized.bodies,
|
|
23
|
+
authoritativeBodyProxies: normalized.authoritativeBodyProxies,
|
|
24
|
+
};
|
|
25
|
+
const previousSimulationWorld = internalPhysicsWorldByCosmeticWorld.get(world);
|
|
26
|
+
if (previousSimulationWorld !== undefined) {
|
|
27
|
+
internalPhysicsWorldByCosmeticWorld.set(nextWorld, previousSimulationWorld);
|
|
28
|
+
}
|
|
29
|
+
return nextWorld;
|
|
30
|
+
}
|
|
31
|
+
function stepDeterministicCosmeticPhysicsWorld3D(world, options = {}) {
|
|
32
|
+
const normalized = normalizeCosmeticBodies(world.bodies, world.authoritativeBodyProxies);
|
|
33
|
+
const previousSimulationWorld = internalPhysicsWorldByCosmeticWorld.get(world);
|
|
34
|
+
const baseSimulationWorld = createSimulationWorld(normalized, previousSimulationWorld);
|
|
35
|
+
const movedProxyIds = movedAuthoritativeBodyProxyIds(previousSimulationWorld, normalized.authoritativeBodyProxies);
|
|
36
|
+
const simulationWorld = wakeSleepingCosmeticBodies(baseSimulationWorld, previousSimulationWorld, movedProxyIds);
|
|
37
|
+
const stepped = (0, physics3d_js_1.stepDeterministicPhysicsWorld3D)(simulationWorld, {
|
|
38
|
+
gravityY: options.gravityY,
|
|
39
|
+
dtTicks: options.dtTicks,
|
|
40
|
+
velocityIterations: options.velocityIterations,
|
|
41
|
+
substeps: options.substeps,
|
|
42
|
+
computeChecksum: false,
|
|
43
|
+
computeBroadphasePairs: options.computeBroadphasePairs,
|
|
44
|
+
});
|
|
45
|
+
const nextBodies = stepped.world.bodies.filter((body) => body.kind === 'dynamic');
|
|
46
|
+
const cosmeticBodyIds = new Set([
|
|
47
|
+
...normalized.bodies.map((body) => body.id),
|
|
48
|
+
...(previousSimulationWorld?.bodies ?? [])
|
|
49
|
+
.filter((body) => body.kind === 'dynamic')
|
|
50
|
+
.map((body) => body.id),
|
|
51
|
+
]);
|
|
52
|
+
const nextWorld = {
|
|
53
|
+
frame: world.frame + 1,
|
|
54
|
+
bodies: nextBodies,
|
|
55
|
+
authoritativeBodyProxies: normalized.authoritativeBodyProxies,
|
|
56
|
+
};
|
|
57
|
+
internalPhysicsWorldByCosmeticWorld.set(nextWorld, stepped.world);
|
|
58
|
+
return {
|
|
59
|
+
world: nextWorld,
|
|
60
|
+
contacts: stepped.contacts.filter((contact) => cosmeticBodyIds.has(contact.a) || cosmeticBodyIds.has(contact.b)),
|
|
61
|
+
broadphasePairs: stepped.broadphasePairs,
|
|
62
|
+
narrowphaseContacts: stepped.narrowphaseContacts,
|
|
63
|
+
solverCorrections: stepped.solverCorrections,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function normalizeCosmeticBodies(bodies, authoritativeBodyProxies) {
|
|
67
|
+
for (const body of bodies) {
|
|
68
|
+
if (body.kind !== 'dynamic') {
|
|
69
|
+
throw new Error(`Cosmetic physics body ${body.id} must be dynamic`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const proxy of authoritativeBodyProxies) {
|
|
73
|
+
if (proxy.kind !== 'static' && proxy.kind !== 'kinematic') {
|
|
74
|
+
throw new Error(`Authoritative cosmetic physics proxy ${proxy.id} must be static or kinematic`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const normalized = (0, physics3d_js_1.createDeterministicPhysicsWorld3D)([
|
|
78
|
+
...authoritativeBodyProxies,
|
|
79
|
+
...bodies,
|
|
80
|
+
]);
|
|
81
|
+
return {
|
|
82
|
+
allBodies: normalized.bodies,
|
|
83
|
+
bodies: normalized.bodies.filter((body) => body.kind === 'dynamic'),
|
|
84
|
+
authoritativeBodyProxies: normalized.bodies.filter((body) => body.kind === 'static' || body.kind === 'kinematic'),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function createSimulationWorld(normalized, previous) {
|
|
88
|
+
const base = {
|
|
89
|
+
frame: 0,
|
|
90
|
+
bodies: normalized.allBodies,
|
|
91
|
+
activePairs: [],
|
|
92
|
+
activePairMetadata: [],
|
|
93
|
+
contactCache: [],
|
|
94
|
+
jointCache: [],
|
|
95
|
+
};
|
|
96
|
+
if (previous === undefined) {
|
|
97
|
+
return base;
|
|
98
|
+
}
|
|
99
|
+
const bodyIds = new Set(base.bodies.map((body) => body.id));
|
|
100
|
+
// Keep removed endpoints in the previous-pair history so the solver can
|
|
101
|
+
// emit their exit event; missing bodies are safe here because event masks
|
|
102
|
+
// default to enabled and the warm cache below only keeps live pairs.
|
|
103
|
+
const activePairMetadata = previous.activePairMetadata;
|
|
104
|
+
const livePairIds = new Set(activePairMetadata
|
|
105
|
+
.filter((pair) => bodyIds.has(pair.a) && bodyIds.has(pair.b))
|
|
106
|
+
.map((pair) => pair.pair));
|
|
107
|
+
return {
|
|
108
|
+
...base,
|
|
109
|
+
activePairs: previous.activePairs,
|
|
110
|
+
activePairMetadata,
|
|
111
|
+
contactCache: previous.contactCache.filter((entry) => livePairIds.has(entry.pair)),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function movedAuthoritativeBodyProxyIds(previous, current) {
|
|
115
|
+
const previousById = new Map((previous?.bodies ?? [])
|
|
116
|
+
.filter((body) => body.kind === 'static' || body.kind === 'kinematic')
|
|
117
|
+
.map((body) => [body.id, body]));
|
|
118
|
+
const currentById = new Map(current.map((proxy) => [proxy.id, proxy]));
|
|
119
|
+
const moved = new Set();
|
|
120
|
+
for (const id of new Set([...previousById.keys(), ...currentById.keys()])) {
|
|
121
|
+
const prior = previousById.get(id);
|
|
122
|
+
const next = currentById.get(id);
|
|
123
|
+
if (prior === undefined || next === undefined || !sameBodyPose(prior, next)) {
|
|
124
|
+
moved.add(id);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return moved;
|
|
128
|
+
}
|
|
129
|
+
function sameBodyPose(left, right) {
|
|
130
|
+
return left.x === right.x
|
|
131
|
+
&& left.y === right.y
|
|
132
|
+
&& left.z === right.z
|
|
133
|
+
&& left.rx === right.rx
|
|
134
|
+
&& left.ry === right.ry
|
|
135
|
+
&& left.rz === right.rz
|
|
136
|
+
&& sameOrientation(left.orientation, right.orientation);
|
|
137
|
+
}
|
|
138
|
+
function sameOrientation(left, right) {
|
|
139
|
+
if (left === undefined || right === undefined) {
|
|
140
|
+
return left === right;
|
|
141
|
+
}
|
|
142
|
+
return left.x === right.x
|
|
143
|
+
&& left.y === right.y
|
|
144
|
+
&& left.z === right.z
|
|
145
|
+
&& left.w === right.w;
|
|
146
|
+
}
|
|
147
|
+
function wakeSleepingCosmeticBodies(world, previous, movedProxyIds) {
|
|
148
|
+
if (movedProxyIds.size === 0) {
|
|
149
|
+
return world;
|
|
150
|
+
}
|
|
151
|
+
const dynamicBodyIds = new Set(world.bodies.filter((body) => body.kind === 'dynamic').map((body) => body.id));
|
|
152
|
+
const dynamicContactGraph = new Map();
|
|
153
|
+
const directlySupportedIds = new Set();
|
|
154
|
+
const contacts = [
|
|
155
|
+
...(0, physics3d_js_1.contactDetailsDeterministicPhysics3D)(world),
|
|
156
|
+
...(previous?.activePairMetadata ?? []),
|
|
157
|
+
];
|
|
158
|
+
for (const contact of contacts) {
|
|
159
|
+
if (contact.trigger || contact.sensor) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const leftDynamic = dynamicBodyIds.has(contact.a);
|
|
163
|
+
const rightDynamic = dynamicBodyIds.has(contact.b);
|
|
164
|
+
if (movedProxyIds.has(contact.a) && rightDynamic) {
|
|
165
|
+
directlySupportedIds.add(contact.b);
|
|
166
|
+
}
|
|
167
|
+
if (movedProxyIds.has(contact.b) && leftDynamic) {
|
|
168
|
+
directlySupportedIds.add(contact.a);
|
|
169
|
+
}
|
|
170
|
+
if (!leftDynamic || !rightDynamic) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const leftNeighbors = dynamicContactGraph.get(contact.a) ?? new Set();
|
|
174
|
+
leftNeighbors.add(contact.b);
|
|
175
|
+
dynamicContactGraph.set(contact.a, leftNeighbors);
|
|
176
|
+
const rightNeighbors = dynamicContactGraph.get(contact.b) ?? new Set();
|
|
177
|
+
rightNeighbors.add(contact.a);
|
|
178
|
+
dynamicContactGraph.set(contact.b, rightNeighbors);
|
|
179
|
+
}
|
|
180
|
+
const wakeIds = new Set(directlySupportedIds);
|
|
181
|
+
const pending = [...directlySupportedIds];
|
|
182
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
183
|
+
const bodyId = pending[index];
|
|
184
|
+
for (const neighbor of dynamicContactGraph.get(bodyId) ?? []) {
|
|
185
|
+
if (wakeIds.has(neighbor)) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
wakeIds.add(neighbor);
|
|
189
|
+
pending.push(neighbor);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
let wokeBody = false;
|
|
193
|
+
const bodies = world.bodies.map((body) => {
|
|
194
|
+
if (body.kind !== 'dynamic' || body.sleeping !== true || !wakeIds.has(body.id)) {
|
|
195
|
+
return body;
|
|
196
|
+
}
|
|
197
|
+
wokeBody = true;
|
|
198
|
+
return { ...body, sleeping: false, lowVelFrames: 0 };
|
|
199
|
+
});
|
|
200
|
+
return wokeBody ? { ...world, bodies } : world;
|
|
201
|
+
}
|
package/dist/cjs/creator.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runSyncplaySynctest = exports.createSyncplayGameRuntime = exports.createSyncplayOfflineRuntime = exports.createSchemaArtifacts = exports.defineSyncplayGame = exports.verifyReplayWithDescriptor = exports.verifyReplay = exports.exportPromotionSnapshot = exports.createSessionFromPromotionSnapshot = exports.createPauseController = exports.createOfflineSession = exports.runInstantReplay = exports.createInstantReplayRunner = exports.createDeterministicCommandTimeline = exports.defaultChecksum = exports.canonicalStringify = exports.canonicalize = void 0;
|
|
3
|
+
exports.stepDeterministicVehicle3D = exports.cookDeterministicVoxelChunkCollider3D = exports.stepDeterministicPhysicsWorld3D = exports.shapeCastDeterministicPhysics3DDetailed = exports.shapeCastDeterministicPhysics3D = exports.setDeterministicBodyVelocity3D = exports.runDeterministicPhysics3DStress = exports.raycastDeterministicPhysics3DDetailed = exports.raycastDeterministicPhysics3D = exports.overlapDeterministicPhysics3D = exports.deterministicPhysicsCallback3D = exports.deterministicPhysicsBodyById3D = exports.deriveInverseInertia = exports.createDeterministicPhysicsWorld3D = exports.contactDetailsDeterministicPhysics3D = exports.applyDeterministicWorldEdit3D = exports.applyDeterministicImpulses3D = exports.applyDeterministicImpulse3D = exports.runSyncplaySynctest = exports.createSyncplayGameRuntime = exports.createSyncplayOfflineRuntime = exports.createSchemaArtifacts = exports.defineSyncplayGame = exports.verifyReplayWithDescriptor = exports.verifyReplay = exports.exportPromotionSnapshot = exports.createSessionFromPromotionSnapshot = exports.createPauseController = exports.createOfflineSession = exports.runInstantReplay = exports.createInstantReplayRunner = exports.createDeterministicCommandTimeline = exports.defaultChecksum = exports.canonicalStringify = exports.canonicalize = void 0;
|
|
4
4
|
var canonical_js_1 = require("./canonical.js");
|
|
5
5
|
Object.defineProperty(exports, "canonicalize", { enumerable: true, get: function () { return canonical_js_1.canonicalize; } });
|
|
6
6
|
Object.defineProperty(exports, "canonicalStringify", { enumerable: true, get: function () { return canonical_js_1.canonicalStringify; } });
|
|
@@ -29,3 +29,28 @@ Object.defineProperty(exports, "createSyncplayOfflineRuntime", { enumerable: tru
|
|
|
29
29
|
Object.defineProperty(exports, "createSyncplayGameRuntime", { enumerable: true, get: function () { return sdk_offline_js_1.createSyncplayOfflineRuntime; } });
|
|
30
30
|
var synctest_js_1 = require("./synctest.js");
|
|
31
31
|
Object.defineProperty(exports, "runSyncplaySynctest", { enumerable: true, get: function () { return synctest_js_1.runSyncplaySynctest; } });
|
|
32
|
+
// Deterministic 3D physics is supported creator/H5 surface. Curated: world
|
|
33
|
+
// create/step/edit, impulses, queries, vehicles, and voxel-chunk collider
|
|
34
|
+
// cooking. Cosmetic physics, KCC (movement3d), and the destruction-cert runner
|
|
35
|
+
// stay off it — the first two are not requested, the third reads wall clock.
|
|
36
|
+
var physics3d_js_1 = require("./physics3d.js");
|
|
37
|
+
Object.defineProperty(exports, "applyDeterministicImpulse3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicImpulse3D; } });
|
|
38
|
+
Object.defineProperty(exports, "applyDeterministicImpulses3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicImpulses3D; } });
|
|
39
|
+
Object.defineProperty(exports, "applyDeterministicWorldEdit3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicWorldEdit3D; } });
|
|
40
|
+
Object.defineProperty(exports, "contactDetailsDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.contactDetailsDeterministicPhysics3D; } });
|
|
41
|
+
Object.defineProperty(exports, "createDeterministicPhysicsWorld3D", { enumerable: true, get: function () { return physics3d_js_1.createDeterministicPhysicsWorld3D; } });
|
|
42
|
+
Object.defineProperty(exports, "deriveInverseInertia", { enumerable: true, get: function () { return physics3d_js_1.deriveInverseInertia; } });
|
|
43
|
+
Object.defineProperty(exports, "deterministicPhysicsBodyById3D", { enumerable: true, get: function () { return physics3d_js_1.deterministicPhysicsBodyById3D; } });
|
|
44
|
+
Object.defineProperty(exports, "deterministicPhysicsCallback3D", { enumerable: true, get: function () { return physics3d_js_1.deterministicPhysicsCallback3D; } });
|
|
45
|
+
Object.defineProperty(exports, "overlapDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.overlapDeterministicPhysics3D; } });
|
|
46
|
+
Object.defineProperty(exports, "raycastDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.raycastDeterministicPhysics3D; } });
|
|
47
|
+
Object.defineProperty(exports, "raycastDeterministicPhysics3DDetailed", { enumerable: true, get: function () { return physics3d_js_1.raycastDeterministicPhysics3DDetailed; } });
|
|
48
|
+
Object.defineProperty(exports, "runDeterministicPhysics3DStress", { enumerable: true, get: function () { return physics3d_js_1.runDeterministicPhysics3DStress; } });
|
|
49
|
+
Object.defineProperty(exports, "setDeterministicBodyVelocity3D", { enumerable: true, get: function () { return physics3d_js_1.setDeterministicBodyVelocity3D; } });
|
|
50
|
+
Object.defineProperty(exports, "shapeCastDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.shapeCastDeterministicPhysics3D; } });
|
|
51
|
+
Object.defineProperty(exports, "shapeCastDeterministicPhysics3DDetailed", { enumerable: true, get: function () { return physics3d_js_1.shapeCastDeterministicPhysics3DDetailed; } });
|
|
52
|
+
Object.defineProperty(exports, "stepDeterministicPhysicsWorld3D", { enumerable: true, get: function () { return physics3d_js_1.stepDeterministicPhysicsWorld3D; } });
|
|
53
|
+
var physics3d_voxel_js_1 = require("./physics3d-voxel.js");
|
|
54
|
+
Object.defineProperty(exports, "cookDeterministicVoxelChunkCollider3D", { enumerable: true, get: function () { return physics3d_voxel_js_1.cookDeterministicVoxelChunkCollider3D; } });
|
|
55
|
+
var physics3d_vehicle_js_1 = require("./physics3d-vehicle.js");
|
|
56
|
+
Object.defineProperty(exports, "stepDeterministicVehicle3D", { enumerable: true, get: function () { return physics3d_vehicle_js_1.stepDeterministicVehicle3D; } });
|
|
@@ -1213,7 +1213,10 @@ function createComponentReplayBundle() {
|
|
|
1213
1213
|
});
|
|
1214
1214
|
}
|
|
1215
1215
|
function physicsCategory(bodies, requestedFrames, executedFrames, enforceThresholds, benchmark, noFastStress) {
|
|
1216
|
-
const metrics = (0, physics3d_js_1.runDeterministicPhysics3DStress)(bodies, executedFrames, {
|
|
1216
|
+
const metrics = (0, physics3d_js_1.runDeterministicPhysics3DStress)(bodies, executedFrames, {
|
|
1217
|
+
allowFastStress: !noFastStress,
|
|
1218
|
+
now: engineCompleteNowMs,
|
|
1219
|
+
});
|
|
1217
1220
|
const callbackMasks = (0, physics3d_js_1.runDeterministicPhysics3DCallbackMaskFixture)();
|
|
1218
1221
|
const queryOptions = (0, physics3d_js_1.runDeterministicPhysics3DQueryOptionsFixture)();
|
|
1219
1222
|
const materials = (0, physics3d_js_1.runDeterministicPhysics3DMaterialFixture)();
|
|
@@ -1228,8 +1231,8 @@ function physicsCategory(bodies, requestedFrames, executedFrames, enforceThresho
|
|
|
1228
1231
|
// the per-frame mean budget; short ad-hoc runs skip it (gates default true).
|
|
1229
1232
|
const rigidPile = benchmark && requestedFrames >= 2000 ? runPhysics3DRigidPileMeasurementFixture(128, 200) : undefined;
|
|
1230
1233
|
const vehicleFleet = benchmark && requestedFrames >= 2000 ? runVehicle3DFleetMeasurementFixture(16, 200) : undefined;
|
|
1231
|
-
const highBodySample512 = requestedFrames > 512 ? (0, physics3d_js_1.runDeterministicPhysics3DStress)(512, 128) : undefined;
|
|
1232
|
-
const highBodySample2048 = requestedFrames > 512 ? (0, physics3d_js_1.runDeterministicPhysics3DStress)(2048, 32) : undefined;
|
|
1234
|
+
const highBodySample512 = requestedFrames > 512 ? (0, physics3d_js_1.runDeterministicPhysics3DStress)(512, 128, { now: engineCompleteNowMs }) : undefined;
|
|
1235
|
+
const highBodySample2048 = requestedFrames > 512 ? (0, physics3d_js_1.runDeterministicPhysics3DStress)(2048, 32, { now: engineCompleteNowMs }) : undefined;
|
|
1233
1236
|
return categoryReport('physics3d', (0, canonical_js_1.defaultChecksum)({
|
|
1234
1237
|
stress: metrics.checksum,
|
|
1235
1238
|
materials: materials.checksum,
|
|
@@ -1276,10 +1279,7 @@ function physicsCategory(bodies, requestedFrames, executedFrames, enforceThresho
|
|
|
1276
1279
|
&& stack.settledDynamicBodies === stack.stackLayers,
|
|
1277
1280
|
stackRollbackEquivalent: stack.rollbackEquivalent,
|
|
1278
1281
|
stackAuthoringOrderStable: stack.stableUnderAuthoringOrderPermutation,
|
|
1279
|
-
|
|
1280
|
-
// (floor-average friction, max restitution); the bounce/friction velocity
|
|
1281
|
-
// magnitudes come from the sequential-impulse solver, not the legacy pusher.
|
|
1282
|
-
materialResponseCovered: materials.combinedFriction === 3
|
|
1282
|
+
materialResponseCovered: Math.abs(materials.combinedFriction - 0.28284271) < 1e-6
|
|
1283
1283
|
&& materials.combinedRestitution === 7
|
|
1284
1284
|
&& materials.normalVelocityAfterBounce > 0
|
|
1285
1285
|
&& materials.tangentVelocityAfterFrictionY < 10
|
|
@@ -1347,7 +1347,9 @@ function physicsCategory(bodies, requestedFrames, executedFrames, enforceThresho
|
|
|
1347
1347
|
? metrics.fullPhysicsStepFrames === metrics.frames && metrics.optimizedStressFrames === 0 && metrics.extrapolatedStress === false
|
|
1348
1348
|
: true,
|
|
1349
1349
|
optimizedStressFramesDeclared: metrics.optimizedStressFrames === Math.max(0, metrics.frames - metrics.fullPhysicsStepFrames),
|
|
1350
|
-
|
|
1350
|
+
// A missing p99StepMs means the stress ran untimed — fail loud rather than
|
|
1351
|
+
// pass a threshold gate that measured nothing.
|
|
1352
|
+
measuredP99WithinThreshold: enforceThresholds ? (metrics.p99StepMs ?? Number.POSITIVE_INFINITY) < 25 : true,
|
|
1351
1353
|
physicsStressProofMode: metrics.extrapolatedStress ? 'optimized-tail' : 'full-step',
|
|
1352
1354
|
}, withFrameMetrics({
|
|
1353
1355
|
...metrics,
|
|
@@ -625,11 +625,18 @@ const engineParityMatrixEntries = [
|
|
|
625
625
|
'packages/syncplay/src/physics3d-solver.ts',
|
|
626
626
|
'packages/syncplay/src/physics3d-toi.ts',
|
|
627
627
|
'packages/syncplay/src/physics3d-joints.ts',
|
|
628
|
+
'packages/syncplay/src/physics3d-mass.ts',
|
|
629
|
+
'packages/syncplay/src/physics3d-heightfield.ts',
|
|
628
630
|
'packages/syncplay/tests/physics2d.test.ts',
|
|
629
631
|
'packages/syncplay/tests/physics3d-solver.test.ts',
|
|
630
632
|
'packages/syncplay/tests/physics3d-joints.test.ts',
|
|
631
633
|
'packages/syncplay/tests/physics3d-ccd.test.ts',
|
|
632
634
|
'packages/syncplay/tests/physics3d-toi.test.ts',
|
|
635
|
+
'packages/syncplay/tests/physics3d-mass.test.ts',
|
|
636
|
+
'packages/syncplay/tests/physics3d-materials.test.ts',
|
|
637
|
+
'packages/syncplay/tests/physics3d-heightfield.test.ts',
|
|
638
|
+
'packages/syncplay/tests/physics3d-rotation-convention.test.ts',
|
|
639
|
+
'packages/syncplay/tests/physics3d-mesh-onesided.test.ts',
|
|
633
640
|
'packages/syncplay/tests/engine-complete.test.ts',
|
|
634
641
|
'packages/syncplay/src/physics3d-vehicle.ts',
|
|
635
642
|
'packages/syncplay/tests/physics3d-vehicle.test.ts',
|
|
@@ -640,16 +647,17 @@ const engineParityMatrixEntries = [
|
|
|
640
647
|
'packages/syncplay/src/physics3d-hull.ts',
|
|
641
648
|
'packages/syncplay/tests/physics3d-hull.test.ts',
|
|
642
649
|
'TGS-Soft (sub-stepped soft-constraint) rigid solver: box3d-class stable stacking, tumbling, sleeping, axis locks, joints (ball/hinge/weld/rope/prismatic/spring/grab), opt-in TOI-bound CCD, compound colliders, orientation-aware queries',
|
|
643
|
-
'extreme-speed CCD (box3d model, src/physics3d-toi.ts): an opt-in ccd body whose per-tick motion exceeds half its smallest extent has its exact first time-of-impact found by GJK conservative advancement; it is advanced there and the impact resolved as a perfectly-inelastic collision
|
|
650
|
+
'extreme-speed CCD (box3d model, src/physics3d-toi.ts): an opt-in ccd body whose per-tick motion exceeds half its smallest extent has its exact first time-of-impact found by GJK conservative advancement against convex shapes and culled heightfield cell triangles; it is advanced there and the impact resolved as a perfectly-inelastic collision with momentum transfer and a TOI position clamp. physics3d-ccd.test.ts and physics3d-heightfield.test.ts cover finite-at-vx60, heightfield-cliff no-tunnel, rollback, and permutation equivalence',
|
|
644
651
|
'stacking stability gated in CI: tower-15 (<1° tilt), 50:1 mass-ratio column, pyramid, kick-recovery, and a 20-layer stack all meet drift/penetration/up-alignment thresholds with rollback + authoring-order-permutation equivalence',
|
|
645
652
|
'convex-hull collision shape (4–16 verts): deterministic supporting-plane preprocessing, SAT+clip hull-vs-hull/box, closest-point hull-vs-sphere/capsule, support-sample hull-vs-static-mesh, exact ray/overlap/shape-cast queries; golden hull-pair battery pinned',
|
|
646
653
|
'cone-twist ball joint (swing cone + twist limits via fixed-point cosine) drives a 6-body ragdoll that settles kinetically and stays articulated; rigid-wheel vehicle recipe (sphere wheels + hinge motors) certified alongside the raycast controller',
|
|
647
654
|
'builtin-rigid physics-cert lane passes all 4 determinism gates; contact/joint caches are checksummed rollback state',
|
|
655
|
+
'builtin-rigid@2 certifies true hull/compound inertia and center-of-mass integration, geometric-mean friction, rolling resistance, static heightfields with CCD/query parity, and active spherical motor/orientation-spring rows',
|
|
648
656
|
'raycast-wheel vehicle controller (stepDeterministicVehicle3D): spring-damper suspension, friction-circle drive/steer/brake, fixed-point steering trig, moving-ground reaction (slip relative to the contact body; equal-and-opposite reaction on dynamic ground)',
|
|
649
657
|
'per-world static AABB-tree query index: raycast/overlap/shape-cast are O(log n + hits) with bit-identical results; batched applyDeterministicImpulses3D applies a frame of controller impulses in one canonical rebuild',
|
|
650
658
|
'pooled narrow-phase/constraint scratch (scalarized box face-clip over ping-pong clip slots, step-scoped constraint pool); prismatic/breakable/collision-suppressed joints, a soft frequencyHz/dampingRatio spring joint (breakable/disable-collision), and per-body gravityScale — joint breaks are sticky checksummed cache state',
|
|
651
659
|
'kinematic bodies integrate their authored velocity (linear + angular) inside the solver, drive the dynamic bodies they touch through the contact relative-velocity term, absorb the equal-and-opposite reaction (zero inverse mass), and wake the sleeping piles they push; a kinematic mesh is therefore a moving platform / conveyor collider. A dynamic mesh is rejected at world creation',
|
|
652
|
-
'one-sided mesh contacts resolve penetration for zero-radius shapes
|
|
660
|
+
'one-sided mesh and heightfield contacts resolve penetration for zero-radius shapes while rejecting genuine back-face approaches; a shallow solver-creep recovery band keeps boxes/hulls resting without ejecting bodies from below',
|
|
653
661
|
'compound colliders accept hull children (packages/syncplay/src/collider-cooking.ts): an offline V-HACD-shaped cooker voxelizes a concave triangle soup, splits it on the axis-aligned plane that best reduces concavity, and emits a compound of ≤16-vert convex hulls that the runtime validates with buildSolverHull. The cook is order-invariant and byte-reproducible (exact integer-lattice convex hull, lexicographic tie-breaks); no decomposition code runs in a simulation step',
|
|
654
662
|
],
|
|
655
663
|
cliProofs: [
|
|
@@ -663,6 +671,7 @@ const engineParityMatrixEntries = [
|
|
|
663
671
|
gaps: [
|
|
664
672
|
'Mesh-vs-mesh collision remains unsupported by design: a mesh collider is static or kinematic, and a dynamic concave body must be cooked to a compound of hulls (collider:cook).',
|
|
665
673
|
'Kinematic bodies resolve contacts discretely — a kinematic mesh driven faster than its own extent per tick can pass through a thin body (no CCD for kinematic; ccd is a dynamic-body opt-in).',
|
|
674
|
+
'Dynamic ccd sweeps box, sphere, capsule, hull, and heightfield targets; triangle-soup mesh and compound targets remain discrete-only.',
|
|
666
675
|
'Convex decomposition is offline only: the cooked hull set is conservative (it contains the source, inflated by up to one voxel of the chosen resolution) and hulls stay capped at 16 verts.',
|
|
667
676
|
],
|
|
668
677
|
nextCliWork: [
|
|
@@ -767,7 +767,7 @@ function runPhysicsCategory(config) {
|
|
|
767
767
|
&& physics3DQueries.overlapCovered
|
|
768
768
|
&& physics3DQueries.shapeCastCovered,
|
|
769
769
|
physics3DMaterialResponse: physics3DMaterials.rollbackEquivalent
|
|
770
|
-
&& physics3DMaterials.combinedFriction
|
|
770
|
+
&& Math.abs(physics3DMaterials.combinedFriction - 0.28284271) < 1e-6
|
|
771
771
|
&& physics3DMaterials.combinedRestitution === 7
|
|
772
772
|
&& physics3DMaterials.normalVelocityAfterBounce < 0,
|
|
773
773
|
physics3DDetailedQueriesAndContacts: physics3DDetails.rollbackEquivalent
|
|
@@ -891,8 +891,11 @@ function runPhysicsCategory(config) {
|
|
|
891
891
|
physics3DStressScheduledPostQueries: physics3DStress.scheduledPostPhysicsQueries,
|
|
892
892
|
physics3DStressScheduledShapeCasts: physics3DStress.scheduledShapeCastQueries,
|
|
893
893
|
physics3DStressScheduledResults: physics3DStress.scheduledQueryResultCount,
|
|
894
|
-
|
|
895
|
-
|
|
894
|
+
// Synthetic deterministic score, never wall clock: this metrics object is
|
|
895
|
+
// checksummed and compared across runtimes, so a real timing would make
|
|
896
|
+
// parity drift run to run.
|
|
897
|
+
physics3DStressP95StepCost: physics3DStress.p95StepCost,
|
|
898
|
+
physics3DStressP99StepCost: physics3DStress.p99StepCost,
|
|
896
899
|
physics3DStressAngularBodies: physics3DStress.angularBodies,
|
|
897
900
|
physics3DStressMeshStaticColliders: physics3DStress.meshStaticColliders,
|
|
898
901
|
physics3DStressExactMeshRaycasts: physics3DStress.exactMeshRaycasts,
|
package/dist/cjs/index.js
CHANGED
|
@@ -4,8 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.createDeterministicCommandTimelineSnapshot = exports.createDeterministicCommandTimeline = exports.assertDeterministicPayloadFields = exports.translateAabb = exports.sortAabbsByStableId = exports.segmentsIntersect = exports.segmentSegmentDistance = exports.segmentPointDistance = exports.pointOnSegment = exports.orientation = exports.fixedVec2 = exports.fixedCircle = exports.fixedAabb = exports.closestPointOnSegment = exports.circleIntersectsAabb = exports.circleIntersects = exports.aabbIntersects = exports.aabbContainsPoint = exports.stableSortedKeys = exports.stableEntries = exports.deterministicShuffle = exports.createStableIndexedMap = exports.encodeUtf8 = exports.defaultChecksum = exports.decodeUtf8 = exports.decodeCanonicalValue = exports.cloneCanonical = exports.canonicalStringify = exports.canonicalize = exports.tickDeterministicHfsm = exports.tickDeterministicBehaviorTreeWithMemory = exports.tickDeterministicBehaviorTree = exports.selectDeterministicUtility = exports.runDeterministicBotSimulation = exports.getBlackboardValue = exports.createDeterministicBotBlackboard = exports.cookDeterministicBotAsset = exports.traceDeterministicBotDocument = exports.summarizeDeterministicBotDocumentTraceCoverage = exports.summarizeDeterministicBotDocumentTraceCounterDelta = exports.compileDeterministicBotDocument = exports.createDeterministicAuthorityRoom = exports.stableAssetCookJson = exports.materializePrototypeEntities = exports.cookDeterministicAssets = exports.assertAssetManifestMatches = exports.stepDeterministicAnimation = exports.reconstructDeterministicAnimationEvents = exports.createDeterministicAnimationRuntimeState = exports.cookDeterministicAnimation = void 0;
|
|
5
5
|
exports.createDeterministicLocalAuthorityCorrectionEnvelope = exports.createDeterministicLocalAuthorityCommandBundleEnvelope = exports.createDeterministicLocalAuthorityAckEnvelope = exports.applyDeterministicLocalAuthorityInputBundleEnvelope = exports.applyDeterministicLocalAuthorityCommandBundleEnvelope = exports.createDeterministicLocalAuthorityRuntime = exports.validateDeterministicLagCompensatedShot3D = exports.validateDeterministicAuthoritativeLagCompensatedShot3D = exports.rewindDeterministicLagCompensatedTargets3D = exports.createDeterministicLagCompensation3DHistory = exports.buildDeterministicLagCompensatedHitboxProxies3D = exports.sortDeterministicInputTimelineFlags = exports.evaluateDeterministicInputTimelineResult = exports.accumulateDeterministicInputTimelineState = exports.createInputAuthority = exports.filterDeterministicEventsForPlayer = exports.createDeterministicEventTimeline = exports.SyncplayError = exports.validateDeterministicFrameSystemsStateless = exports.runDeterministicFrameRuntimeMutationCorpus = exports.isDeterministicFrameHeapStaleHandleError = exports.generateDeterministicFrameRuntimeSource = exports.createDeterministicSparseSetFrameRuntime = exports.createDeterministicSlotMap = exports.createDeterministicFrameRuntimeAccessors = exports.createDeterministicFrameRuntime = exports.createDeterministicBitset = exports.compileDeterministicDslRuntimeDescriptor = exports.assertDeterministicFrameSystemsStateless = exports.assertDeterministicFrameHeapStaleHandleError = exports.stableDeterministicEngineCompleteJson = exports.runDeterministicEngineCompleteSuite = exports.engineCompleteExecutionProofHash = exports.createDeterministicEventEffectsAdapter = exports.createEcsLiteWorld = exports.verifyDeterministicSessionRuntimeReplay = exports.createDeterministicSessionReplayBundle = exports.createDeterministicSessionCore = exports.stepTopDownBody = exports.stepKccLiteBody = exports.quantizeFpsAim = exports.detectVerticalCcdHit = exports.cookStaticColliders = exports.combineDeterministicPhysicsMaterial = exports.verifyDeterministicConfigBundle = exports.summarizeDeterministicConfigBundleFailureReasons = exports.evaluateDeterministicConfigBundleParityResult = exports.cookDeterministicConfigBundle = exports.evaluateDeterministicCommandTimelineMigrationResult = exports.deterministicPayloadMatchesFields = void 0;
|
|
6
6
|
exports.queryDeterministicPhysicsShapeOverlap2D = exports.queryDeterministicPhysicsAabb2D = exports.nearestDeterministicPhysicsHit2D = exports.createDeterministicPhysicsWorld2D = exports.circleCastDeterministicPhysics2D = exports.createOfflineSession = exports.valueNoise2D = exports.valueNoise1D = exports.hashUint32 = exports.hash2 = exports.fbm2D = exports.createNetworkedSyncplayClient = exports.stepDeterministicNavmeshOffMeshTraversal = exports.stepDeterministicNavmeshAgents = exports.smoothDeterministicNavmeshPath = exports.runDeterministicNavmeshStress = exports.locateDeterministicNavmeshPolygon = exports.findDeterministicNavmeshPointPath = exports.findDeterministicNavmeshPath = exports.cookImportedDeterministicNavmesh = exports.cookDeterministicNavmesh = exports.stepDeterministicNavigationAgents = exports.smoothDeterministicPath = exports.findDeterministicPath = exports.createDeterministicFlowField = exports.cookTilemapNavigationGraph = exports.cookDeterministicNavigationGraph = exports.applyDeterministicReciprocalAvoidance = exports.stepDeterministicKcc3D = exports.stepDeterministicCarry3D = exports.validateDeterministicLagCompensatedHit = exports.stepDeterministicTopDownMover = exports.stepDeterministicKcc2D = exports.stepDeterministicFpsAim = exports.runDeterministicMovementSimulation = exports.runDeterministicMovementCrowdSimulation = exports.rewindDeterministicTargets = exports.createDeterministicMath = exports.encodeDeterministicLocalAuthorityWireEnvelope = exports.deterministicLocalAuthorityWireProtocol = exports.decodeDeterministicLocalAuthorityWireEnvelope = exports.createDeterministicLocalAuthorityWireReceiver = exports.createDeterministicLocalAuthorityWireAuth = exports.createDeterministicLocalAuthoritySnapshotTransfer = exports.createDeterministicLocalAuthoritySnapshotRequestEnvelope = exports.createDeterministicLocalAuthoritySnapshotOfferEnvelope = exports.createDeterministicLocalAuthoritySnapshotEnvelope = exports.createDeterministicLocalAuthoritySnapshotCompleteEnvelope = exports.createDeterministicLocalAuthoritySnapshotChunkEnvelope = exports.createDeterministicLocalAuthorityInputBundleEnvelope = void 0;
|
|
7
|
-
exports.
|
|
8
|
-
exports.tickCooldown = exports.scheduleFrameEvent = exports.popDueFrameEvents = exports.millisecondsToFrames = exports.framesToMilliseconds = exports.createCooldown = exports.summarizeDeterministicLifecycleCounters = exports.createDeterministicLifecycleRunner = exports.createDeterministicSparseSet = exports.createDeterministicSignalBus = exports.encodeDeterministicSessionMessage = exports.deterministicSessionWireVersion = exports.decodeDeterministicSessionMessage = exports.encodeDeterministicStateSnapshot = exports.deterministicRoomDescriptorHash = exports.DEFAULT_SNAPSHOT_CHUNK_SIZE = exports.DEFAULT_MAX_SNAPSHOT_BYTES = exports.decodeDeterministicStateSnapshot = exports.createSnapshotTransferFromBytes = exports.createSnapshotTransferCollector = exports.bytesToBase64 = exports.base64ToBytes = exports.createSyncplayOfflineRuntime = exports.stableDeterministicDslSchemaJson = exports.parseDeterministicSchemaDsl = exports.deterministicDslMaxPlayers = exports.createDeterministicBinarySerializer = exports.proveSchemaBinaryRoundTrip = exports.generateSchemaTypes = exports.generateSchemaBinarySource = exports.createDeterministicDescriptorBinarySchema = exports.createSchemaArtifacts = exports.stableDescriptorId = exports.defineSyncplayGame = exports.withRuntimeDeterminismGuards = exports.createDeterministicRollbackHistory = exports.stableReportJson = exports.stableReportDiffJson = exports.renderDeterministicReportHtml = void 0;
|
|
7
|
+
exports.inspectReplayFrame = exports.explainReplayChecksum = exports.diffReplayFrames = exports.verifyReplayScoreAgainstTrustedRuntime = exports.verifyDeterministicSelfContainedFrameRuntimeReplayBundle = exports.verifyDeterministicReplayBundle = exports.verifyDeterministicFrameRuntimeReplayBundle = exports.sliceDeterministicReplayBundle = exports.minimizeDeterministicReplayDesyncBundle = exports.minimizeDeterministicReplayDesync = exports.createDeterministicReplayRuntimeManifest = exports.createDeterministicReplayDebugTables = exports.createDeterministicReplayBundle = exports.verifyReplayWithDescriptor = exports.verifyReplay = exports.DeterministicRandom = exports.interpolateDeterministicRenderVec2 = exports.interpolateDeterministicRenderNumber = exports.createDeterministicR3fRenderAdapter = exports.createDeterministicR3fDebugOverlay = exports.stepDeterministicVehicle3D = exports.runDeterministicTower3DScenario = exports.runDeterministicStackingSuite3D = exports.runDeterministicPyramid3DScenario = exports.runDeterministicMassRatio3DScenario = exports.runDeterministicKickRecovery3DScenario = exports.stepDeterministicCosmeticPhysicsWorld3D = exports.setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D = exports.createDeterministicCosmeticPhysicsWorld3D = exports.runDeterministicPhysics3DDestructionCert = exports.cookDeterministicVoxelChunkCollider3D = exports.stepDeterministicPhysicsWorld3D = exports.shapeCastDeterministicPhysics3DDetailed = exports.shapeCastDeterministicPhysics3D = exports.setDeterministicBodyVelocity3D = exports.runDeterministicPhysics3DStress = exports.raycastDeterministicPhysics3DDetailed = exports.raycastDeterministicPhysics3D = exports.overlapDeterministicPhysics3D = exports.deterministicPhysicsCallback3D = exports.deterministicPhysicsBodyById3D = exports.deriveInverseInertia = exports.createDeterministicPhysicsWorld3D = exports.contactDetailsDeterministicPhysics3D = exports.applyDeterministicWorldEdit3D = exports.applyDeterministicImpulses3D = exports.applyDeterministicImpulse3D = exports.stepDeterministicPhysicsWorld2D = exports.raycastDeterministicPhysics2D = exports.raycastAllDeterministicPhysics2D = void 0;
|
|
8
|
+
exports.isSyncplaySecretCommand = exports.decodeSyncplaySecretPrivateMessage = exports.validateSyncplaySecretSystemsConfig = exports.syncplaySecretLimits = exports.syncplaySecretConfigHash = exports.tickCooldown = exports.scheduleFrameEvent = exports.popDueFrameEvents = exports.millisecondsToFrames = exports.framesToMilliseconds = exports.createCooldown = exports.summarizeDeterministicLifecycleCounters = exports.createDeterministicLifecycleRunner = exports.createDeterministicSparseSet = exports.createDeterministicSignalBus = exports.encodeDeterministicSessionMessage = exports.deterministicSessionWireVersion = exports.decodeDeterministicSessionMessage = exports.encodeDeterministicStateSnapshot = exports.deterministicRoomDescriptorHash = exports.DEFAULT_SNAPSHOT_CHUNK_SIZE = exports.DEFAULT_MAX_SNAPSHOT_BYTES = exports.decodeDeterministicStateSnapshot = exports.createSnapshotTransferFromBytes = exports.createSnapshotTransferCollector = exports.bytesToBase64 = exports.base64ToBytes = exports.createSyncplayOfflineRuntime = exports.stableDeterministicDslSchemaJson = exports.parseDeterministicSchemaDsl = exports.deterministicDslMaxPlayers = exports.createDeterministicBinarySerializer = exports.proveSchemaBinaryRoundTrip = exports.generateSchemaTypes = exports.generateSchemaBinarySource = exports.createDeterministicDescriptorBinarySchema = exports.createSchemaArtifacts = exports.stableDescriptorId = exports.defineSyncplayGame = exports.withRuntimeDeterminismGuards = exports.createDeterministicRollbackHistory = exports.stableReportJson = exports.stableReportDiffJson = exports.renderDeterministicReportHtml = exports.diffDeterministicReports = exports.createProtocolRollbackReport = exports.verifyScoredReplay = exports.stableFrameDumpJson = exports.stableFrameDiffJson = exports.inspectReplayFrameWithDescriptor = void 0;
|
|
9
|
+
exports.createSyncplaySecretsClient = exports.createSyncplaySecretEventReader = exports.createSyncplaySecretAuthority = exports.verifySyncplaySignedReceipt = exports.createBrowserSyncplaySecretCrypto = exports.syncplaySecretProtocol = void 0;
|
|
9
10
|
var animation_js_1 = require("./animation.js");
|
|
10
11
|
Object.defineProperty(exports, "cookDeterministicAnimation", { enumerable: true, get: function () { return animation_js_1.cookDeterministicAnimation; } });
|
|
11
12
|
Object.defineProperty(exports, "createDeterministicAnimationRuntimeState", { enumerable: true, get: function () { return animation_js_1.createDeterministicAnimationRuntimeState; } });
|
|
@@ -194,6 +195,7 @@ Object.defineProperty(exports, "stepDeterministicPhysicsWorld2D", { enumerable:
|
|
|
194
195
|
var physics3d_js_1 = require("./physics3d.js");
|
|
195
196
|
Object.defineProperty(exports, "applyDeterministicImpulse3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicImpulse3D; } });
|
|
196
197
|
Object.defineProperty(exports, "applyDeterministicImpulses3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicImpulses3D; } });
|
|
198
|
+
Object.defineProperty(exports, "applyDeterministicWorldEdit3D", { enumerable: true, get: function () { return physics3d_js_1.applyDeterministicWorldEdit3D; } });
|
|
197
199
|
Object.defineProperty(exports, "contactDetailsDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.contactDetailsDeterministicPhysics3D; } });
|
|
198
200
|
Object.defineProperty(exports, "createDeterministicPhysicsWorld3D", { enumerable: true, get: function () { return physics3d_js_1.createDeterministicPhysicsWorld3D; } });
|
|
199
201
|
Object.defineProperty(exports, "deriveInverseInertia", { enumerable: true, get: function () { return physics3d_js_1.deriveInverseInertia; } });
|
|
@@ -207,6 +209,14 @@ Object.defineProperty(exports, "setDeterministicBodyVelocity3D", { enumerable: t
|
|
|
207
209
|
Object.defineProperty(exports, "shapeCastDeterministicPhysics3D", { enumerable: true, get: function () { return physics3d_js_1.shapeCastDeterministicPhysics3D; } });
|
|
208
210
|
Object.defineProperty(exports, "shapeCastDeterministicPhysics3DDetailed", { enumerable: true, get: function () { return physics3d_js_1.shapeCastDeterministicPhysics3DDetailed; } });
|
|
209
211
|
Object.defineProperty(exports, "stepDeterministicPhysicsWorld3D", { enumerable: true, get: function () { return physics3d_js_1.stepDeterministicPhysicsWorld3D; } });
|
|
212
|
+
var physics3d_voxel_js_1 = require("./physics3d-voxel.js");
|
|
213
|
+
Object.defineProperty(exports, "cookDeterministicVoxelChunkCollider3D", { enumerable: true, get: function () { return physics3d_voxel_js_1.cookDeterministicVoxelChunkCollider3D; } });
|
|
214
|
+
var physics3d_destruction_cert_js_1 = require("./physics3d-destruction-cert.js");
|
|
215
|
+
Object.defineProperty(exports, "runDeterministicPhysics3DDestructionCert", { enumerable: true, get: function () { return physics3d_destruction_cert_js_1.runDeterministicPhysics3DDestructionCert; } });
|
|
216
|
+
var cosmetic_physics3d_js_1 = require("./cosmetic-physics3d.js");
|
|
217
|
+
Object.defineProperty(exports, "createDeterministicCosmeticPhysicsWorld3D", { enumerable: true, get: function () { return cosmetic_physics3d_js_1.createDeterministicCosmeticPhysicsWorld3D; } });
|
|
218
|
+
Object.defineProperty(exports, "setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D", { enumerable: true, get: function () { return cosmetic_physics3d_js_1.setDeterministicCosmeticPhysicsAuthoritativeBodyProxies3D; } });
|
|
219
|
+
Object.defineProperty(exports, "stepDeterministicCosmeticPhysicsWorld3D", { enumerable: true, get: function () { return cosmetic_physics3d_js_1.stepDeterministicCosmeticPhysicsWorld3D; } });
|
|
210
220
|
var physics3d_stacking_js_1 = require("./physics3d-stacking.js");
|
|
211
221
|
Object.defineProperty(exports, "runDeterministicKickRecovery3DScenario", { enumerable: true, get: function () { return physics3d_stacking_js_1.runDeterministicKickRecovery3DScenario; } });
|
|
212
222
|
Object.defineProperty(exports, "runDeterministicMassRatio3DScenario", { enumerable: true, get: function () { return physics3d_stacking_js_1.runDeterministicMassRatio3DScenario; } });
|
|
@@ -300,3 +310,19 @@ Object.defineProperty(exports, "millisecondsToFrames", { enumerable: true, get:
|
|
|
300
310
|
Object.defineProperty(exports, "popDueFrameEvents", { enumerable: true, get: function () { return timers_js_1.popDueFrameEvents; } });
|
|
301
311
|
Object.defineProperty(exports, "scheduleFrameEvent", { enumerable: true, get: function () { return timers_js_1.scheduleFrameEvent; } });
|
|
302
312
|
Object.defineProperty(exports, "tickCooldown", { enumerable: true, get: function () { return timers_js_1.tickCooldown; } });
|
|
313
|
+
var secret_config_js_1 = require("./secret-config.js");
|
|
314
|
+
Object.defineProperty(exports, "syncplaySecretConfigHash", { enumerable: true, get: function () { return secret_config_js_1.syncplaySecretConfigHash; } });
|
|
315
|
+
Object.defineProperty(exports, "syncplaySecretLimits", { enumerable: true, get: function () { return secret_config_js_1.syncplaySecretLimits; } });
|
|
316
|
+
Object.defineProperty(exports, "validateSyncplaySecretSystemsConfig", { enumerable: true, get: function () { return secret_config_js_1.validateSyncplaySecretSystemsConfig; } });
|
|
317
|
+
var secret_protocol_js_1 = require("./secret-protocol.js");
|
|
318
|
+
Object.defineProperty(exports, "decodeSyncplaySecretPrivateMessage", { enumerable: true, get: function () { return secret_protocol_js_1.decodeSyncplaySecretPrivateMessage; } });
|
|
319
|
+
Object.defineProperty(exports, "isSyncplaySecretCommand", { enumerable: true, get: function () { return secret_protocol_js_1.isSyncplaySecretCommand; } });
|
|
320
|
+
Object.defineProperty(exports, "syncplaySecretProtocol", { enumerable: true, get: function () { return secret_protocol_js_1.syncplaySecretProtocol; } });
|
|
321
|
+
var secret_crypto_js_1 = require("./secret-crypto.js");
|
|
322
|
+
Object.defineProperty(exports, "createBrowserSyncplaySecretCrypto", { enumerable: true, get: function () { return secret_crypto_js_1.createBrowserSyncplaySecretCrypto; } });
|
|
323
|
+
Object.defineProperty(exports, "verifySyncplaySignedReceipt", { enumerable: true, get: function () { return secret_crypto_js_1.verifySyncplaySignedReceipt; } });
|
|
324
|
+
var secret_authority_js_1 = require("./secret-authority.js");
|
|
325
|
+
Object.defineProperty(exports, "createSyncplaySecretAuthority", { enumerable: true, get: function () { return secret_authority_js_1.createSyncplaySecretAuthority; } });
|
|
326
|
+
var secret_client_js_1 = require("./secret-client.js");
|
|
327
|
+
Object.defineProperty(exports, "createSyncplaySecretEventReader", { enumerable: true, get: function () { return secret_client_js_1.createSyncplaySecretEventReader; } });
|
|
328
|
+
Object.defineProperty(exports, "createSyncplaySecretsClient", { enumerable: true, get: function () { return secret_client_js_1.createSyncplaySecretsClient; } });
|
|
@@ -10,6 +10,8 @@ function createInputAuthority(config) {
|
|
|
10
10
|
const maxFutureTicks = config.maxFutureTicks ?? Number.POSITIVE_INFINITY;
|
|
11
11
|
const retainedConfirmedFrames = config.retainedConfirmedFrames ?? 512;
|
|
12
12
|
const pending = new Map();
|
|
13
|
+
const pendingCommands = new Map();
|
|
14
|
+
const occupiedSlotsByTick = new Map();
|
|
13
15
|
const lastConfirmedInput = Array.from({ length: playerCount }, () => config.neutralInput);
|
|
14
16
|
const retained = new Map();
|
|
15
17
|
let confirmedThrough = -1;
|
|
@@ -22,7 +24,20 @@ function createInputAuthority(config) {
|
|
|
22
24
|
const frame = frames[index];
|
|
23
25
|
(0, errors_js_1.invariant)(Number.isInteger(frame.tick) && (index === 0 || frame.tick === frames[index - 1].tick + 1), 'restoreFrom frames must be tick-contiguous', 'input-authority.restore-gap');
|
|
24
26
|
(0, errors_js_1.invariant)(frame.inputs.length === playerCount, 'restoreFrom frame inputs must cover every player slot', 'input-authority.restore-inputs');
|
|
25
|
-
|
|
27
|
+
if (frame.occupiedSlots !== undefined) {
|
|
28
|
+
(0, errors_js_1.invariant)(frame.occupiedSlots.every((slot, slotIndex, slots) => (Number.isInteger(slot) &&
|
|
29
|
+
slot >= 0 &&
|
|
30
|
+
slot < playerCount &&
|
|
31
|
+
(slotIndex === 0 || slots[slotIndex - 1] < slot))), 'restoreFrom occupied slots must be sorted unique valid slots', 'input-authority.restore-occupied-slots');
|
|
32
|
+
const checksumPayload = {
|
|
33
|
+
tick: frame.tick,
|
|
34
|
+
inputs: frame.inputs,
|
|
35
|
+
occupiedSlots: frame.occupiedSlots,
|
|
36
|
+
...((frame.commands?.length ?? 0) === 0 ? {} : { commands: frame.commands }),
|
|
37
|
+
};
|
|
38
|
+
(0, errors_js_1.invariant)(frame.checksum === String((0, canonical_js_1.defaultChecksum)(checksumPayload)), 'restoreFrom occupied-slot checksum mismatch', 'input-authority.restore-occupied-checksum');
|
|
39
|
+
}
|
|
40
|
+
retained.set(frame.tick, (0, canonical_js_1.cloneCanonical)(frame));
|
|
26
41
|
}
|
|
27
42
|
(0, errors_js_1.invariant)(frames[frames.length - 1].tick === restoredThrough, 'restoreFrom frames must end at the restored frontier', 'input-authority.restore-frontier');
|
|
28
43
|
earliestRetained = frames[0].tick;
|
|
@@ -75,11 +90,25 @@ function createInputAuthority(config) {
|
|
|
75
90
|
}
|
|
76
91
|
}
|
|
77
92
|
pending.delete(tick);
|
|
93
|
+
const commands = (pendingCommands.get(tick) ?? [])
|
|
94
|
+
.map((command) => (0, canonical_js_1.cloneCanonical)(command))
|
|
95
|
+
.sort(compareAuthorityCommands);
|
|
96
|
+
pendingCommands.delete(tick);
|
|
97
|
+
const occupiedSlots = occupiedSlotsByTick.get(tick);
|
|
98
|
+
occupiedSlotsByTick.delete(tick);
|
|
99
|
+
const checksumPayload = {
|
|
100
|
+
tick,
|
|
101
|
+
inputs,
|
|
102
|
+
...(occupiedSlots === undefined ? {} : { occupiedSlots }),
|
|
103
|
+
...(commands.length === 0 ? {} : { commands }),
|
|
104
|
+
};
|
|
78
105
|
const frame = {
|
|
79
106
|
tick,
|
|
80
107
|
inputs,
|
|
81
108
|
substitutedSlots,
|
|
82
|
-
|
|
109
|
+
...(occupiedSlots === undefined ? {} : { occupiedSlots }),
|
|
110
|
+
...(commands.length === 0 ? {} : { commands }),
|
|
111
|
+
checksum: String((0, canonical_js_1.defaultChecksum)(checksumPayload)),
|
|
83
112
|
};
|
|
84
113
|
retained.set(tick, frame);
|
|
85
114
|
if (earliestRetained === -1) {
|
|
@@ -116,6 +145,22 @@ function createInputAuthority(config) {
|
|
|
116
145
|
return confirmedThrough;
|
|
117
146
|
},
|
|
118
147
|
receiveInput,
|
|
148
|
+
recordOccupiedSlots(tick, slots) {
|
|
149
|
+
(0, errors_js_1.invariant)(Number.isInteger(tick) && tick >= 0, 'presence tick must be a non-negative integer', 'input-authority.presence-tick');
|
|
150
|
+
const sorted = [...slots].sort((a, b) => a - b);
|
|
151
|
+
(0, errors_js_1.invariant)(sorted.every((slot, index) => (Number.isInteger(slot) &&
|
|
152
|
+
slot >= 0 &&
|
|
153
|
+
slot < playerCount &&
|
|
154
|
+
(index === 0 || sorted[index - 1] !== slot))), 'occupied slots must be unique valid slots', 'input-authority.presence-slots');
|
|
155
|
+
occupiedSlotsByTick.set(tick, sorted);
|
|
156
|
+
},
|
|
157
|
+
queueCommand(tick, command) {
|
|
158
|
+
(0, errors_js_1.invariant)(Number.isInteger(tick) && tick >= 0, 'command tick must be a non-negative integer', 'input-authority.command-tick');
|
|
159
|
+
(0, errors_js_1.invariant)(tick > confirmedThrough, `command tick ${tick} is already confirmed`, 'input-authority.command-confirmed');
|
|
160
|
+
const commands = pendingCommands.get(tick) ?? [];
|
|
161
|
+
commands.push((0, canonical_js_1.cloneCanonical)(command));
|
|
162
|
+
pendingCommands.set(tick, commands);
|
|
163
|
+
},
|
|
119
164
|
advance,
|
|
120
165
|
get earliestRetainedTick() {
|
|
121
166
|
return earliestRetained;
|
|
@@ -148,3 +193,22 @@ function createInputAuthority(config) {
|
|
|
148
193
|
},
|
|
149
194
|
};
|
|
150
195
|
}
|
|
196
|
+
function compareAuthorityCommands(left, right) {
|
|
197
|
+
const leftRecord = isCanonicalRecord(left) ? left : undefined;
|
|
198
|
+
const rightRecord = isCanonicalRecord(right) ? right : undefined;
|
|
199
|
+
const leftSystem = typeof leftRecord?.systemId === 'string' ? leftRecord.systemId : '';
|
|
200
|
+
const rightSystem = typeof rightRecord?.systemId === 'string' ? rightRecord.systemId : '';
|
|
201
|
+
const systemOrder = compareCanonicalText(leftSystem, rightSystem);
|
|
202
|
+
if (systemOrder !== 0)
|
|
203
|
+
return systemOrder;
|
|
204
|
+
const leftRequest = typeof leftRecord?.requestId === 'string' ? leftRecord.requestId : '';
|
|
205
|
+
const rightRequest = typeof rightRecord?.requestId === 'string' ? rightRecord.requestId : '';
|
|
206
|
+
const requestOrder = compareCanonicalText(leftRequest, rightRequest);
|
|
207
|
+
return requestOrder !== 0 ? requestOrder : compareCanonicalText((0, canonical_js_1.canonicalStringify)(left), (0, canonical_js_1.canonicalStringify)(right));
|
|
208
|
+
}
|
|
209
|
+
function compareCanonicalText(left, right) {
|
|
210
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
211
|
+
}
|
|
212
|
+
function isCanonicalRecord(value) {
|
|
213
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
214
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LOCAL_AUTHORITY_SNAPSHOT_CHUNK_BYTES = void 0;
|
|
3
4
|
exports.runDeterministicLocalAuthorityServerRunner = runDeterministicLocalAuthorityServerRunner;
|
|
4
5
|
const node_http_1 = require("node:http");
|
|
5
6
|
const canonical_js_1 = require("./canonical.js");
|
|
@@ -8,6 +9,7 @@ const commands_js_1 = require("./commands.js");
|
|
|
8
9
|
const local_authority_wire_js_1 = require("./local-authority-wire.js");
|
|
9
10
|
const lag_compensation3d_js_1 = require("./lag-compensation3d.js");
|
|
10
11
|
const LOCAL_AUTHORITY_MAX_BODY_BYTES = 256 * 1024;
|
|
12
|
+
exports.LOCAL_AUTHORITY_SNAPSHOT_CHUNK_BYTES = 32 * 1024;
|
|
11
13
|
async function runDeterministicLocalAuthorityServerRunner(options = {}) {
|
|
12
14
|
const players = options.players ?? 4;
|
|
13
15
|
const seed = options.seed ?? 71;
|
|
@@ -550,7 +552,7 @@ async function driveAuthorityWireResync(baseUrl, runtime, players, seed, sequenc
|
|
|
550
552
|
wireRequests += 1;
|
|
551
553
|
wireSnapshotRequestEnvelopes += 1;
|
|
552
554
|
wireAuthRejected += request.wire?.rejectionReasons.includes('missing-wire-auth') === true ? 1 : 0;
|
|
553
|
-
const transfer = (0, local_authority_wire_js_1.createDeterministicLocalAuthoritySnapshotTransfer)(runtime, identity, `runner-transfer-${seed}-${sequenceBase}`,
|
|
555
|
+
const transfer = (0, local_authority_wire_js_1.createDeterministicLocalAuthoritySnapshotTransfer)(runtime, identity, `runner-transfer-${seed}-${sequenceBase}`, exports.LOCAL_AUTHORITY_SNAPSHOT_CHUNK_BYTES);
|
|
554
556
|
const offer = await postWire(baseUrl, 0, (0, local_authority_wire_js_1.createDeterministicLocalAuthoritySnapshotOfferEnvelope)(sequence, transfer, authoritySign));
|
|
555
557
|
sequence += 1;
|
|
556
558
|
requests += 1;
|
|
@@ -37,10 +37,12 @@ function encodeDeterministicLocalAuthorityWireEnvelope(envelope, sign) {
|
|
|
37
37
|
};
|
|
38
38
|
const auth = sign === undefined ? undefined : createDeterministicLocalAuthorityWireAuth(withoutChecksum, sign);
|
|
39
39
|
const signedEnvelope = auth === undefined ? withoutChecksum : { ...withoutChecksum, auth };
|
|
40
|
-
|
|
40
|
+
const encoded = (0, canonical_js_1.canonicalStringify)({
|
|
41
41
|
...signedEnvelope,
|
|
42
42
|
checksum: (0, canonical_js_1.defaultChecksum)(signedEnvelope),
|
|
43
43
|
});
|
|
44
|
+
assertWireEnvelopeWithinBudget(envelope.kind, encoded);
|
|
45
|
+
return encoded;
|
|
44
46
|
}
|
|
45
47
|
function decodeDeterministicLocalAuthorityWireEnvelope(encoded) {
|
|
46
48
|
// Bound parse cost BEFORE JSON.parse. The kind-specific budget is only known
|
|
@@ -1267,6 +1269,23 @@ const absoluteMaxWireEnvelopeBytes = 2_097_152;
|
|
|
1267
1269
|
function maxWireEnvelopeBytes(kind) {
|
|
1268
1270
|
return kind === 'input-bundle' || kind === 'command-bundle' ? 65_536 : 2_097_152;
|
|
1269
1271
|
}
|
|
1272
|
+
// UTF-8 byte length is at most 3× the UTF-16 length, so every small envelope
|
|
1273
|
+
// (per-frame input/command bundles) skips the exact byte measurement.
|
|
1274
|
+
function assertWireEnvelopeWithinBudget(kind, encoded) {
|
|
1275
|
+
const budget = maxWireEnvelopeBytes(kind);
|
|
1276
|
+
if (encoded.length * 3 <= budget) {
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
if (encoded.length > budget || (0, canonical_js_1.encodeUtf8)(encoded).byteLength > budget) {
|
|
1280
|
+
throw new Error(wireEnvelopeBudgetError(kind, budget));
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
function wireEnvelopeBudgetError(kind, budget) {
|
|
1284
|
+
if (kind === 'snapshot' || kind === 'correction') {
|
|
1285
|
+
return `Wire ${kind} envelope exceeds the ${budget} byte monolithic budget. A state this large must ride the chunked snapshot-offer/chunk/complete transfer (createSnapshotTransferFromBytes + createDeterministicLocalAuthoritySnapshotOfferEnvelope), which carries snapshots up to the collector's maxSnapshotBytes (default 4194304).`;
|
|
1286
|
+
}
|
|
1287
|
+
return `Wire envelope exceeds ${budget} byte payload budget`;
|
|
1288
|
+
}
|
|
1270
1289
|
function parseWireAuth(value) {
|
|
1271
1290
|
if (!isRecord(value)) {
|
|
1272
1291
|
throw new Error('Wire envelope auth must be an object');
|