@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,356 @@
1
+ import { defaultChecksum } from '../canonical.js';
2
+ import { fixedCircle, circleIntersects } from '../collision.js';
3
+ import { createDeterministicEventTimeline } from '../events.js';
4
+ import { createOfflineSession } from '../offline-session.js';
5
+ import { DeterministicRandom } from '../random.js';
6
+ import { verifyReplay } from '../replay.js';
7
+ import { defineSyncplayGame } from '../schema.js';
8
+ const arenaHalfExtent = 2048;
9
+ const playerRadius = 24;
10
+ const maxVelocity = 48;
11
+ const dashImpulse = 9;
12
+ const thrustScale = 3;
13
+ export const fixedArenaDefaultInput = {
14
+ thrustX: 0,
15
+ thrustY: 0,
16
+ dash: false,
17
+ };
18
+ export function createFixedArenaDescriptor(maxPlayers = 128) {
19
+ return {
20
+ deterministicVersion: 'fixed-arena@1',
21
+ tickRate: 30,
22
+ maxPlayers,
23
+ input: {
24
+ id: 'fixed-arena-input/v1',
25
+ fields: [
26
+ { name: 'thrustX', kind: 'integer', policy: 'repeat', defaultValue: 0, min: -1, max: 1 },
27
+ { name: 'thrustY', kind: 'integer', policy: 'repeat', defaultValue: 0, min: -1, max: 1 },
28
+ { name: 'dash', kind: 'boolean', policy: 'command', defaultValue: false },
29
+ ],
30
+ },
31
+ state: {
32
+ id: 'fixed-arena-state/v1',
33
+ fields: [
34
+ { name: 'frame', kind: 'integer', numericMode: 'integer', checksummed: true },
35
+ { name: 'x', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: -8192, max: 8192 },
36
+ { name: 'y', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: -8192, max: 8192 },
37
+ { name: 'vx', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: -maxVelocity, max: maxVelocity },
38
+ { name: 'vy', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: -maxVelocity, max: maxVelocity },
39
+ { name: 'score', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: 0, max: 1_000_000 },
40
+ { name: 'collisions', kind: 'integer', numericMode: 'integer', collectionOrdering: 'indexed', checksummed: true, min: 0, max: 1_000_000 },
41
+ ],
42
+ },
43
+ systems: [{ id: 'input' }, { id: 'movement' }, { id: 'bounds' }, { id: 'collision' }],
44
+ };
45
+ }
46
+ export function createFixedArenaSession(players, seed, options = {}) {
47
+ // Stamp the CONTENT-HASHED identity so descriptor-based verification
48
+ // (verifyReplayWithDescriptor) agrees with these replays.
49
+ const identity = defineSyncplayGame(createFixedArenaDescriptor(players)).replayIdentity;
50
+ return createOfflineSession({
51
+ tickRate: 30,
52
+ playerCount: players,
53
+ initialState: createInitialFixedArenaState(players, seed),
54
+ step: fixedArenaStep,
55
+ defaultInput: fixedArenaDefaultInput,
56
+ inputSchemaId: identity.inputSchemaId,
57
+ stateSchemaId: identity.stateSchemaId,
58
+ deterministicVersion: 'fixed-arena@1',
59
+ randomSeed: seed,
60
+ snapshotBufferSize: options.snapshotBufferSize,
61
+ replayRecordingMode: options.replayRecordingMode,
62
+ });
63
+ }
64
+ export function runFixedArenaExample(options) {
65
+ validateFixedArenaOptions(options);
66
+ const session = createFixedArenaSession(options.players, options.seed);
67
+ const inputRandom = new DeterministicRandom(options.seed);
68
+ const eventTimeline = createDeterministicEventTimeline();
69
+ for (let frame = 0; frame < options.frames; frame += 1) {
70
+ for (let slot = 0; slot < options.players; slot += 1) {
71
+ session.setInput(slot, makeFixedArenaInput(inputRandom));
72
+ }
73
+ session.stepFrames(1);
74
+ const nextState = session.getState();
75
+ for (const pair of findFixedArenaCollisionPairs(nextState)) {
76
+ eventTimeline.emitVerifiedOnly('fixed-arena.collision', nextState.frame, {
77
+ a: pair.a,
78
+ b: pair.b,
79
+ ax: nextState.x[pair.a],
80
+ ay: nextState.y[pair.a],
81
+ bx: nextState.x[pair.b],
82
+ by: nextState.y[pair.b],
83
+ }, `fixed-arena.collision:${nextState.frame}:${pair.a}:${pair.b}`);
84
+ }
85
+ }
86
+ const replay = session.exportReplay();
87
+ if (options.verify === true) {
88
+ verifyFixedArenaReplay(replay);
89
+ }
90
+ const finalChecksum = replay.checksums.at(-1)?.checksum ?? defaultChecksum(session.getState());
91
+ return {
92
+ frames: options.frames,
93
+ players: options.players,
94
+ events: eventTimeline.records().length,
95
+ replayChecksums: replay.checksums.length,
96
+ finalChecksum,
97
+ verified: options.verify === true,
98
+ result: 'pass',
99
+ replay,
100
+ renderState: projectFixedArenaRenderState(session.getState()),
101
+ eventTimeline: eventTimeline.records(),
102
+ };
103
+ }
104
+ export function verifyFixedArenaReplay(replay) {
105
+ const identity = defineSyncplayGame(createFixedArenaDescriptor(replay.playerCount)).replayIdentity;
106
+ const result = verifyReplay({
107
+ replay,
108
+ step: fixedArenaStep,
109
+ defaultInput: fixedArenaDefaultInput,
110
+ inputSchemaId: identity.inputSchemaId,
111
+ stateSchemaId: identity.stateSchemaId,
112
+ deterministicVersion: 'fixed-arena@1',
113
+ hydrateInput: hydrateFixedArenaInput,
114
+ });
115
+ if (result.mismatches !== 0) {
116
+ throw new Error(`Fixed Arena replay mismatch: ${result.mismatches}`);
117
+ }
118
+ }
119
+ export function projectFixedArenaRenderState(state) {
120
+ return {
121
+ players: state.x.map((x, slot) => ({
122
+ key: `player-${slot}`,
123
+ x,
124
+ y: state.y[slot],
125
+ radius: playerRadius,
126
+ color: slot % 2 === 0 ? 'cyan' : 'magenta',
127
+ score: state.score[slot],
128
+ collisions: state.collisions[slot],
129
+ })),
130
+ bounds: {
131
+ minX: -arenaHalfExtent,
132
+ minY: -arenaHalfExtent,
133
+ maxX: arenaHalfExtent,
134
+ maxY: arenaHalfExtent,
135
+ },
136
+ };
137
+ }
138
+ export function projectFixedArenaReferenceView(state) {
139
+ const leaderboard = state.score
140
+ .map((score, slot) => ({
141
+ slot,
142
+ score,
143
+ collisions: state.collisions[slot],
144
+ color: fixedArenaColor(slot),
145
+ }))
146
+ .sort((left, right) => {
147
+ if (left.score !== right.score) {
148
+ return right.score - left.score;
149
+ }
150
+ return left.slot - right.slot;
151
+ });
152
+ const ranks = new Map(leaderboard.map((entry, index) => [entry.slot, index + 1]));
153
+ const topScore = leaderboard[0]?.score ?? 0;
154
+ return {
155
+ camera: {
156
+ position: [0, 0, 10],
157
+ zoom: 0.1,
158
+ },
159
+ arena: {
160
+ width: (arenaHalfExtent * 2) / 100,
161
+ height: (arenaHalfExtent * 2) / 100,
162
+ wallThickness: 0.2,
163
+ backgroundColor: '#071014',
164
+ wallColor: '#10242b',
165
+ },
166
+ players: state.x.map((x, slot) => ({
167
+ key: `player-${slot}`,
168
+ slot,
169
+ position: [x / 100, state.y[slot] / 100, 0],
170
+ scale: [1 + minInt(state.score[slot], 20) / 50, 1 + minInt(state.collisions[slot], 10) / 40, 1],
171
+ color: fixedArenaColor(slot),
172
+ ringColor: ranks.get(slot) === 1 ? '#f5d76e' : '#d7eef2',
173
+ velocity: [state.vx[slot] / 100, state.vy[slot] / 100, 0],
174
+ score: state.score[slot],
175
+ collisions: state.collisions[slot],
176
+ rank: ranks.get(slot) ?? state.x.length,
177
+ })),
178
+ leaderboard,
179
+ debug: {
180
+ frame: state.frame,
181
+ players: state.x.length,
182
+ topScore,
183
+ },
184
+ };
185
+ }
186
+ export function makeFixedArenaInput(random) {
187
+ return {
188
+ thrustX: random.nextInt(-1, 1),
189
+ thrustY: random.nextInt(-1, 1),
190
+ dash: random.nextInt(0, 31) === 0,
191
+ };
192
+ }
193
+ export function createInitialFixedArenaState(players, seed) {
194
+ const columns = ceilSqrtInt(players);
195
+ const spacing = maxInt(playerRadius * 3, truncDivTowardZero(arenaHalfExtent * 2, columns + 1));
196
+ const random = new DeterministicRandom(seed).fork('fixed-arena-spawn');
197
+ return {
198
+ frame: 0,
199
+ x: Array.from({ length: players }, (_, slot) => {
200
+ const column = slot % columns;
201
+ return -arenaHalfExtent + spacing * (column + 1) + random.nextInt(-8, 8);
202
+ }),
203
+ y: Array.from({ length: players }, (_, slot) => {
204
+ const row = truncDivTowardZero(slot, columns);
205
+ return -arenaHalfExtent + spacing * (row + 1) + random.nextInt(-8, 8);
206
+ }),
207
+ vx: Array.from({ length: players }, () => 0),
208
+ vy: Array.from({ length: players }, () => 0),
209
+ score: Array.from({ length: players }, () => 0),
210
+ collisions: Array.from({ length: players }, () => 0),
211
+ };
212
+ }
213
+ export function fixedArenaStep(state, inputs) {
214
+ const x = [...state.x];
215
+ const y = [...state.y];
216
+ const vx = [...state.vx];
217
+ const vy = [...state.vy];
218
+ const score = [...state.score];
219
+ const collisions = [...state.collisions];
220
+ for (let slot = 0; slot < inputs.length; slot += 1) {
221
+ const input = inputs[slot];
222
+ const impulse = input.dash ? dashImpulse : thrustScale;
223
+ vx[slot] = clamp(vx[slot] + input.thrustX * impulse, -maxVelocity, maxVelocity);
224
+ vy[slot] = clamp(vy[slot] + input.thrustY * impulse, -maxVelocity, maxVelocity);
225
+ x[slot] += vx[slot];
226
+ y[slot] += vy[slot];
227
+ if (x[slot] < -arenaHalfExtent || x[slot] > arenaHalfExtent) {
228
+ x[slot] = clamp(x[slot], -arenaHalfExtent, arenaHalfExtent);
229
+ vx[slot] = -truncDivTowardZero(vx[slot], 2);
230
+ }
231
+ if (y[slot] < -arenaHalfExtent || y[slot] > arenaHalfExtent) {
232
+ y[slot] = clamp(y[slot], -arenaHalfExtent, arenaHalfExtent);
233
+ vy[slot] = -truncDivTowardZero(vy[slot], 2);
234
+ }
235
+ }
236
+ for (let left = 0; left < inputs.length; left += 1) {
237
+ for (let right = left + 1; right < inputs.length; right += 1) {
238
+ if (!circleIntersects(fixedCircle({ x: x[left], y: y[left] }, playerRadius), fixedCircle({ x: x[right], y: y[right] }, playerRadius))) {
239
+ continue;
240
+ }
241
+ const axis = chooseResolutionAxis(x[left] - x[right], y[left] - y[right], left, right);
242
+ x[left] += axis.x * playerRadius;
243
+ y[left] += axis.y * playerRadius;
244
+ x[right] -= axis.x * playerRadius;
245
+ y[right] -= axis.y * playerRadius;
246
+ vx[left] = -truncDivTowardZero(vx[left], 2);
247
+ vy[left] = -truncDivTowardZero(vy[left], 2);
248
+ vx[right] = -truncDivTowardZero(vx[right], 2);
249
+ vy[right] = -truncDivTowardZero(vy[right], 2);
250
+ collisions[left] += 1;
251
+ collisions[right] += 1;
252
+ if ((state.frame + left + right) % 2 === 0) {
253
+ score[left] += 1;
254
+ }
255
+ else {
256
+ score[right] += 1;
257
+ }
258
+ }
259
+ }
260
+ return {
261
+ frame: state.frame + 1,
262
+ x,
263
+ y,
264
+ vx,
265
+ vy,
266
+ score,
267
+ collisions,
268
+ };
269
+ }
270
+ function findFixedArenaCollisionPairs(state) {
271
+ const pairs = [];
272
+ for (let left = 0; left < state.x.length; left += 1) {
273
+ for (let right = left + 1; right < state.x.length; right += 1) {
274
+ if (circleIntersects(fixedCircle({ x: state.x[left], y: state.y[left] }, playerRadius), fixedCircle({ x: state.x[right], y: state.y[right] }, playerRadius))) {
275
+ pairs.push({ a: left, b: right });
276
+ }
277
+ }
278
+ }
279
+ return pairs;
280
+ }
281
+ function chooseResolutionAxis(dx, dy, left, right) {
282
+ if (absInt(dx) > absInt(dy)) {
283
+ return { x: dx >= 0 ? 1 : -1, y: 0 };
284
+ }
285
+ if (absInt(dy) > 0) {
286
+ return { x: 0, y: dy >= 0 ? 1 : -1 };
287
+ }
288
+ return { x: left < right ? -1 : 1, y: 0 };
289
+ }
290
+ function hydrateFixedArenaInput(recordedInput) {
291
+ if (recordedInput === null ||
292
+ typeof recordedInput !== 'object' ||
293
+ typeof recordedInput.thrustX !== 'number' ||
294
+ typeof recordedInput.thrustY !== 'number' ||
295
+ typeof recordedInput.dash !== 'boolean') {
296
+ throw new Error('Invalid Fixed Arena replay input');
297
+ }
298
+ return {
299
+ thrustX: clampInput(recordedInput.thrustX),
300
+ thrustY: clampInput(recordedInput.thrustY),
301
+ dash: recordedInput.dash,
302
+ };
303
+ }
304
+ function clampInput(value) {
305
+ if (!Number.isInteger(value)) {
306
+ throw new Error('Fixed Arena input thrust must be an integer');
307
+ }
308
+ return clamp(value, -1, 1);
309
+ }
310
+ function clamp(value, min, max) {
311
+ if (value < min) {
312
+ return min;
313
+ }
314
+ if (value > max) {
315
+ return max;
316
+ }
317
+ return value;
318
+ }
319
+ function ceilSqrtInt(value) {
320
+ let candidate = 1;
321
+ while (candidate * candidate < value) {
322
+ candidate += 1;
323
+ }
324
+ return candidate;
325
+ }
326
+ function maxInt(left, right) {
327
+ return left >= right ? left : right;
328
+ }
329
+ function minInt(left, right) {
330
+ return left <= right ? left : right;
331
+ }
332
+ function absInt(value) {
333
+ return value < 0 ? -value : value;
334
+ }
335
+ function fixedArenaColor(slot) {
336
+ return slot % 4 === 0 ? '#40d9ff' : slot % 4 === 1 ? '#ff4fd8' : slot % 4 === 2 ? '#7cff6b' : '#ffcc4d';
337
+ }
338
+ function truncDivTowardZero(value, divisor) {
339
+ if (!Number.isInteger(value) || !Number.isInteger(divisor) || divisor <= 0) {
340
+ throw new Error('Integer division requires integer value and positive integer divisor');
341
+ }
342
+ const positive = value >= 0 ? value : -value;
343
+ const quotient = (positive - (positive % divisor)) / divisor;
344
+ return value >= 0 ? quotient : -quotient;
345
+ }
346
+ function validateFixedArenaOptions(options) {
347
+ if (!Number.isInteger(options.players) || options.players < 2 || options.players > 128) {
348
+ throw new Error('Fixed Arena requires 2 to 128 players');
349
+ }
350
+ if (!Number.isInteger(options.frames) || options.frames < 1) {
351
+ throw new Error('Fixed Arena requires at least one frame');
352
+ }
353
+ if (!Number.isInteger(options.seed)) {
354
+ throw new Error('Fixed Arena seed must be an integer');
355
+ }
356
+ }
@@ -0,0 +1,101 @@
1
+ export { canonicalize, canonicalStringify, cloneCanonical, decodeCanonicalValue, decodeUtf8, defaultChecksum, encodeUtf8 } from './canonical.js';
2
+ export type { CanonicalValue } from './canonical.js';
3
+ export * from './animation.js';
4
+ export { cookDeterministicBotAsset, createDeterministicBotBlackboard, getBlackboardValue, runDeterministicBotSimulation, selectDeterministicUtility, tickDeterministicBehaviorTree, tickDeterministicBehaviorTreeWithMemory, tickDeterministicHfsm, } from './bot-primitives.js';
5
+ export * from './bot-documents.js';
6
+ export * from './commands.js';
7
+ export * from './config-bundle.js';
8
+ export * from './input-timeline.js';
9
+ export * from './lag-compensation3d.js';
10
+ export type { CookedDeterministicBotAsset, DeterministicBehaviorTreeNode, DeterministicBehaviorTreeStatus, DeterministicBehaviorTreeTick, DeterministicBlackboardEntry, DeterministicBlackboardValue, DeterministicBotAssetSource, DeterministicBotBlackboard, DeterministicBotSimulationMetrics, DeterministicHfsmAgent, DeterministicHfsmDefinition, DeterministicHfsmState, DeterministicHfsmTransition, DeterministicUtilityConsideration, DeterministicUtilitySelection, } from './bot-primitives.js';
11
+ export { assertAssetManifestMatches, cookDeterministicAssets, materializePrototypeEntities, stableAssetCookJson, } from './asset-cooking.js';
12
+ export type { DeterministicAssetCookManifest, DeterministicAssetCookResult, DeterministicAssetDependency, DeterministicAssetRecord, DeterministicAssetSource, DeterministicCookedAsset, DeterministicPrototypeEntity, } from './asset-cooking.js';
13
+ export type { CertificationBudgetResult, CertificationBudgets, CertificationBotReplacementFixture, CertificationBotReplacementMetrics, CertificationEcsLiteFixture, CertificationEcsLiteMetrics, CertificationEventCallbacksFixture, CertificationEventCallbacksMetrics, CertificationExternalPhysicsGateFixture, CertificationExternalPhysicsGateMetrics, CertificationFixture, CertificationFixtureKind, CertificationFixtureReport, CertificationFixtureTier, CertificationFixedFoundationFixture, CertificationFixedFoundationMetrics, CertificationFrameModelMetrics, CertificationGenre128Fixture, CertificationGenre128Metrics, CertificationKccLiteFixture, CertificationKccLiteMetrics, CertificationManifest, CertificationMetrics, CertificationNetcodeFixture, CertificationNetcodeMetrics, CertificationNetcodeShape, CertificationPhysicsBuiltinFixture, CertificationPhysicsBuiltinMetrics, CertificationPredictionCullingFixture, CertificationPredictionCullingMetrics, CertificationProjectileHitscanFixture, CertificationProjectileHitscanMetrics, CertificationProtocolMatrixFixture, CertificationProtocolMatrixMetrics, CertificationProtocolProfileId, CertificationProtocolProfileMetrics, CertificationSchemaToolingFixture, CertificationSchemaToolingMetrics, CertificationStaticAnalysisFixture, CertificationStaticAnalysisMetrics, CertificationDesyncArtifact, CertificationReplayNodeFixture, CertificationReplayNodeMetrics, CertificationResult, CertificationRuntimeTarget, CertificationSuiteReport, CertificationSuiteRun, } from './certification.js';
14
+ export { aabbContainsPoint, aabbIntersects, circleIntersects, circleIntersectsAabb, fixedAabb, fixedCircle, fixedVec2, sortAabbsByStableId, translateAabb, } from './collision.js';
15
+ export type { FixedAabb, FixedCircle, FixedVec2 } from './collision.js';
16
+ export { createStableIndexedMap, deterministicShuffle, stableEntries, stableSortedKeys } from './collections.js';
17
+ export type { StableIndexedEntry } from './collections.js';
18
+ export { combineDeterministicPhysicsMaterial, cookStaticColliders, detectVerticalCcdHit, quantizeFpsAim, stepKccLiteBody, stepTopDownBody, } from './deterministic-primitives.js';
19
+ export type { CookedDeterministicStaticCollider, CookedStaticColliderSet, DeterministicPhysicsMaterial, DeterministicStaticCollider, FpsAimInput, MovementBody, MovementInput, QuantizedFpsAim, } from './deterministic-primitives.js';
20
+ export { createDeterministicEventEffectsAdapter } from './effects-adapter.js';
21
+ export type { DeterministicEffectDispatch, DeterministicEffectTarget, DeterministicEventEffectsAdapter, DeterministicEventEffectsAdapterConfig, DeterministicRenderSafeEffect, } from './effects-adapter.js';
22
+ export { createDeterministicEventTimeline, filterDeterministicEventsForPlayer, runDeterministicEventKeywordFixture } from './events.js';
23
+ export type { DeterministicEventDeliveryScope, DeterministicEventEmitOptions, DeterministicEventKeywordFixtureResult, DeterministicEventPredictionState, DeterministicEventRecord, DeterministicEventTimeline, } from './events.js';
24
+ export { createEcsLiteWorld } from './ecs-lite.js';
25
+ export type { EcsComponentName, EcsEntityId, EcsLiteQueryResult, EcsLiteSnapshot, EcsLiteWorld } from './ecs-lite.js';
26
+ export * from './engine-core-proof.js';
27
+ export * from './engine-complete.js';
28
+ export * from './engine-runtime.js';
29
+ export * from './deterministic-session.js';
30
+ export { deterministicButtonInitialState, runDeterministicButtonFixture, runDeterministicDescriptorButtonFixture, stepDeterministicButton, } from './input-button.js';
31
+ export type { DeterministicButtonFixtureResult, DeterministicButtonState, DeterministicButtonStep, DeterministicDescriptorButtonFixtureResult, } from './input-button.js';
32
+ export { createCounterDuelSession, counterDuelDefaultInput, makeCounterDuelInput, runCounterDuelExample, verifyCounterDuelReplay, } from './examples/counter-duel.js';
33
+ export { createFixedArenaDescriptor, createFixedArenaSession, createInitialFixedArenaState, fixedArenaDefaultInput, fixedArenaStep, makeFixedArenaInput, projectFixedArenaReferenceView, projectFixedArenaRenderState, runFixedArenaExample, verifyFixedArenaReplay, } from './examples/fixed-arena.js';
34
+ export type { CounterDuelInput, CounterDuelOptions, CounterDuelResult, CounterDuelSessionOptions, CounterDuelState, } from './examples/counter-duel.js';
35
+ export type { FixedArenaInput, FixedArenaOptions, FixedArenaReferenceView, FixedArenaRenderState, FixedArenaResult, FixedArenaSessionOptions, FixedArenaState, } from './examples/fixed-arena.js';
36
+ export { SyncplayError } from './errors.js';
37
+ export { createDeterministicMath } from './math.js';
38
+ export { createDeterministicMockNetworkAdapter } from './mock-network-adapter.js';
39
+ export type { DeterministicMockNetworkAdapter, DeterministicMockNetworkReplay } from './mock-network-adapter.js';
40
+ export { runDeterministicMovementCrowdSimulation, rewindDeterministicTargets, runDeterministicMovementSimulation, stepDeterministicFpsAim, stepDeterministicKcc2D, stepDeterministicTopDownMover, validateDeterministicLagCompensatedHit, } from './movement.js';
41
+ export * from './movement3d.js';
42
+ export type { DeterministicFpsAimState, DeterministicFpsInput, DeterministicKccBody, DeterministicKccInput, DeterministicKccStepResult, DeterministicMovementCrowdMetrics, DeterministicMovementSimulationMetrics, DeterministicMovementWorld, DeterministicMovingPlatform, DeterministicOneWayPlatform, DeterministicSlope, DeterministicMovementStep, DeterministicTargetSnapshot, DeterministicTopDownBody, DeterministicTopDownBounds, DeterministicTopDownInput, } from './movement.js';
43
+ export { applyDeterministicReciprocalAvoidance, cookDeterministicNavigationGraph, cookTilemapNavigationGraph, createDeterministicFlowField, findDeterministicPath, smoothDeterministicPath, stepDeterministicNavigationAgents, } from './navigation.js';
44
+ export * from './navmesh.js';
45
+ export * from './engine-parity-matrix.js';
46
+ export type { CookedDeterministicNavigationGraph, DeterministicFlowField, DeterministicNavEdge, DeterministicNavigationAgent, DeterministicNavigationGraphSource, DeterministicNavigationStepOptions, DeterministicNavigationStepResult, DeterministicNavNode, DeterministicNavRegion, DeterministicPathQuery, DeterministicPathResult, DeterministicTilemapSource, } from './navigation.js';
47
+ export { runNumberLab } from './number-lab.js';
48
+ export { createOfflineSession } from './offline-session.js';
49
+ export { createSyncplayOfflineRuntime } from './sdk-offline.js';
50
+ export * from './rollback-history.js';
51
+ export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D, } from './physics2d.js';
52
+ export * from './physics3d.js';
53
+ export type { DeterministicBodyKind, DeterministicContactEvent2D, DeterministicContactEventType, DeterministicPhysicsAabbQuery2D, DeterministicPhysicsBody2D, DeterministicPhysicsConstraint2D, DeterministicPhysicsHit2D, DeterministicPhysicsQueryOptions2D, DeterministicPhysicsRaycastQuery2D, DeterministicPhysicsCircleCastQuery2D, DeterministicPhysicsShape2D, DeterministicPhysicsShapeOverlapQuery2D, DeterministicPhysicsStepOptions2D, DeterministicPhysicsStepResult2D, DeterministicPhysicsWorld2D, } from './physics2d.js';
54
+ export { runPhysicsCert, runRapierPhysicsCert } from './physics-cert.js';
55
+ export { runPredictionCullingLab } from './prediction-culling.js';
56
+ export { createDeterministicR3fDebugOverlay, createDeterministicR3fRenderAdapter, interpolateDeterministicRenderNumber, interpolateDeterministicRenderVec2, } from './r3f-render-adapter.js';
57
+ export { runProtocolRollbackLab } from './protocol-lab.js';
58
+ export { createProtocolRollbackReport, diffDeterministicReports, renderDeterministicReportHtml, stableReportDiffJson, stableReportJson, } from './reports.js';
59
+ export { diffReplayFrames, explainReplayChecksum, inspectReplayFrame, inspectReplayFrameWithDescriptor, stableFrameDiffJson, stableFrameDumpJson, } from './replay-inspect.js';
60
+ export { deterministicSampleSceneIds, runAllDeterministicSampleScenes, runDeterministicIntegratedHeadlessScene, runDeterministicSampleScene, } from './sample-scenes.js';
61
+ export type { DeterministicIntegratedHeadlessSceneResult, DeterministicSampleSceneId, DeterministicSampleSceneResult, } from './sample-scenes.js';
62
+ export { DeterministicRandom } from './random.js';
63
+ export { verifyReplay, verifyReplayWithDescriptor } from './replay.js';
64
+ export * from './replay-scoring.js';
65
+ export { createDeterministicReplayBundle, createDeterministicReplayDebugTables, createDeterministicReplayRuntimeManifest, minimizeDeterministicReplayDesync, minimizeDeterministicReplayDesyncBundle, sliceDeterministicReplayBundle, verifyDeterministicFrameRuntimeReplayBundle, verifyDeterministicReplayBundle, verifyDeterministicSelfContainedFrameRuntimeReplayBundle, } from './replay-bundle.js';
66
+ export type { DeterministicFrameRuntimeReplayBundleOptions, DeterministicFrameRuntimeReplayBundleVerification, DeterministicReplayBundle, DeterministicReplayBundleMismatch, DeterministicReplayBundleVerification, DeterministicReplayDebugTables, DeterministicReplayDesyncMinimization, DeterministicReplayRuntimeBeforeFrameId, DeterministicReplayRuntimeManifest, DeterministicReplayRuntimeManifestSource, DeterministicReplayRuntimeSystemId, DeterministicReplaySemanticModel, DeterministicReplaySemanticOperation, DeterministicReplaySliceOrigin, DeterministicReplaySnapshot, } from './replay-bundle.js';
67
+ export * from './local-authority.js';
68
+ export * from './local-authority-wire.js';
69
+ export * from './input-authority.js';
70
+ export * from './session-wire.js';
71
+ export * from './session-snapshot.js';
72
+ export * from './networked-client.js';
73
+ export * from './authority-room.js';
74
+ export * from './multiclient-authority.js';
75
+ export { withRuntimeDeterminismGuards } from './runtime-guards.js';
76
+ export { createLabSession, hydrateLabInput, labDefaultInput, labStep } from './sample-lab.js';
77
+ export { createSchemaArtifacts } from './schema-artifacts.js';
78
+ export { createDeterministicDescriptorBinarySchema, generateSchemaBinarySource, generateSchemaTypes, proveSchemaBinaryRoundTrip, } from './schema-codegen.js';
79
+ export { defineSyncplayGame, stableDescriptorId } from './schema.js';
80
+ export * from './schema-dsl-binary.js';
81
+ export * from './signals.js';
82
+ export * from './sparse-set.js';
83
+ export * from './system-lifecycle.js';
84
+ export { createCooldown, framesToMilliseconds, millisecondsToFrames, popDueFrameEvents, scheduleFrameEvent, tickCooldown, } from './timers.js';
85
+ export { runVenusMpBudgetLab } from './venus-mp-budget.js';
86
+ export type { DeterministicCooldown, ScheduledFrameEvent } from './timers.js';
87
+ export type { DeterministicSchemaArtifacts, SchemaFrameDump } from './schema-artifacts.js';
88
+ export type { DeterministicOfflineFrame, DeterministicOfflineRuntime, DeterministicOfflineRuntimeConfig, } from './sdk-offline.js';
89
+ export type { SchemaBinaryProof, SchemaBinarySourceOptions, SchemaTypesOptions } from './schema-codegen.js';
90
+ export type { AssetDescriptor, CollectionOrdering, CommandChannelDescriptor, ConfigDescriptor, DeterministicGameDescriptor, EventDescriptor, InputFieldDescriptor, InputFieldPolicy, NumericMode, SchemaFieldDescriptor, SchemaFieldKind, StateFieldDescriptor, SystemDescriptor, PrototypeDescriptor, ValidatedDeterministicGameDescriptor, } from './schema.js';
91
+ export type { LabInput, LabSessionOptions, LabState } from './sample-lab.js';
92
+ export type { ProtocolRollbackEventPayload, ProtocolRollbackEventTimeline, ProtocolPredictionPolicy, ProtocolRollbackGame, ProtocolRollbackLabOptions, ProtocolRollbackLabResult, } from './protocol-lab.js';
93
+ export type { DeterministicReport, DeterministicAssetCookCliFileResult, DeterministicAssetCookCliReport, DeterministicReportDiff, DeterministicReportDiffEntry, ProtocolRollbackReport, ReplayVerifyCliFileResult, ReplayVerifyCliReport, StaticDeterminismReport, } from './reports.js';
94
+ export type { PredictionCullingMode, PredictionCullingOptions, PredictionCullingResult } from './prediction-culling.js';
95
+ export type { DeterministicR3fRenderAdapter, DeterministicR3fRenderAdapterConfig, DeterministicR3fRenderDebug, DeterministicR3fRenderFrame, DeterministicRenderReadonly, } from './r3f-render-adapter.js';
96
+ export type { DescriptorReplayInspectConfig, ReplayDiffResult, ReplayFrameDiff, ReplayFrameDump, ReplayInspectConfig, ReplayChecksumExplanation, ReplayChecksumTableExplanation, } from './replay-inspect.js';
97
+ export type { DescriptorReplayVerificationConfig, ReplayVerificationConfig } from './replay.js';
98
+ export type { NumberLabMode, NumberLabOptions, NumberLabResult } from './number-lab.js';
99
+ export type { PhysicsCertEngine, PhysicsCertOptions, PhysicsCertResult, PhysicsCertShape } from './physics-cert.js';
100
+ export type { VenusMpBudgetOptions, VenusMpBudgetResult } from './venus-mp-budget.js';
101
+ export type { DeterministicSessionConfig, DeterministicStep, DeterministicStepContext, FrameSnapshot, OfflineSession, RecordedChecksum, RecordedCommandFrame, RecordedDebugEvent, RecordedInputFrame, ReplayFile, ReplayRecordingMode, ReplayVerificationMismatch, ReplayVerificationResult, TickRate, } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ export { canonicalize, canonicalStringify, cloneCanonical, decodeCanonicalValue, decodeUtf8, defaultChecksum, encodeUtf8 } from './canonical.js';
2
+ export * from './animation.js';
3
+ export { cookDeterministicBotAsset, createDeterministicBotBlackboard, getBlackboardValue, runDeterministicBotSimulation, selectDeterministicUtility, tickDeterministicBehaviorTree, tickDeterministicBehaviorTreeWithMemory, tickDeterministicHfsm, } from './bot-primitives.js';
4
+ export * from './bot-documents.js';
5
+ export * from './commands.js';
6
+ export * from './config-bundle.js';
7
+ export * from './input-timeline.js';
8
+ export * from './lag-compensation3d.js';
9
+ export { assertAssetManifestMatches, cookDeterministicAssets, materializePrototypeEntities, stableAssetCookJson, } from './asset-cooking.js';
10
+ export { aabbContainsPoint, aabbIntersects, circleIntersects, circleIntersectsAabb, fixedAabb, fixedCircle, fixedVec2, sortAabbsByStableId, translateAabb, } from './collision.js';
11
+ export { createStableIndexedMap, deterministicShuffle, stableEntries, stableSortedKeys } from './collections.js';
12
+ export { combineDeterministicPhysicsMaterial, cookStaticColliders, detectVerticalCcdHit, quantizeFpsAim, stepKccLiteBody, stepTopDownBody, } from './deterministic-primitives.js';
13
+ export { createDeterministicEventEffectsAdapter } from './effects-adapter.js';
14
+ export { createDeterministicEventTimeline, filterDeterministicEventsForPlayer, runDeterministicEventKeywordFixture } from './events.js';
15
+ export { createEcsLiteWorld } from './ecs-lite.js';
16
+ export * from './engine-core-proof.js';
17
+ export * from './engine-complete.js';
18
+ export * from './engine-runtime.js';
19
+ export * from './deterministic-session.js';
20
+ export { deterministicButtonInitialState, runDeterministicButtonFixture, runDeterministicDescriptorButtonFixture, stepDeterministicButton, } from './input-button.js';
21
+ export { createCounterDuelSession, counterDuelDefaultInput, makeCounterDuelInput, runCounterDuelExample, verifyCounterDuelReplay, } from './examples/counter-duel.js';
22
+ export { createFixedArenaDescriptor, createFixedArenaSession, createInitialFixedArenaState, fixedArenaDefaultInput, fixedArenaStep, makeFixedArenaInput, projectFixedArenaReferenceView, projectFixedArenaRenderState, runFixedArenaExample, verifyFixedArenaReplay, } from './examples/fixed-arena.js';
23
+ export { SyncplayError } from './errors.js';
24
+ export { createDeterministicMath } from './math.js';
25
+ export { createDeterministicMockNetworkAdapter } from './mock-network-adapter.js';
26
+ export { runDeterministicMovementCrowdSimulation, rewindDeterministicTargets, runDeterministicMovementSimulation, stepDeterministicFpsAim, stepDeterministicKcc2D, stepDeterministicTopDownMover, validateDeterministicLagCompensatedHit, } from './movement.js';
27
+ export * from './movement3d.js';
28
+ export { applyDeterministicReciprocalAvoidance, cookDeterministicNavigationGraph, cookTilemapNavigationGraph, createDeterministicFlowField, findDeterministicPath, smoothDeterministicPath, stepDeterministicNavigationAgents, } from './navigation.js';
29
+ export * from './navmesh.js';
30
+ export * from './engine-parity-matrix.js';
31
+ export { runNumberLab } from './number-lab.js';
32
+ export { createOfflineSession } from './offline-session.js';
33
+ export { createSyncplayOfflineRuntime } from './sdk-offline.js';
34
+ export * from './rollback-history.js';
35
+ export { circleCastDeterministicPhysics2D, createDeterministicPhysicsWorld2D, nearestDeterministicPhysicsHit2D, queryDeterministicPhysicsAabb2D, queryDeterministicPhysicsShapeOverlap2D, raycastAllDeterministicPhysics2D, raycastDeterministicPhysics2D, stepDeterministicPhysicsWorld2D, } from './physics2d.js';
36
+ export * from './physics3d.js';
37
+ export { runPhysicsCert, runRapierPhysicsCert } from './physics-cert.js';
38
+ export { runPredictionCullingLab } from './prediction-culling.js';
39
+ export { createDeterministicR3fDebugOverlay, createDeterministicR3fRenderAdapter, interpolateDeterministicRenderNumber, interpolateDeterministicRenderVec2, } from './r3f-render-adapter.js';
40
+ export { runProtocolRollbackLab } from './protocol-lab.js';
41
+ export { createProtocolRollbackReport, diffDeterministicReports, renderDeterministicReportHtml, stableReportDiffJson, stableReportJson, } from './reports.js';
42
+ export { diffReplayFrames, explainReplayChecksum, inspectReplayFrame, inspectReplayFrameWithDescriptor, stableFrameDiffJson, stableFrameDumpJson, } from './replay-inspect.js';
43
+ export { deterministicSampleSceneIds, runAllDeterministicSampleScenes, runDeterministicIntegratedHeadlessScene, runDeterministicSampleScene, } from './sample-scenes.js';
44
+ export { DeterministicRandom } from './random.js';
45
+ export { verifyReplay, verifyReplayWithDescriptor } from './replay.js';
46
+ export * from './replay-scoring.js';
47
+ export { createDeterministicReplayBundle, createDeterministicReplayDebugTables, createDeterministicReplayRuntimeManifest, minimizeDeterministicReplayDesync, minimizeDeterministicReplayDesyncBundle, sliceDeterministicReplayBundle, verifyDeterministicFrameRuntimeReplayBundle, verifyDeterministicReplayBundle, verifyDeterministicSelfContainedFrameRuntimeReplayBundle, } from './replay-bundle.js';
48
+ export * from './local-authority.js';
49
+ export * from './local-authority-wire.js';
50
+ export * from './input-authority.js';
51
+ export * from './session-wire.js';
52
+ export * from './session-snapshot.js';
53
+ export * from './networked-client.js';
54
+ export * from './authority-room.js';
55
+ export * from './multiclient-authority.js';
56
+ export { withRuntimeDeterminismGuards } from './runtime-guards.js';
57
+ export { createLabSession, hydrateLabInput, labDefaultInput, labStep } from './sample-lab.js';
58
+ export { createSchemaArtifacts } from './schema-artifacts.js';
59
+ export { createDeterministicDescriptorBinarySchema, generateSchemaBinarySource, generateSchemaTypes, proveSchemaBinaryRoundTrip, } from './schema-codegen.js';
60
+ export { defineSyncplayGame, stableDescriptorId } from './schema.js';
61
+ export * from './schema-dsl-binary.js';
62
+ export * from './signals.js';
63
+ export * from './sparse-set.js';
64
+ export * from './system-lifecycle.js';
65
+ export { createCooldown, framesToMilliseconds, millisecondsToFrames, popDueFrameEvents, scheduleFrameEvent, tickCooldown, } from './timers.js';
66
+ export { runVenusMpBudgetLab } from './venus-mp-budget.js';
@@ -0,0 +1,82 @@
1
+ import { type CanonicalValue } from './canonical.js';
2
+ /**
3
+ * Game-agnostic input authority (server orders inputs, clients simulate — §2 Option 1).
4
+ *
5
+ * It orders per-slot inputs by tick and confirms each tick exactly once, in order,
6
+ * either when every player slot has reported or when a HardTolerance deadline elapses
7
+ * (substituting the slot's last confirmed input). It never runs the simulation — only
8
+ * inputs cross the wire and clients run the deterministic sim locally.
9
+ *
10
+ * This module is the reusable core: the M0 spike hosts it over sockets, and M2 lifts it
11
+ * into the mp-room-server room type unchanged.
12
+ */
13
+ /** Opaque, engine-defined input payload. The authority never interprets it. */
14
+ export type EncodedInput = CanonicalValue;
15
+ export interface ConfirmedInputFrame {
16
+ readonly tick: number;
17
+ /** One entry per player slot, in slot order. */
18
+ readonly inputs: readonly EncodedInput[];
19
+ /** Slots whose input was substituted (repeated) because it never arrived in time. */
20
+ readonly substitutedSlots: readonly number[];
21
+ readonly checksum: string;
22
+ }
23
+ export interface InputAuthorityConfig {
24
+ readonly playerCount: number;
25
+ /** Confirm a tick once `now - tick >= hardToleranceTicks`, substituting any missing input. */
26
+ readonly hardToleranceTicks: number;
27
+ /** Substitute this when a slot has no prior confirmed input to repeat. */
28
+ readonly neutralInput: EncodedInput;
29
+ /** Reject inputs whose tick is further ahead than `confirmedThrough + maxFutureTicks`. */
30
+ readonly maxFutureTicks?: number;
31
+ /** Confirmed frames retained for the redundant broadcast window. */
32
+ readonly retainedConfirmedFrames?: number;
33
+ /**
34
+ * Rebuild a previously-persisted authority (M6.5 crash recovery): the
35
+ * retained frames, frontier, and per-slot last-confirmed inputs (derived
36
+ * from the final frame — confirmed inputs equal the post-substitution
37
+ * last-confirmed values by construction). Fail-loud on gaps or a frontier
38
+ * mismatch.
39
+ */
40
+ readonly restoreFrom?: InputAuthorityRestoreState;
41
+ }
42
+ export interface InputAuthorityRestoreState {
43
+ readonly confirmedThrough: number;
44
+ readonly frames: readonly ConfirmedInputFrame[];
45
+ }
46
+ export type InputRejectionReason = 'slot-out-of-range' | 'invalid-tick' | 'tick-already-confirmed' | 'tick-too-far-ahead';
47
+ export interface InputSubmissionResult {
48
+ readonly accepted: boolean;
49
+ readonly reason?: InputRejectionReason;
50
+ }
51
+ export interface InputAuthorityStats {
52
+ readonly confirmedTicks: number;
53
+ readonly substitutedInputs: number;
54
+ readonly droppedLateInputs: number;
55
+ readonly rejectedFutureInputs: number;
56
+ }
57
+ export interface InputAuthority {
58
+ readonly playerCount: number;
59
+ /** Highest confirmed tick, or -1 when nothing is confirmed yet. */
60
+ readonly confirmedThrough: number;
61
+ /** Lowest confirmed tick still retained, or -1 when nothing is confirmed yet. */
62
+ readonly earliestRetainedTick: number;
63
+ receiveInput(slot: number, tick: number, input: EncodedInput): InputSubmissionResult;
64
+ /** Confirm every tick that can be confirmed up to and including `now`. Returns the new frames in order. */
65
+ advance(now: number): readonly ConfirmedInputFrame[];
66
+ /** A confirmed frame still inside the retained window, for redundant re-broadcast. */
67
+ confirmedFrame(tick: number): ConfirmedInputFrame | undefined;
68
+ /**
69
+ * The retained frames `from..to` inclusive, for persistence (M6.5). Throws
70
+ * if any tick in the range is no longer retained — a persisted record with
71
+ * a silent gap would strand every restored client.
72
+ */
73
+ confirmedFrameRange(from: number, to: number): readonly ConfirmedInputFrame[];
74
+ /**
75
+ * Drop retained frames below `tick` (M5.5: history before a validated
76
+ * snapshot is no longer needed for late-join catch-up). Never moves the
77
+ * frontier; a no-op at or below the current earliest retained tick.
78
+ */
79
+ pruneConfirmedBefore(tick: number): void;
80
+ stats(): InputAuthorityStats;
81
+ }
82
+ export declare function createInputAuthority(config: InputAuthorityConfig): InputAuthority;