@series-inc/rundot-syncplay 5.23.0-beta.7

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.
Files changed (264) hide show
  1. package/README.md +610 -0
  2. package/dist/animation.d.ts +119 -0
  3. package/dist/animation.js +488 -0
  4. package/dist/asset-cooking.d.ts +82 -0
  5. package/dist/asset-cooking.js +364 -0
  6. package/dist/authority-room.d.ts +217 -0
  7. package/dist/authority-room.js +701 -0
  8. package/dist/bot-documents.d.ts +115 -0
  9. package/dist/bot-documents.js +549 -0
  10. package/dist/bot-primitives.d.ts +152 -0
  11. package/dist/bot-primitives.js +472 -0
  12. package/dist/browser.d.ts +57 -0
  13. package/dist/browser.js +53 -0
  14. package/dist/canonical.d.ts +12 -0
  15. package/dist/canonical.js +288 -0
  16. package/dist/certification.d.ts +455 -0
  17. package/dist/certification.js +1855 -0
  18. package/dist/chaos-certification.d.ts +56 -0
  19. package/dist/chaos-certification.js +1397 -0
  20. package/dist/cjs/animation.js +495 -0
  21. package/dist/cjs/asset-cooking.js +372 -0
  22. package/dist/cjs/authority-room.js +704 -0
  23. package/dist/cjs/bot-documents.js +556 -0
  24. package/dist/cjs/bot-primitives.js +482 -0
  25. package/dist/cjs/browser.js +96 -0
  26. package/dist/cjs/canonical.js +299 -0
  27. package/dist/cjs/certification.js +1860 -0
  28. package/dist/cjs/chaos-certification.js +1402 -0
  29. package/dist/cjs/collections.js +36 -0
  30. package/dist/cjs/collision.js +96 -0
  31. package/dist/cjs/commands.js +987 -0
  32. package/dist/cjs/config-bundle.js +491 -0
  33. package/dist/cjs/creator.js +30 -0
  34. package/dist/cjs/deterministic-primitives.js +134 -0
  35. package/dist/cjs/deterministic-session.js +1410 -0
  36. package/dist/cjs/ecs-lite.js +155 -0
  37. package/dist/cjs/effects-adapter.js +97 -0
  38. package/dist/cjs/engine-complete.js +2297 -0
  39. package/dist/cjs/engine-core-proof.js +70 -0
  40. package/dist/cjs/engine-parity-matrix.js +874 -0
  41. package/dist/cjs/engine-parity.js +3183 -0
  42. package/dist/cjs/engine-runtime.js +3141 -0
  43. package/dist/cjs/errors.js +22 -0
  44. package/dist/cjs/events.js +247 -0
  45. package/dist/cjs/examples/counter-duel.js +157 -0
  46. package/dist/cjs/examples/fixed-arena.js +368 -0
  47. package/dist/cjs/index.js +229 -0
  48. package/dist/cjs/input-authority.js +150 -0
  49. package/dist/cjs/input-button.js +256 -0
  50. package/dist/cjs/input-timeline.js +418 -0
  51. package/dist/cjs/instant-replay.js +66 -0
  52. package/dist/cjs/lag-compensation3d.js +837 -0
  53. package/dist/cjs/local-authority-server-runner.js +1121 -0
  54. package/dist/cjs/local-authority-wire.js +1497 -0
  55. package/dist/cjs/local-authority.js +817 -0
  56. package/dist/cjs/local-ws-adapter.js +150 -0
  57. package/dist/cjs/match-log.js +61 -0
  58. package/dist/cjs/math.js +157 -0
  59. package/dist/cjs/mock-network-adapter.js +26 -0
  60. package/dist/cjs/movement.js +703 -0
  61. package/dist/cjs/movement3d.js +1246 -0
  62. package/dist/cjs/multiclient-authority.js +308 -0
  63. package/dist/cjs/multiplayer-service.js +434 -0
  64. package/dist/cjs/navigation.js +347 -0
  65. package/dist/cjs/navmesh.js +1437 -0
  66. package/dist/cjs/networked-client.js +691 -0
  67. package/dist/cjs/networked-input-authority.js +443 -0
  68. package/dist/cjs/node.js +47 -0
  69. package/dist/cjs/number-lab.js +78 -0
  70. package/dist/cjs/offline-session.js +370 -0
  71. package/dist/cjs/package.json +1 -0
  72. package/dist/cjs/pause-resume.js +43 -0
  73. package/dist/cjs/physics-cert.js +426 -0
  74. package/dist/cjs/physics2d.js +751 -0
  75. package/dist/cjs/physics3d.js +1996 -0
  76. package/dist/cjs/prediction-culling.js +203 -0
  77. package/dist/cjs/protocol-lab.js +1299 -0
  78. package/dist/cjs/r3f-render-adapter.js +209 -0
  79. package/dist/cjs/random.js +59 -0
  80. package/dist/cjs/replay-bundle.js +1598 -0
  81. package/dist/cjs/replay-inspect.js +236 -0
  82. package/dist/cjs/replay-scoring.js +68 -0
  83. package/dist/cjs/replay.js +356 -0
  84. package/dist/cjs/reports.js +181 -0
  85. package/dist/cjs/rollback-history.js +251 -0
  86. package/dist/cjs/runtime-guards.js +111 -0
  87. package/dist/cjs/sample-lab.js +145 -0
  88. package/dist/cjs/sample-scenes.js +752 -0
  89. package/dist/cjs/schema-artifacts.js +359 -0
  90. package/dist/cjs/schema-codegen.js +544 -0
  91. package/dist/cjs/schema-dsl-binary.js +655 -0
  92. package/dist/cjs/schema.js +319 -0
  93. package/dist/cjs/sdk-offline.js +99 -0
  94. package/dist/cjs/session-promotion.js +74 -0
  95. package/dist/cjs/session-snapshot.js +265 -0
  96. package/dist/cjs/session-wire.js +216 -0
  97. package/dist/cjs/signals.js +103 -0
  98. package/dist/cjs/sparse-set.js +169 -0
  99. package/dist/cjs/synctest.js +136 -0
  100. package/dist/cjs/system-lifecycle.js +286 -0
  101. package/dist/cjs/timers.js +61 -0
  102. package/dist/cjs/tools/static-checker.js +1468 -0
  103. package/dist/cjs/types.js +2 -0
  104. package/dist/cjs/venus-mp-budget.js +125 -0
  105. package/dist/cjs/ws-frame.js +255 -0
  106. package/dist/cli.d.ts +2 -0
  107. package/dist/cli.js +11379 -0
  108. package/dist/collections.d.ts +9 -0
  109. package/dist/collections.js +30 -0
  110. package/dist/collision.d.ts +25 -0
  111. package/dist/collision.js +85 -0
  112. package/dist/commands.d.ts +137 -0
  113. package/dist/commands.js +977 -0
  114. package/dist/config-bundle.d.ts +89 -0
  115. package/dist/config-bundle.js +483 -0
  116. package/dist/creator.d.ts +20 -0
  117. package/dist/creator.js +11 -0
  118. package/dist/deterministic-primitives.d.ts +59 -0
  119. package/dist/deterministic-primitives.js +126 -0
  120. package/dist/deterministic-session.d.ts +197 -0
  121. package/dist/deterministic-session.js +1401 -0
  122. package/dist/ecs-lite.d.ts +26 -0
  123. package/dist/ecs-lite.js +152 -0
  124. package/dist/effects-adapter.d.ts +21 -0
  125. package/dist/effects-adapter.js +94 -0
  126. package/dist/engine-complete.d.ts +45 -0
  127. package/dist/engine-complete.js +2292 -0
  128. package/dist/engine-core-proof.d.ts +26 -0
  129. package/dist/engine-core-proof.js +66 -0
  130. package/dist/engine-parity-matrix.d.ts +300 -0
  131. package/dist/engine-parity-matrix.js +869 -0
  132. package/dist/engine-parity.d.ts +74 -0
  133. package/dist/engine-parity.js +3178 -0
  134. package/dist/engine-runtime.d.ts +351 -0
  135. package/dist/engine-runtime.js +3123 -0
  136. package/dist/errors.d.ts +11 -0
  137. package/dist/errors.js +17 -0
  138. package/dist/events.d.ts +45 -0
  139. package/dist/events.js +242 -0
  140. package/dist/examples/counter-duel.d.ts +43 -0
  141. package/dist/examples/counter-duel.js +150 -0
  142. package/dist/examples/fixed-arena.d.ts +110 -0
  143. package/dist/examples/fixed-arena.js +356 -0
  144. package/dist/index.d.ts +101 -0
  145. package/dist/index.js +66 -0
  146. package/dist/input-authority.d.ts +82 -0
  147. package/dist/input-authority.js +147 -0
  148. package/dist/input-button.d.ts +36 -0
  149. package/dist/input-button.js +249 -0
  150. package/dist/input-timeline.d.ts +65 -0
  151. package/dist/input-timeline.js +412 -0
  152. package/dist/instant-replay.d.ts +59 -0
  153. package/dist/instant-replay.js +62 -0
  154. package/dist/lag-compensation3d.d.ts +146 -0
  155. package/dist/lag-compensation3d.js +827 -0
  156. package/dist/local-authority-server-runner.d.ts +79 -0
  157. package/dist/local-authority-server-runner.js +1118 -0
  158. package/dist/local-authority-wire.d.ts +142 -0
  159. package/dist/local-authority-wire.js +1477 -0
  160. package/dist/local-authority.d.ts +160 -0
  161. package/dist/local-authority.js +810 -0
  162. package/dist/local-ws-adapter.d.ts +14 -0
  163. package/dist/local-ws-adapter.js +146 -0
  164. package/dist/match-log.d.ts +74 -0
  165. package/dist/match-log.js +57 -0
  166. package/dist/math.d.ts +41 -0
  167. package/dist/math.js +154 -0
  168. package/dist/mock-network-adapter.d.ts +13 -0
  169. package/dist/mock-network-adapter.js +23 -0
  170. package/dist/movement.d.ts +155 -0
  171. package/dist/movement.js +694 -0
  172. package/dist/movement3d.d.ts +195 -0
  173. package/dist/movement3d.js +1238 -0
  174. package/dist/multiclient-authority.d.ts +30 -0
  175. package/dist/multiclient-authority.js +305 -0
  176. package/dist/multiplayer-service.d.ts +153 -0
  177. package/dist/multiplayer-service.js +429 -0
  178. package/dist/navigation.d.ts +91 -0
  179. package/dist/navigation.js +338 -0
  180. package/dist/navmesh.d.ts +236 -0
  181. package/dist/navmesh.js +1423 -0
  182. package/dist/networked-client.d.ts +124 -0
  183. package/dist/networked-client.js +688 -0
  184. package/dist/networked-input-authority.d.ts +51 -0
  185. package/dist/networked-input-authority.js +439 -0
  186. package/dist/node.d.ts +22 -0
  187. package/dist/node.js +19 -0
  188. package/dist/number-lab.d.ts +15 -0
  189. package/dist/number-lab.js +75 -0
  190. package/dist/offline-session.d.ts +2 -0
  191. package/dist/offline-session.js +367 -0
  192. package/dist/pause-resume.d.ts +48 -0
  193. package/dist/pause-resume.js +40 -0
  194. package/dist/physics-cert.d.ts +40 -0
  195. package/dist/physics-cert.js +389 -0
  196. package/dist/physics2d.d.ts +142 -0
  197. package/dist/physics2d.js +741 -0
  198. package/dist/physics3d.d.ts +285 -0
  199. package/dist/physics3d.js +1979 -0
  200. package/dist/prediction-culling.d.ts +34 -0
  201. package/dist/prediction-culling.js +200 -0
  202. package/dist/protocol-lab.d.ts +115 -0
  203. package/dist/protocol-lab.js +1295 -0
  204. package/dist/r3f-render-adapter.d.ts +61 -0
  205. package/dist/r3f-render-adapter.js +203 -0
  206. package/dist/random.d.ts +13 -0
  207. package/dist/random.js +55 -0
  208. package/dist/replay-bundle.d.ts +150 -0
  209. package/dist/replay-bundle.js +1586 -0
  210. package/dist/replay-inspect.d.ts +60 -0
  211. package/dist/replay-inspect.js +228 -0
  212. package/dist/replay-scoring.d.ts +28 -0
  213. package/dist/replay-scoring.js +65 -0
  214. package/dist/replay.d.ts +17 -0
  215. package/dist/replay.js +351 -0
  216. package/dist/reports.d.ts +176 -0
  217. package/dist/reports.js +174 -0
  218. package/dist/rollback-history.d.ts +46 -0
  219. package/dist/rollback-history.js +247 -0
  220. package/dist/runtime-guards.d.ts +1 -0
  221. package/dist/runtime-guards.js +108 -0
  222. package/dist/sample-lab.d.ts +32 -0
  223. package/dist/sample-lab.js +134 -0
  224. package/dist/sample-scenes.d.ts +86 -0
  225. package/dist/sample-scenes.js +745 -0
  226. package/dist/schema-artifacts.d.ts +49 -0
  227. package/dist/schema-artifacts.js +356 -0
  228. package/dist/schema-codegen.d.ts +21 -0
  229. package/dist/schema-codegen.js +538 -0
  230. package/dist/schema-dsl-binary.d.ts +75 -0
  231. package/dist/schema-dsl-binary.js +648 -0
  232. package/dist/schema.d.ts +87 -0
  233. package/dist/schema.js +315 -0
  234. package/dist/sdk-offline.d.ts +34 -0
  235. package/dist/sdk-offline.js +96 -0
  236. package/dist/session-promotion.d.ts +26 -0
  237. package/dist/session-promotion.js +70 -0
  238. package/dist/session-snapshot.d.ts +95 -0
  239. package/dist/session-snapshot.js +255 -0
  240. package/dist/session-wire.d.ts +89 -0
  241. package/dist/session-wire.js +211 -0
  242. package/dist/signals.d.ts +31 -0
  243. package/dist/signals.js +99 -0
  244. package/dist/sparse-set.d.ts +34 -0
  245. package/dist/sparse-set.js +165 -0
  246. package/dist/synctest.d.ts +31 -0
  247. package/dist/synctest.js +133 -0
  248. package/dist/system-lifecycle.d.ts +72 -0
  249. package/dist/system-lifecycle.js +281 -0
  250. package/dist/timers.d.ts +17 -0
  251. package/dist/timers.js +53 -0
  252. package/dist/tools/index.d.ts +4 -0
  253. package/dist/tools/index.js +4 -0
  254. package/dist/tools/static-checker.d.ts +31 -0
  255. package/dist/tools/static-checker.js +1462 -0
  256. package/dist/tools/vite-plugin.d.ts +69 -0
  257. package/dist/tools/vite-plugin.js +203 -0
  258. package/dist/types.d.ts +148 -0
  259. package/dist/types.js +1 -0
  260. package/dist/venus-mp-budget.d.ts +29 -0
  261. package/dist/venus-mp-budget.js +122 -0
  262. package/dist/ws-frame.d.ts +49 -0
  263. package/dist/ws-frame.js +247 -0
  264. package/package.json +169 -0
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cookDeterministicConfigBundle = cookDeterministicConfigBundle;
4
+ exports.verifyDeterministicConfigBundle = verifyDeterministicConfigBundle;
5
+ exports.runDeterministicConfigBundleFixture = runDeterministicConfigBundleFixture;
6
+ exports.runDeterministicConfigBundleParityFixture = runDeterministicConfigBundleParityFixture;
7
+ exports.summarizeDeterministicConfigBundleFailureReasons = summarizeDeterministicConfigBundleFailureReasons;
8
+ exports.evaluateDeterministicConfigBundleParityResult = evaluateDeterministicConfigBundleParityResult;
9
+ const canonical_js_1 = require("./canonical.js");
10
+ const asset_cooking_js_1 = require("./asset-cooking.js");
11
+ function cookDeterministicConfigBundle(source, targetVersion = source.version) {
12
+ const migrated = migrateConfigBundle(source, targetVersion);
13
+ validateConfigSource(migrated);
14
+ const assets = (0, asset_cooking_js_1.cookDeterministicAssets)(migrated.assets);
15
+ const payload = {
16
+ version: migrated.version,
17
+ engineHash: migrated.engineHash,
18
+ schemaHash: migrated.schemaHash,
19
+ sessionConfig: (0, canonical_js_1.cloneCanonical)(migrated.sessionConfig),
20
+ simulationConfig: (0, canonical_js_1.cloneCanonical)(migrated.simulationConfig),
21
+ runtimeConfig: (0, canonical_js_1.cloneCanonical)(migrated.runtimeConfig),
22
+ playerConfig: (0, canonical_js_1.cloneCanonical)(migrated.playerConfig),
23
+ assetDbHash: assets.manifest.assetDbHash,
24
+ };
25
+ const bytes = (0, canonical_js_1.canonicalStringify)(payload);
26
+ return {
27
+ version: migrated.version,
28
+ engineHash: migrated.engineHash,
29
+ schemaHash: migrated.schemaHash,
30
+ assetDbHash: assets.manifest.assetDbHash,
31
+ configHash: (0, canonical_js_1.defaultChecksum)(bytes),
32
+ bytes,
33
+ assets,
34
+ prototypeCount: assets.manifest.prototypeIds.length,
35
+ migrationResult: migrated.version === source.version ? 'none' : 'migrated',
36
+ };
37
+ }
38
+ function verifyDeterministicConfigBundle(bundle, expected) {
39
+ const identityFailure = verifyConfigBundleIdentity(bundle);
40
+ const materializedEntityCount = identityFailure === undefined ? materializedEntityCountOrUndefined(bundle) : undefined;
41
+ const base = {
42
+ configHash: bundle.configHash,
43
+ assetDbHash: bundle.assetDbHash,
44
+ prototypeCount: bundle.prototypeCount,
45
+ materializedEntityCount: materializedEntityCount ?? 0,
46
+ migrationResult: bundle.migrationResult,
47
+ };
48
+ if (identityFailure !== undefined) {
49
+ return { ...base, result: 'fail', failure: identityFailure };
50
+ }
51
+ if (materializedEntityCount === undefined) {
52
+ return { ...base, result: 'fail', failure: 'prototype-materialization-mismatch' };
53
+ }
54
+ if (bundle.engineHash !== expected.engineHash) {
55
+ return { ...base, result: 'fail', failure: 'stale-engine-hash' };
56
+ }
57
+ if (bundle.schemaHash !== expected.schemaHash) {
58
+ return { ...base, result: 'fail', failure: 'stale-schema-hash' };
59
+ }
60
+ if (expected.configHash !== undefined && bundle.configHash !== expected.configHash) {
61
+ return { ...base, result: 'fail', failure: 'stale-config-hash' };
62
+ }
63
+ if (expected.assetDbHash !== undefined && bundle.assetDbHash !== expected.assetDbHash) {
64
+ return { ...base, result: 'fail', failure: 'stale-asset-db-hash' };
65
+ }
66
+ return { ...base, result: 'pass' };
67
+ }
68
+ function materializedEntityCountOrUndefined(bundle) {
69
+ try {
70
+ return bundle.assets.manifest.prototypeIds.reduce((sum, id) => sum + (0, asset_cooking_js_1.materializePrototypeEntities)(bundle.assets, id, 1).length, 0);
71
+ }
72
+ catch {
73
+ return undefined;
74
+ }
75
+ }
76
+ function verifyConfigBundleIdentity(bundle) {
77
+ if ((0, canonical_js_1.defaultChecksum)(bundle.bytes) !== bundle.configHash) {
78
+ return 'config-bytes-hash-mismatch';
79
+ }
80
+ const payload = parseJsonOrUndefined(bundle.bytes);
81
+ if (!isRecord(payload)) {
82
+ return 'config-bytes-payload-invalid';
83
+ }
84
+ if (payload.version !== bundle.version) {
85
+ return 'config-bytes-version-mismatch';
86
+ }
87
+ if (payload.engineHash !== bundle.engineHash) {
88
+ return 'config-bytes-engine-hash-mismatch';
89
+ }
90
+ if (payload.schemaHash !== bundle.schemaHash) {
91
+ return 'config-bytes-schema-hash-mismatch';
92
+ }
93
+ if (payload.assetDbHash !== bundle.assetDbHash) {
94
+ return 'config-bytes-asset-db-hash-mismatch';
95
+ }
96
+ if (!isRecord(payload.sessionConfig)) {
97
+ return 'config-bytes-session-config-mismatch';
98
+ }
99
+ if (!isRecord(payload.simulationConfig)) {
100
+ return 'config-bytes-simulation-config-mismatch';
101
+ }
102
+ if (!isRecord(payload.runtimeConfig)) {
103
+ return 'config-bytes-runtime-config-mismatch';
104
+ }
105
+ if (!isRecord(payload.playerConfig)) {
106
+ return 'config-bytes-player-config-mismatch';
107
+ }
108
+ const assetPayload = parseJsonOrUndefined(bundle.assets.bytes);
109
+ if (assetPayload === undefined || (0, canonical_js_1.canonicalStringify)(assetPayload) !== bundle.assets.bytes) {
110
+ return 'asset-bytes-canonical-mismatch';
111
+ }
112
+ if ((0, canonical_js_1.canonicalStringify)(assetPayload) !== (0, canonical_js_1.canonicalStringify)({ manifest: bundle.assets.manifest, assets: bundle.assets.cookedAssets })) {
113
+ return 'asset-bytes-content-mismatch';
114
+ }
115
+ const cookedAssetHashes = bundle.assets.cookedAssets.map((asset) => ({
116
+ id: asset.id,
117
+ type: asset.type,
118
+ hash: (0, canonical_js_1.defaultChecksum)({ id: asset.id, data: asset.data }),
119
+ }));
120
+ if ((0, canonical_js_1.canonicalStringify)(cookedAssetHashes) !== (0, canonical_js_1.canonicalStringify)(bundle.assets.manifest.assets)) {
121
+ return 'asset-manifest-entry-mismatch';
122
+ }
123
+ const recomputedAssetDbHash = (0, canonical_js_1.defaultChecksum)({
124
+ engineVersion: bundle.assets.manifest.engineVersion,
125
+ schemaHash: bundle.assets.manifest.schemaHash,
126
+ dependencyHash: bundle.assets.manifest.dependencyHash,
127
+ dependencies: bundle.assets.manifest.dependencies,
128
+ cookedAssets: bundle.assets.cookedAssets,
129
+ });
130
+ if (recomputedAssetDbHash !== bundle.assetDbHash || recomputedAssetDbHash !== bundle.assets.manifest.assetDbHash) {
131
+ return 'asset-db-hash-mismatch';
132
+ }
133
+ if (bundle.prototypeCount !== bundle.assets.manifest.prototypeIds.length) {
134
+ return 'prototype-count-mismatch';
135
+ }
136
+ if (bundle.assets.manifest.assetCount !== bundle.assets.cookedAssets.length) {
137
+ return 'asset-count-mismatch';
138
+ }
139
+ return undefined;
140
+ }
141
+ function parseJsonOrUndefined(value) {
142
+ try {
143
+ return JSON.parse(value);
144
+ }
145
+ catch {
146
+ return undefined;
147
+ }
148
+ }
149
+ function runDeterministicConfigBundleFixture() {
150
+ const bundle = cookDeterministicConfigBundle({
151
+ version: 1,
152
+ engineHash: 'engine@1',
153
+ schemaHash: 'schema@1',
154
+ sessionConfig: { tickRate: 60, players: 128 },
155
+ simulationConfig: { numericModeV1: 'fixed', rollback: true },
156
+ runtimeConfig: { maxRollbackFrames: 12 },
157
+ playerConfig: { defaultTeam: 'blue' },
158
+ assets: {
159
+ schemaVersion: 1,
160
+ engineVersion: 'engine@1',
161
+ assets: [
162
+ { id: 'material.default', type: 'physics-material', friction: 1, restitution: 0 },
163
+ { id: 'player.prototype', type: 'prototype', prototype: true, references: ['material.default'], components: { hp: 100, speed: 12 } },
164
+ ],
165
+ },
166
+ migrations: [{ fromVersion: 1, toVersion: 2, renameKeys: { numericModeV1: 'numericMode' } }],
167
+ }, 2);
168
+ return verifyDeterministicConfigBundle(bundle, {
169
+ engineHash: 'engine@1',
170
+ schemaHash: 'schema@1',
171
+ configHash: bundle.configHash,
172
+ assetDbHash: bundle.assetDbHash,
173
+ });
174
+ }
175
+ function runDeterministicConfigBundleParityFixture() {
176
+ const source = createConfigBundleParitySource();
177
+ const targetVersion = 2;
178
+ const bundle = cookDeterministicConfigBundle(source, targetVersion);
179
+ const repeated = cookDeterministicConfigBundle(source, targetVersion);
180
+ const verification = verifyDeterministicConfigBundle(bundle, {
181
+ engineHash: 'engine@1',
182
+ schemaHash: 'schema@1',
183
+ configHash: bundle.configHash,
184
+ assetDbHash: bundle.assetDbHash,
185
+ });
186
+ const staleEngine = verifyDeterministicConfigBundle(bundle, {
187
+ engineHash: 'engine@old',
188
+ schemaHash: 'schema@1',
189
+ });
190
+ const staleSchema = verifyDeterministicConfigBundle(bundle, {
191
+ engineHash: 'engine@1',
192
+ schemaHash: 'schema@old',
193
+ });
194
+ const staleConfig = verifyDeterministicConfigBundle(bundle, {
195
+ engineHash: 'engine@1',
196
+ schemaHash: 'schema@1',
197
+ configHash: 'stale-config',
198
+ });
199
+ const staleAssetDb = verifyDeterministicConfigBundle(bundle, {
200
+ engineHash: 'engine@1',
201
+ schemaHash: 'schema@1',
202
+ assetDbHash: 'stale-asset-db',
203
+ });
204
+ const tamperedConfigBytes = verifyDeterministicConfigBundle({
205
+ ...bundle,
206
+ bytes: (0, canonical_js_1.canonicalStringify)({ tampered: true }),
207
+ }, {
208
+ engineHash: 'engine@1',
209
+ schemaHash: 'schema@1',
210
+ });
211
+ const tamperedAssetBytes = verifyDeterministicConfigBundle({
212
+ ...bundle,
213
+ assets: {
214
+ ...bundle.assets,
215
+ bytes: (0, canonical_js_1.canonicalStringify)({ manifest: bundle.assets.manifest, assets: [] }),
216
+ },
217
+ }, {
218
+ engineHash: 'engine@1',
219
+ schemaHash: 'schema@1',
220
+ });
221
+ const unsupportedFloatRejected = throws(() => cookDeterministicConfigBundle({
222
+ ...source,
223
+ sessionConfig: { ...source.sessionConfig, badFloat: 1.5 },
224
+ }, targetVersion));
225
+ const validConfigAccepted = !throws(() => cookDeterministicConfigBundle(source, targetVersion));
226
+ const materializedA = (0, asset_cooking_js_1.materializePrototypeEntities)(bundle.assets, 'player.prototype', 2);
227
+ const materializedB = (0, asset_cooking_js_1.materializePrototypeEntities)(bundle.assets, 'player.prototype', 2);
228
+ const inherited = (0, asset_cooking_js_1.materializePrototypeEntities)(bundle.assets, 'player.prototype', 1, {
229
+ componentOverrides: { Loadout: { slot: 7 } },
230
+ });
231
+ const inheritedComponents = inherited[0]?.components;
232
+ const map = (0, asset_cooking_js_1.materializeDeterministicMapEntities)(bundle.assets, 'map.arena');
233
+ const mapRepeat = (0, asset_cooking_js_1.materializeDeterministicMapEntities)(repeated.assets, 'map.arena');
234
+ const rebaked = (0, asset_cooking_js_1.materializeDeterministicMapEntities)(cookDeterministicConfigBundle({
235
+ ...source,
236
+ assets: {
237
+ ...source.assets,
238
+ assets: source.assets.assets.map((asset) => asset.id === 'map.arena'
239
+ ? { ...asset, spawns: [{ prototypeRef: 'player.prototype', count: 3, startEntityId: 100, overrides: { hp: 80 } }] }
240
+ : asset),
241
+ },
242
+ }, targetVersion).assets, 'map.arena');
243
+ const failureReasons = {
244
+ ...summarizeDeterministicConfigBundleFailureReasons({
245
+ staleEngine,
246
+ staleSchema,
247
+ staleConfig,
248
+ staleAssetDb,
249
+ tamperedConfigBytes,
250
+ tamperedAssetBytes,
251
+ }),
252
+ };
253
+ const withoutChecksum = {
254
+ version: source.version,
255
+ targetVersion,
256
+ configHash: bundle.configHash,
257
+ assetDbHash: bundle.assetDbHash,
258
+ prototypeCount: bundle.prototypeCount,
259
+ materializedEntityCount: verification.materializedEntityCount,
260
+ migrationResult: bundle.migrationResult,
261
+ byteStable: bundle.configHash === repeated.configHash && bundle.assetDbHash === repeated.assetDbHash && bundle.bytes === repeated.bytes,
262
+ staleEngineRejected: staleEngine.failure === 'stale-engine-hash',
263
+ staleSchemaRejected: staleSchema.failure === 'stale-schema-hash',
264
+ staleConfigRejected: staleConfig.failure === 'stale-config-hash',
265
+ staleAssetDbRejected: staleAssetDb.failure === 'stale-asset-db-hash',
266
+ tamperedConfigBytesRejected: tamperedConfigBytes.failure === 'config-bytes-hash-mismatch',
267
+ tamperedAssetBytesRejected: tamperedAssetBytes.failure === 'asset-bytes-content-mismatch',
268
+ unsupportedFloatRejected,
269
+ prototypeMaterializationStable: (0, canonical_js_1.defaultChecksum)(materializedA) === (0, canonical_js_1.defaultChecksum)(materializedB) && materializedA.length === 2,
270
+ inheritedPrototypeMaterialized: inheritedComponents?.hp === 80
271
+ && inheritedComponents.speed === 12
272
+ && inheritedComponents.numericMode === 'fixed'
273
+ && inheritedComponents.Loadout?.slot === 7,
274
+ dynamicCollectionsMaterialized: Array.isArray(inheritedComponents?.Inventory?.items)
275
+ && inheritedComponents.Inventory.items[0] === 'weapon.sword'
276
+ && Array.isArray(inheritedComponents.Inventory.tags)
277
+ && inheritedComponents.Inventory.tags.join(',') === 'player,spawned',
278
+ mapMaterializationStable: map.mapBakeHash === mapRepeat.mapBakeHash && map.materializedEntityCount === 2,
279
+ mapRebakeInvalidated: map.mapBakeHash !== rebaked.mapBakeHash,
280
+ mapMaterializedEntityCount: map.materializedEntityCount,
281
+ mapBakeHash: map.mapBakeHash,
282
+ failureReasons,
283
+ };
284
+ const invariantChecks = [
285
+ withoutChecksum.byteStable,
286
+ withoutChecksum.staleEngineRejected,
287
+ withoutChecksum.staleSchemaRejected,
288
+ withoutChecksum.staleConfigRejected,
289
+ withoutChecksum.staleAssetDbRejected,
290
+ withoutChecksum.tamperedConfigBytesRejected,
291
+ withoutChecksum.tamperedAssetBytesRejected,
292
+ withoutChecksum.unsupportedFloatRejected,
293
+ validConfigAccepted,
294
+ withoutChecksum.prototypeMaterializationStable,
295
+ withoutChecksum.inheritedPrototypeMaterialized,
296
+ withoutChecksum.dynamicCollectionsMaterialized,
297
+ withoutChecksum.mapMaterializationStable,
298
+ withoutChecksum.mapRebakeInvalidated,
299
+ ];
300
+ const result = evaluateDeterministicConfigBundleParityResult(verification, invariantChecks);
301
+ return {
302
+ result,
303
+ ...withoutChecksum,
304
+ checksum: (0, canonical_js_1.defaultChecksum)(withoutChecksum),
305
+ };
306
+ }
307
+ function summarizeDeterministicConfigBundleFailureReasons(inputs) {
308
+ return {
309
+ staleEngine: inputs.staleEngine.failure ?? '',
310
+ staleSchema: inputs.staleSchema.failure ?? '',
311
+ staleConfig: inputs.staleConfig.failure ?? '',
312
+ staleAssetDb: inputs.staleAssetDb.failure ?? '',
313
+ tamperedConfigBytes: inputs.tamperedConfigBytes.failure ?? '',
314
+ tamperedAssetBytes: inputs.tamperedAssetBytes.failure ?? '',
315
+ };
316
+ }
317
+ function evaluateDeterministicConfigBundleParityResult(verification, invariantChecks) {
318
+ return verification.result === 'pass'
319
+ && invariantChecks.every((value) => value)
320
+ ? 'pass'
321
+ : 'fail';
322
+ }
323
+ function createConfigBundleParitySource() {
324
+ return {
325
+ version: 1,
326
+ engineHash: 'engine@1',
327
+ schemaHash: 'schema@1',
328
+ sessionConfig: { tickRate: 60, players: 128 },
329
+ simulationConfig: { numericModeV1: 'fixed', rollback: true },
330
+ runtimeConfig: { maxRollbackFrames: 12, snapshotStride: 4 },
331
+ playerConfig: { defaultTeam: 'blue', maxSlots: 128 },
332
+ assets: {
333
+ schemaVersion: 1,
334
+ engineVersion: 'engine@1',
335
+ assets: [
336
+ { id: 'material.default', type: 'physics-material', friction: 1, restitution: 0 },
337
+ { id: 'material.ice', type: 'physics-material', friction: 0, restitution: 1 },
338
+ {
339
+ id: 'base.prototype',
340
+ type: 'prototype',
341
+ prototype: true,
342
+ references: ['material.default'],
343
+ components: {
344
+ hp: 100,
345
+ speed: 12,
346
+ numericModeV1: 'fixed',
347
+ Inventory: {
348
+ items: { collection: 'list', values: ['weapon.sword'] },
349
+ tags: { collection: 'set', values: ['spawned', 'player', 'spawned'] },
350
+ },
351
+ },
352
+ },
353
+ {
354
+ id: 'weapon.sword',
355
+ type: 'item',
356
+ },
357
+ {
358
+ id: 'player.prototype',
359
+ type: 'prototype',
360
+ prototype: true,
361
+ extendsRef: 'base.prototype',
362
+ references: ['base.prototype'],
363
+ components: { hp: 80 },
364
+ },
365
+ {
366
+ id: 'map.arena',
367
+ type: 'map',
368
+ references: ['player.prototype'],
369
+ spawns: [{ prototypeRef: 'player.prototype', count: 2, startEntityId: 100, overrides: { hp: 80 } }],
370
+ },
371
+ ],
372
+ },
373
+ migrations: [{
374
+ fromVersion: 1,
375
+ toVersion: 2,
376
+ renameSimulationKeys: { numericModeV1: 'numericMode' },
377
+ renamePrototypeComponentKeys: { numericModeV1: 'numericMode' },
378
+ }],
379
+ };
380
+ }
381
+ function migrateConfigBundle(source, targetVersion) {
382
+ let current = (0, canonical_js_1.cloneCanonical)(source);
383
+ validateUniqueMigrations(current.migrations ?? []);
384
+ while (current.version < targetVersion) {
385
+ const migration = current.migrations?.find((candidate) => candidate.fromVersion === current.version);
386
+ if (migration === undefined) {
387
+ throw new Error(`Missing config migration from ${current.version}`);
388
+ }
389
+ current = {
390
+ ...current,
391
+ version: migration.toVersion,
392
+ sessionConfig: renameConfigKeys(current.sessionConfig, migration.renameSessionKeys ?? {}),
393
+ simulationConfig: renameConfigKeys(current.simulationConfig, migration.renameSimulationKeys ?? migration.renameKeys ?? {}),
394
+ runtimeConfig: renameConfigKeys(current.runtimeConfig, migration.renameRuntimeKeys ?? {}),
395
+ playerConfig: renameConfigKeys(current.playerConfig, migration.renamePlayerKeys ?? {}),
396
+ assets: renamePrototypeComponentKeys(current.assets, migration.renamePrototypeComponentKeys ?? {}),
397
+ };
398
+ }
399
+ if (current.version !== targetVersion) {
400
+ throw new Error(`Unsupported config version ${current.version}`);
401
+ }
402
+ return current;
403
+ }
404
+ function renamePrototypeComponentKeys(assets, renames) {
405
+ if (stableKeys(renames).length === 0) {
406
+ return assets;
407
+ }
408
+ return {
409
+ ...assets,
410
+ assets: assets.assets.map((asset) => {
411
+ if (asset.prototype !== true || !isRecord(asset.components)) {
412
+ return asset;
413
+ }
414
+ return {
415
+ ...asset,
416
+ components: renameConfigKeys(asset.components, renames),
417
+ };
418
+ }),
419
+ };
420
+ }
421
+ function validateUniqueMigrations(migrations) {
422
+ const fromVersions = new Set();
423
+ for (const migration of migrations) {
424
+ if (!Number.isInteger(migration.fromVersion) || !Number.isInteger(migration.toVersion)) {
425
+ throw new Error('Config migration versions must be integers');
426
+ }
427
+ if (migration.toVersion <= migration.fromVersion) {
428
+ throw new Error(`Config migration from ${migration.fromVersion} must advance to a higher version`);
429
+ }
430
+ if (fromVersions.has(migration.fromVersion)) {
431
+ throw new Error(`Duplicate config migration from ${migration.fromVersion}`);
432
+ }
433
+ fromVersions.add(migration.fromVersion);
434
+ }
435
+ }
436
+ function renameConfigKeys(config, renames) {
437
+ const next = {};
438
+ for (const key of stableKeys(config)) {
439
+ const renamed = renames[key] ?? key;
440
+ if (Object.prototype.hasOwnProperty.call(next, renamed)) {
441
+ throw new Error(`Config migration key collision at ${renamed}`);
442
+ }
443
+ next[renamed] = config[key];
444
+ }
445
+ return next;
446
+ }
447
+ function validateConfigSource(source) {
448
+ if (source.engineHash.length === 0 || source.schemaHash.length === 0) {
449
+ throw new Error('Config bundle requires engine and schema hashes');
450
+ }
451
+ rejectUnsupportedFloats(source.sessionConfig, 'sessionConfig');
452
+ rejectUnsupportedFloats(source.simulationConfig, 'simulationConfig');
453
+ rejectUnsupportedFloats(source.runtimeConfig, 'runtimeConfig');
454
+ rejectUnsupportedFloats(source.playerConfig, 'playerConfig');
455
+ }
456
+ function rejectUnsupportedFloats(value, path) {
457
+ if (typeof value === 'number') {
458
+ if (!Number.isInteger(value)) {
459
+ throw new Error(`Unsupported float in config bundle at ${path}`);
460
+ }
461
+ return;
462
+ }
463
+ if (Array.isArray(value)) {
464
+ value.forEach((entry, index) => rejectUnsupportedFloats(entry, `${path}[${index}]`));
465
+ return;
466
+ }
467
+ if (value !== null && typeof value === 'object') {
468
+ const record = value;
469
+ for (const key of stableKeys(record)) {
470
+ rejectUnsupportedFloats(record[key], `${path}.${key}`);
471
+ }
472
+ }
473
+ }
474
+ function isRecord(value) {
475
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
476
+ }
477
+ function stableKeys(record) {
478
+ return Object.keys(record).sort(compareStrings);
479
+ }
480
+ function compareStrings(left, right) {
481
+ return Number(left > right) - Number(left < right);
482
+ }
483
+ function throws(action) {
484
+ try {
485
+ action();
486
+ return false;
487
+ }
488
+ catch {
489
+ return true;
490
+ }
491
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSyncplaySynctest = 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
+ var canonical_js_1 = require("./canonical.js");
5
+ Object.defineProperty(exports, "canonicalize", { enumerable: true, get: function () { return canonical_js_1.canonicalize; } });
6
+ Object.defineProperty(exports, "canonicalStringify", { enumerable: true, get: function () { return canonical_js_1.canonicalStringify; } });
7
+ Object.defineProperty(exports, "defaultChecksum", { enumerable: true, get: function () { return canonical_js_1.defaultChecksum; } });
8
+ var commands_js_1 = require("./commands.js");
9
+ Object.defineProperty(exports, "createDeterministicCommandTimeline", { enumerable: true, get: function () { return commands_js_1.createDeterministicCommandTimeline; } });
10
+ var instant_replay_js_1 = require("./instant-replay.js");
11
+ Object.defineProperty(exports, "createInstantReplayRunner", { enumerable: true, get: function () { return instant_replay_js_1.createInstantReplayRunner; } });
12
+ Object.defineProperty(exports, "runInstantReplay", { enumerable: true, get: function () { return instant_replay_js_1.runInstantReplay; } });
13
+ var offline_session_js_1 = require("./offline-session.js");
14
+ Object.defineProperty(exports, "createOfflineSession", { enumerable: true, get: function () { return offline_session_js_1.createOfflineSession; } });
15
+ var pause_resume_js_1 = require("./pause-resume.js");
16
+ Object.defineProperty(exports, "createPauseController", { enumerable: true, get: function () { return pause_resume_js_1.createPauseController; } });
17
+ var session_promotion_js_1 = require("./session-promotion.js");
18
+ Object.defineProperty(exports, "createSessionFromPromotionSnapshot", { enumerable: true, get: function () { return session_promotion_js_1.createSessionFromPromotionSnapshot; } });
19
+ Object.defineProperty(exports, "exportPromotionSnapshot", { enumerable: true, get: function () { return session_promotion_js_1.exportPromotionSnapshot; } });
20
+ var replay_js_1 = require("./replay.js");
21
+ Object.defineProperty(exports, "verifyReplay", { enumerable: true, get: function () { return replay_js_1.verifyReplay; } });
22
+ Object.defineProperty(exports, "verifyReplayWithDescriptor", { enumerable: true, get: function () { return replay_js_1.verifyReplayWithDescriptor; } });
23
+ var schema_js_1 = require("./schema.js");
24
+ Object.defineProperty(exports, "defineSyncplayGame", { enumerable: true, get: function () { return schema_js_1.defineSyncplayGame; } });
25
+ var schema_artifacts_js_1 = require("./schema-artifacts.js");
26
+ Object.defineProperty(exports, "createSchemaArtifacts", { enumerable: true, get: function () { return schema_artifacts_js_1.createSchemaArtifacts; } });
27
+ var sdk_offline_js_1 = require("./sdk-offline.js");
28
+ Object.defineProperty(exports, "createSyncplayOfflineRuntime", { enumerable: true, get: function () { return sdk_offline_js_1.createSyncplayOfflineRuntime; } });
29
+ var synctest_js_1 = require("./synctest.js");
30
+ Object.defineProperty(exports, "runSyncplaySynctest", { enumerable: true, get: function () { return synctest_js_1.runSyncplaySynctest; } });
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectVerticalCcdHit = detectVerticalCcdHit;
4
+ exports.combineDeterministicPhysicsMaterial = combineDeterministicPhysicsMaterial;
5
+ exports.cookStaticColliders = cookStaticColliders;
6
+ exports.stepTopDownBody = stepTopDownBody;
7
+ exports.stepKccLiteBody = stepKccLiteBody;
8
+ exports.quantizeFpsAim = quantizeFpsAim;
9
+ const canonical_js_1 = require("./canonical.js");
10
+ const defaultMaterial = {
11
+ friction: 0,
12
+ restitution: 0,
13
+ };
14
+ function detectVerticalCcdHit(startX, endX, wallX) {
15
+ assertInteger(startX, 'startX');
16
+ assertInteger(endX, 'endX');
17
+ assertInteger(wallX, 'wallX');
18
+ return Math.min(startX, endX) <= wallX && Math.max(startX, endX) >= wallX;
19
+ }
20
+ function combineDeterministicPhysicsMaterial(left, right) {
21
+ assertInteger(left.friction, 'left.friction');
22
+ assertInteger(right.friction, 'right.friction');
23
+ assertInteger(left.restitution, 'left.restitution');
24
+ assertInteger(right.restitution, 'right.restitution');
25
+ return {
26
+ friction: Math.floor((left.friction + right.friction) / 2),
27
+ restitution: Math.max(left.restitution, right.restitution),
28
+ };
29
+ }
30
+ function cookStaticColliders(colliders) {
31
+ const ids = new Set();
32
+ const cooked = colliders.map((collider) => {
33
+ if (ids.has(collider.id)) {
34
+ throw new Error(`Duplicate static collider id ${collider.id}`);
35
+ }
36
+ ids.add(collider.id);
37
+ assertInteger(collider.x, `${collider.id}.x`);
38
+ assertInteger(collider.y, `${collider.id}.y`);
39
+ assertInteger(collider.halfWidth, `${collider.id}.halfWidth`);
40
+ assertInteger(collider.halfHeight, `${collider.id}.halfHeight`);
41
+ return {
42
+ id: collider.id,
43
+ x: collider.x,
44
+ y: collider.y,
45
+ halfWidth: collider.halfWidth,
46
+ halfHeight: collider.halfHeight,
47
+ material: collider.material ?? defaultMaterial,
48
+ };
49
+ }).sort((left, right) => compareUniqueStrings(left.id, right.id));
50
+ const bytes = (0, canonical_js_1.canonicalStringify)(cooked);
51
+ return {
52
+ schemaVersion: 1,
53
+ hash: (0, canonical_js_1.defaultChecksum)(cooked),
54
+ bytes,
55
+ colliders: cooked,
56
+ };
57
+ }
58
+ function compareUniqueStrings(left, right) {
59
+ return left < right ? -1 : 1;
60
+ }
61
+ function stepTopDownBody(body, input, bounds) {
62
+ assertInteger(input.dx, 'input.dx');
63
+ const dy = input.dy ?? 0;
64
+ assertInteger(dy, 'input.dy');
65
+ let x = body.x + input.dx;
66
+ let y = body.y + dy;
67
+ let vx = input.dx;
68
+ let vy = dy;
69
+ if (x < bounds.minX || x > bounds.maxX) {
70
+ x = clamp(x, bounds.minX, bounds.maxX);
71
+ vx = 0;
72
+ }
73
+ if (y < bounds.minY || y > bounds.maxY) {
74
+ y = clamp(y, bounds.minY, bounds.maxY);
75
+ vy = 0;
76
+ }
77
+ return {
78
+ x,
79
+ y,
80
+ vx,
81
+ vy,
82
+ grounded: body.grounded,
83
+ };
84
+ }
85
+ function stepKccLiteBody(body, input) {
86
+ assertInteger(input.dx, 'input.dx');
87
+ let x = body.x + input.dx;
88
+ let y = body.y + body.vy;
89
+ let vy = body.vy - 1;
90
+ if (input.jump === true && body.grounded) {
91
+ vy = 7;
92
+ y += 1;
93
+ }
94
+ if (x > 24) {
95
+ x = 24;
96
+ }
97
+ if (x < -24) {
98
+ x = -24;
99
+ }
100
+ if (y <= 0) {
101
+ y = 0;
102
+ vy = 0;
103
+ }
104
+ return {
105
+ x,
106
+ y,
107
+ vx: input.dx,
108
+ vy,
109
+ grounded: y === 0,
110
+ };
111
+ }
112
+ function quantizeFpsAim(previous, input) {
113
+ assertInteger(input.yawDelta, 'input.yawDelta');
114
+ assertInteger(input.pitchDelta, 'input.pitchDelta');
115
+ const yaw = positiveModulo(previous.yaw + input.yawDelta, 360);
116
+ const pitch = clamp(previous.pitch + input.pitchDelta, -89, 89);
117
+ return {
118
+ yaw,
119
+ pitch,
120
+ originX: previous.originX,
121
+ originY: previous.originY,
122
+ };
123
+ }
124
+ function clamp(value, min, max) {
125
+ return Math.max(min, Math.min(max, value));
126
+ }
127
+ function positiveModulo(value, modulus) {
128
+ return ((value % modulus) + modulus) % modulus;
129
+ }
130
+ function assertInteger(value, name) {
131
+ if (!Number.isInteger(value)) {
132
+ throw new Error(`${name} must be an integer`);
133
+ }
134
+ }