@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,34 @@
1
+ export type PredictionCullingMode = 'off' | 'local-area';
2
+ export interface PredictionCullingOptions {
3
+ readonly mode: PredictionCullingMode;
4
+ readonly players: number;
5
+ readonly objectsPerPlayer: number;
6
+ readonly frames: number;
7
+ readonly seed: number;
8
+ readonly radius: number;
9
+ readonly includeHiddenThreat?: boolean;
10
+ }
11
+ export interface PredictionCullingResult {
12
+ readonly mode: PredictionCullingMode;
13
+ readonly players: number;
14
+ readonly objects: number;
15
+ readonly frames: number;
16
+ readonly seed: number;
17
+ readonly radius: number;
18
+ readonly averagePredictedObjects: string;
19
+ readonly minPredictedObjects: number;
20
+ readonly maxPredictedObjects: number;
21
+ readonly visibleCorrections: number;
22
+ readonly hiddenAuthoritativeInteractions: number;
23
+ readonly predictedObjectSteps: number;
24
+ readonly verifiedObjectSteps: number;
25
+ readonly culledObjectSteps: number;
26
+ readonly restoreFrame: number;
27
+ readonly predictedChecksum: string;
28
+ readonly verifiedChecksum: string;
29
+ readonly resimulatedChecksum: string;
30
+ readonly predictionFilterChecksum: string;
31
+ readonly completeChecksum: string;
32
+ readonly result: 'pass' | 'fail';
33
+ }
34
+ export declare function runPredictionCullingLab(options: PredictionCullingOptions): PredictionCullingResult;
@@ -0,0 +1,200 @@
1
+ import { defaultChecksum } from './canonical.js';
2
+ export function runPredictionCullingLab(options) {
3
+ validateOptions(options);
4
+ const objects = createObjects(options);
5
+ let previousPredicted = new Set();
6
+ let predictedTotal = 0;
7
+ let minPredictedObjects = Number.POSITIVE_INFINITY;
8
+ let maxPredictedObjects = 0;
9
+ let visibleCorrections = 0;
10
+ let hiddenAuthoritativeInteractions = 0;
11
+ let predictedObjectSteps = 0;
12
+ let verifiedObjectSteps = 0;
13
+ let predictedChecksum = '';
14
+ let verifiedChecksum = '';
15
+ let completeChecksum = '';
16
+ const filterHistory = [];
17
+ const frameHistory = [];
18
+ const restoreFrame = Math.floor(options.frames * 0.6);
19
+ for (let frame = 0; frame < options.frames; frame += 1) {
20
+ const predictedBySlot = [];
21
+ const frameState = [];
22
+ for (const object of objects) {
23
+ frameState.push(getObjectFrameState(object, frame, options.seed));
24
+ }
25
+ frameHistory.push(frameState);
26
+ const localPredicted = new Set();
27
+ for (let slot = 0; slot < options.players; slot += 1) {
28
+ const player = getPlayerPosition(slot, frame, options.seed);
29
+ const slotPredicted = [];
30
+ for (const objectState of frameState) {
31
+ const object = objects[objectState.id];
32
+ if (shouldPredictObject(options.mode, player, object, objectState, options.radius)) {
33
+ slotPredicted.push(objectState.id);
34
+ if (slot === 0) {
35
+ localPredicted.add(objectState.id);
36
+ }
37
+ }
38
+ }
39
+ predictedObjectSteps += slotPredicted.length;
40
+ predictedBySlot.push(slotPredicted);
41
+ }
42
+ for (const objectState of frameState) {
43
+ if (objectState.canAffectPlayer && !localPredicted.has(objectState.id)) {
44
+ hiddenAuthoritativeInteractions += 1;
45
+ }
46
+ }
47
+ for (const objectId of localPredicted) {
48
+ if (!previousPredicted.has(objectId) && frame > 0) {
49
+ visibleCorrections += 1;
50
+ }
51
+ }
52
+ previousPredicted = localPredicted;
53
+ filterHistory.push(predictedBySlot);
54
+ predictedTotal += localPredicted.size;
55
+ minPredictedObjects = Math.min(minPredictedObjects, localPredicted.size);
56
+ maxPredictedObjects = Math.max(maxPredictedObjects, localPredicted.size);
57
+ predictedChecksum = defaultChecksum({
58
+ frame,
59
+ predictedBySlot,
60
+ previousChecksum: predictedChecksum,
61
+ });
62
+ verifiedObjectSteps += frameState.length;
63
+ verifiedChecksum = defaultChecksum({
64
+ frame,
65
+ objects: frameState,
66
+ previousChecksum: verifiedChecksum,
67
+ });
68
+ completeChecksum = defaultChecksum({
69
+ frame,
70
+ player: getPlayerPosition(0, frame, options.seed),
71
+ objects: frameState,
72
+ previousChecksum: completeChecksum,
73
+ });
74
+ }
75
+ const resimulatedChecksum = resimulateVerifiedChecksum(frameHistory, restoreFrame);
76
+ const predictionFilterChecksum = defaultChecksum(filterHistory);
77
+ const culledObjectSteps = options.mode === 'off' ? 0 : verifiedObjectSteps * options.players - predictedObjectSteps;
78
+ return {
79
+ mode: options.mode,
80
+ players: options.players,
81
+ objects: objects.length,
82
+ frames: options.frames,
83
+ seed: options.seed,
84
+ radius: options.radius,
85
+ averagePredictedObjects: (predictedTotal / options.frames).toFixed(2),
86
+ minPredictedObjects,
87
+ maxPredictedObjects,
88
+ visibleCorrections,
89
+ hiddenAuthoritativeInteractions,
90
+ predictedObjectSteps,
91
+ verifiedObjectSteps,
92
+ culledObjectSteps,
93
+ restoreFrame,
94
+ predictedChecksum,
95
+ verifiedChecksum,
96
+ resimulatedChecksum,
97
+ predictionFilterChecksum,
98
+ completeChecksum,
99
+ result: hiddenAuthoritativeInteractions === 0 && verifiedChecksum === resimulatedChecksum ? 'pass' : 'fail',
100
+ };
101
+ }
102
+ function createObjects(options) {
103
+ const objects = [];
104
+ for (let slot = 0; slot < options.players; slot += 1) {
105
+ for (let index = 0; index < options.objectsPerPlayer; index += 1) {
106
+ const id = objects.length;
107
+ objects.push({
108
+ id,
109
+ ownerSlot: slot,
110
+ offsetX: ((index * 37 + options.seed) % 90) - 45,
111
+ offsetY: ((index * 53 + options.seed) % 90) - 45,
112
+ alwaysPredict: index % 17 === 0,
113
+ canAffectPlayer: index % 17 === 0,
114
+ });
115
+ }
116
+ }
117
+ if (options.includeHiddenThreat === true) {
118
+ objects.push({
119
+ id: objects.length,
120
+ ownerSlot: Math.max(1, options.players - 1),
121
+ offsetX: 10_000,
122
+ offsetY: 10_000,
123
+ alwaysPredict: false,
124
+ canAffectPlayer: true,
125
+ });
126
+ }
127
+ return objects;
128
+ }
129
+ function shouldPredictObject(mode, player, object, objectState, radius) {
130
+ if (mode === 'off') {
131
+ return true;
132
+ }
133
+ if (object.alwaysPredict) {
134
+ return true;
135
+ }
136
+ const dx = objectState.x - player.x;
137
+ const dy = objectState.y - player.y;
138
+ return dx * dx + dy * dy <= radius * radius;
139
+ }
140
+ function getPlayerPosition(slot, frame, seed) {
141
+ return {
142
+ x: slot * 100 + ((frame * 3 + seed) % 37),
143
+ y: ((frame * 5 + seed) % 41) - 20,
144
+ };
145
+ }
146
+ function getObjectFrameState(object, frame, seed) {
147
+ const owner = getPlayerPosition(object.ownerSlot, frame, seed);
148
+ return {
149
+ id: object.id,
150
+ x: owner.x + object.offsetX + ((frame + object.id) % 7) - 3,
151
+ y: owner.y + object.offsetY + ((frame * 2 + object.id) % 7) - 3,
152
+ active: (frame + object.id) % 29 === 0 ? 0 : 1,
153
+ canAffectPlayer: object.canAffectPlayer,
154
+ };
155
+ }
156
+ function validateOptions(options) {
157
+ if (options.mode !== 'off' && options.mode !== 'local-area') {
158
+ throw new Error('prediction culling mode must be off or local-area');
159
+ }
160
+ if (!Number.isInteger(options.players) || options.players < 1 || options.players > 128) {
161
+ throw new Error('prediction culling players must be between 1 and 128');
162
+ }
163
+ if (!Number.isInteger(options.objectsPerPlayer) || options.objectsPerPlayer < 1 || options.objectsPerPlayer > 128) {
164
+ throw new Error('objectsPerPlayer must be between 1 and 128');
165
+ }
166
+ if (!Number.isInteger(options.frames) || options.frames < 1) {
167
+ throw new Error('prediction culling frames must be at least 1');
168
+ }
169
+ if (!Number.isInteger(options.seed)) {
170
+ throw new Error('prediction culling seed must be an integer');
171
+ }
172
+ if (!Number.isInteger(options.radius) || options.radius < 1) {
173
+ throw new Error('prediction culling radius must be a positive integer');
174
+ }
175
+ }
176
+ function resimulateVerifiedChecksum(frameHistory, restoreFrame) {
177
+ let checksum = '';
178
+ for (let frame = 0; frame < frameHistory.length; frame += 1) {
179
+ if (frame === restoreFrame) {
180
+ checksum = resimulateVerifiedChecksumPrefix(frameHistory, frame);
181
+ }
182
+ checksum = defaultChecksum({
183
+ frame,
184
+ objects: frameHistory[frame],
185
+ previousChecksum: checksum,
186
+ });
187
+ }
188
+ return checksum;
189
+ }
190
+ function resimulateVerifiedChecksumPrefix(frameHistory, endFrameExclusive) {
191
+ let checksum = '';
192
+ for (let frame = 0; frame < endFrameExclusive; frame += 1) {
193
+ checksum = defaultChecksum({
194
+ frame,
195
+ objects: frameHistory[frame],
196
+ previousChecksum: checksum,
197
+ });
198
+ }
199
+ return checksum;
200
+ }
@@ -0,0 +1,115 @@
1
+ import type { DeterministicEventRecord } from './events.js';
2
+ export type ProtocolRollbackGame = 'lab' | 'counter-duel' | 'moderate-state' | 'command-bursts';
3
+ export type ProtocolPredictionPolicy = 'repeat-last' | 'neutral';
4
+ export interface ProtocolRollbackLabOptions {
5
+ readonly game?: ProtocolRollbackGame;
6
+ readonly players: number;
7
+ readonly frames: number;
8
+ readonly seed: number;
9
+ readonly minDelayFrames: number;
10
+ readonly maxDelayFrames: number;
11
+ readonly bundleSizeFrames?: number;
12
+ readonly inputDelayFrames?: number;
13
+ readonly adaptiveInputDelay?: boolean;
14
+ readonly maxAdaptiveInputDelayFrames?: number;
15
+ readonly duplicatePermille?: number;
16
+ readonly lossPermille?: number;
17
+ readonly resendIntervalFrames?: number;
18
+ readonly maxResendAttempts?: number;
19
+ readonly disconnectStartFrame?: number;
20
+ readonly disconnectEndFrame?: number;
21
+ readonly lateJoinSlot?: number;
22
+ readonly lateJoinFrame?: number;
23
+ readonly spectatorSlot?: number;
24
+ readonly spectatorJoinFrame?: number;
25
+ readonly latencySkewSlot?: number;
26
+ readonly latencySkewFrames?: number;
27
+ readonly botSlots?: readonly number[];
28
+ readonly desyncFrame?: number;
29
+ readonly desyncSlot?: number;
30
+ readonly expectDesync?: boolean;
31
+ readonly eventTimelineLimit?: number;
32
+ readonly predictionPolicy?: ProtocolPredictionPolicy;
33
+ }
34
+ export interface ProtocolRollbackLabResult {
35
+ readonly game: ProtocolRollbackGame;
36
+ readonly frames: number;
37
+ readonly players: number;
38
+ readonly confirmations: number;
39
+ readonly localInputConfirmations: number;
40
+ readonly localInputRollbacks: number;
41
+ readonly bundledInputMessages: number;
42
+ readonly bundleSizeFrames: number;
43
+ readonly inputDelayFrames: number;
44
+ readonly adaptiveInputDelay: boolean;
45
+ readonly finalInputDelayFrames: number;
46
+ readonly maxObservedInputDelayFrames: number;
47
+ readonly inputDelayAdjustments: number;
48
+ readonly deliveries: number;
49
+ readonly duplicates: number;
50
+ readonly lost: number;
51
+ readonly disconnectDrops: number;
52
+ readonly canceledRetries: number;
53
+ readonly absentInputFrames: number;
54
+ readonly botInputFrames: number;
55
+ readonly reorders: number;
56
+ readonly rollbacks: number;
57
+ readonly maxRollbackDepth: number;
58
+ readonly deliveryDelaySamples: readonly number[];
59
+ readonly rollbackDepthSamples: readonly number[];
60
+ readonly eventTimeline: ProtocolRollbackEventTimeline;
61
+ readonly commandDeliveries: number;
62
+ readonly commandDuplicates: number;
63
+ readonly commandLost: number;
64
+ readonly commandDisconnectDrops: number;
65
+ readonly commandReorders: number;
66
+ readonly commandDeliveryDelaySamples: readonly number[];
67
+ readonly commandRejected: number;
68
+ readonly commandRejectionCounts: Readonly<Record<string, number>>;
69
+ readonly commandDuplicateDrops: number;
70
+ readonly commandRollbackConverged: boolean;
71
+ readonly commandRollbackObserved: boolean;
72
+ readonly commandReplayChecksum: string;
73
+ readonly commandAuthorityChecksum: string;
74
+ readonly commandClientChecksum: string;
75
+ readonly spectatorReconstructions: number;
76
+ readonly spectatorReconstructionChecksum: string;
77
+ readonly spectatorInputFrames: number;
78
+ readonly spectatorCommandRejected: number;
79
+ readonly lateJoinReconstructions: number;
80
+ readonly lateJoinReconstructionChecksum: string;
81
+ readonly staleJoinRejected: boolean;
82
+ readonly predictionPolicy: ProtocolPredictionPolicy;
83
+ readonly predictedInputFrames: number;
84
+ readonly neutralPredictions: number;
85
+ readonly repeatLastPredictions: number;
86
+ readonly repeatLastNonDefaultPredictions: number;
87
+ readonly predictionFallbackChecksum: string;
88
+ readonly authorityChecksum: string;
89
+ readonly clientChecksum: string;
90
+ readonly result: 'pass' | 'desync';
91
+ }
92
+ export interface ProtocolRollbackEventPayload {
93
+ readonly kind: 'input-prediction';
94
+ readonly frame: number;
95
+ readonly slot: number;
96
+ }
97
+ export interface ProtocolRollbackEventTimeline {
98
+ readonly totalRecords: number;
99
+ readonly sampledRecords: readonly DeterministicEventRecord<ProtocolRollbackEventPayload>[];
100
+ readonly truncatedRecords: number;
101
+ readonly predicted: number;
102
+ readonly confirmed: number;
103
+ readonly canceled: number;
104
+ readonly verifiedOnly: number;
105
+ }
106
+ export declare function runProtocolRollbackLab(options: ProtocolRollbackLabOptions): ProtocolRollbackLabResult;
107
+ export declare function runProtocolLabInternalCoverageProbe(): {
108
+ readonly eventPredicted: number;
109
+ readonly eventSampled: number;
110
+ readonly invalidCommandFrame: number;
111
+ readonly defaultPowerHealth: number;
112
+ readonly validationReasons: readonly (string | undefined)[];
113
+ readonly normalizedCommandIds: readonly string[];
114
+ readonly sortedComparison: readonly number[];
115
+ };