rollback-netcode 0.0.4

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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/dist/debug.d.ts +29 -0
  4. package/dist/debug.d.ts.map +1 -0
  5. package/dist/debug.js +56 -0
  6. package/dist/debug.js.map +1 -0
  7. package/dist/index.d.ts +62 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +57 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/protocol/encoding.d.ts +80 -0
  12. package/dist/protocol/encoding.d.ts.map +1 -0
  13. package/dist/protocol/encoding.js +992 -0
  14. package/dist/protocol/encoding.js.map +1 -0
  15. package/dist/protocol/messages.d.ts +271 -0
  16. package/dist/protocol/messages.d.ts.map +1 -0
  17. package/dist/protocol/messages.js +114 -0
  18. package/dist/protocol/messages.js.map +1 -0
  19. package/dist/rollback/engine.d.ts +261 -0
  20. package/dist/rollback/engine.d.ts.map +1 -0
  21. package/dist/rollback/engine.js +543 -0
  22. package/dist/rollback/engine.js.map +1 -0
  23. package/dist/rollback/input-buffer.d.ts +225 -0
  24. package/dist/rollback/input-buffer.d.ts.map +1 -0
  25. package/dist/rollback/input-buffer.js +483 -0
  26. package/dist/rollback/input-buffer.js.map +1 -0
  27. package/dist/rollback/snapshot-buffer.d.ts +119 -0
  28. package/dist/rollback/snapshot-buffer.d.ts.map +1 -0
  29. package/dist/rollback/snapshot-buffer.js +256 -0
  30. package/dist/rollback/snapshot-buffer.js.map +1 -0
  31. package/dist/session/desync-manager.d.ts +106 -0
  32. package/dist/session/desync-manager.d.ts.map +1 -0
  33. package/dist/session/desync-manager.js +136 -0
  34. package/dist/session/desync-manager.js.map +1 -0
  35. package/dist/session/lag-monitor.d.ts +69 -0
  36. package/dist/session/lag-monitor.d.ts.map +1 -0
  37. package/dist/session/lag-monitor.js +74 -0
  38. package/dist/session/lag-monitor.js.map +1 -0
  39. package/dist/session/message-builders.d.ts +86 -0
  40. package/dist/session/message-builders.d.ts.map +1 -0
  41. package/dist/session/message-builders.js +199 -0
  42. package/dist/session/message-builders.js.map +1 -0
  43. package/dist/session/message-router.d.ts +61 -0
  44. package/dist/session/message-router.d.ts.map +1 -0
  45. package/dist/session/message-router.js +105 -0
  46. package/dist/session/message-router.js.map +1 -0
  47. package/dist/session/player-manager.d.ts +100 -0
  48. package/dist/session/player-manager.d.ts.map +1 -0
  49. package/dist/session/player-manager.js +160 -0
  50. package/dist/session/player-manager.js.map +1 -0
  51. package/dist/session/session.d.ts +379 -0
  52. package/dist/session/session.d.ts.map +1 -0
  53. package/dist/session/session.js +1294 -0
  54. package/dist/session/session.js.map +1 -0
  55. package/dist/session/topology.d.ts +66 -0
  56. package/dist/session/topology.d.ts.map +1 -0
  57. package/dist/session/topology.js +72 -0
  58. package/dist/session/topology.js.map +1 -0
  59. package/dist/transport/adapter.d.ts +99 -0
  60. package/dist/transport/adapter.d.ts.map +1 -0
  61. package/dist/transport/adapter.js +8 -0
  62. package/dist/transport/adapter.js.map +1 -0
  63. package/dist/transport/local.d.ts +192 -0
  64. package/dist/transport/local.d.ts.map +1 -0
  65. package/dist/transport/local.js +435 -0
  66. package/dist/transport/local.js.map +1 -0
  67. package/dist/transport/transforming.d.ts +177 -0
  68. package/dist/transport/transforming.d.ts.map +1 -0
  69. package/dist/transport/transforming.js +407 -0
  70. package/dist/transport/transforming.js.map +1 -0
  71. package/dist/transport/webrtc.d.ts +285 -0
  72. package/dist/transport/webrtc.d.ts.map +1 -0
  73. package/dist/transport/webrtc.js +734 -0
  74. package/dist/transport/webrtc.js.map +1 -0
  75. package/dist/types.d.ts +394 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +256 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/utils/rate-limiter.d.ts +59 -0
  80. package/dist/utils/rate-limiter.d.ts.map +1 -0
  81. package/dist/utils/rate-limiter.js +93 -0
  82. package/dist/utils/rate-limiter.js.map +1 -0
  83. package/package.json +61 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * TransformingTransport - Wraps a transport with compression and segmentation.
3
+ *
4
+ * Provides transparent compression (using pako/gzip) and segmentation for large
5
+ * messages that exceed WebRTC DataChannel limits (~16KB).
6
+ */
7
+ import * as pako from "pako";
8
+ /**
9
+ * Default configuration for TransformingTransport.
10
+ */
11
+ export const DEFAULT_TRANSFORMING_TRANSPORT_CONFIG = {
12
+ compression: "auto",
13
+ compressionThreshold: 128,
14
+ segmentation: true,
15
+ maxSegmentSize: 16000,
16
+ reassemblyTimeout: 5000,
17
+ };
18
+ /** Header byte indicating uncompressed data */
19
+ const COMPRESSION_HEADER_RAW = 0x00;
20
+ /** Header byte indicating gzip-compressed data */
21
+ const COMPRESSION_HEADER_GZIP = 0x01;
22
+ /** Size of the compression header (1 byte) */
23
+ const COMPRESSION_HEADER_SIZE = 1;
24
+ /** Size of the segment header (msgId:u32 + idx:u16 + total:u16 = 8 bytes) */
25
+ const SEGMENT_HEADER_SIZE = 8;
26
+ /** Maximum segments allowed per message (prevents DoS with absurd total values) */
27
+ const MAX_SEGMENTS_PER_MESSAGE = 4096; // ~64MB at 16KB segments
28
+ /**
29
+ * Wraps a transport with transparent compression and segmentation.
30
+ *
31
+ * Send path: compress -> segment -> send via inner transport
32
+ * Receive path: reassemble -> decompress -> deliver to callback
33
+ */
34
+ export class TransformingTransport {
35
+ onMessage = null;
36
+ onConnect = null;
37
+ onDisconnect = null;
38
+ onError = null;
39
+ inner;
40
+ config;
41
+ /** Per-peer message ID counters for outgoing messages */
42
+ messageIdCounters = new Map();
43
+ /** Per-peer reassembly buffers for incoming messages */
44
+ reassemblyBuffers = new Map();
45
+ /** Timer ID for periodic cleanup */
46
+ cleanupTimerId = null;
47
+ /**
48
+ * Create a new TransformingTransport.
49
+ *
50
+ * @param inner - The underlying transport to wrap
51
+ * @param config - Optional configuration (uses defaults for missing values)
52
+ */
53
+ constructor(inner, config) {
54
+ this.inner = inner;
55
+ this.config = {
56
+ ...DEFAULT_TRANSFORMING_TRANSPORT_CONFIG,
57
+ ...config,
58
+ };
59
+ // Wire up inner transport callbacks
60
+ this.inner.onMessage = (peerId, message) => {
61
+ this.handleIncomingMessage(peerId, message);
62
+ };
63
+ this.inner.onConnect = (peerId) => {
64
+ this.onConnect?.(peerId);
65
+ };
66
+ this.inner.onDisconnect = (peerId) => {
67
+ this.cleanupPeerState(peerId);
68
+ this.onDisconnect?.(peerId);
69
+ };
70
+ // Forward errors from inner transport
71
+ if (this.inner.onError !== undefined) {
72
+ this.inner.onError = (peerId, error, context) => {
73
+ this.onError?.(peerId, error, context);
74
+ };
75
+ }
76
+ // Start periodic cleanup for timed-out reassembly buffers
77
+ this.startCleanupTimer();
78
+ }
79
+ /**
80
+ * Get the set of connected peer IDs.
81
+ */
82
+ get connectedPeers() {
83
+ return this.inner.connectedPeers;
84
+ }
85
+ /**
86
+ * Get the local peer's ID.
87
+ */
88
+ get localPeerId() {
89
+ return this.inner.localPeerId;
90
+ }
91
+ /**
92
+ * Connect to a peer.
93
+ */
94
+ async connect(peerId) {
95
+ return this.inner.connect(peerId);
96
+ }
97
+ /**
98
+ * Disconnect from a peer.
99
+ */
100
+ disconnect(peerId) {
101
+ this.cleanupPeerState(peerId);
102
+ this.inner.disconnect(peerId);
103
+ }
104
+ /**
105
+ * Disconnect from all peers.
106
+ */
107
+ disconnectAll() {
108
+ // Clean up all state
109
+ this.messageIdCounters.clear();
110
+ this.reassemblyBuffers.clear();
111
+ this.inner.disconnectAll();
112
+ }
113
+ /**
114
+ * Send a message to a specific peer.
115
+ * Applies compression and segmentation as configured.
116
+ */
117
+ send(peerId, message, reliable) {
118
+ const transformed = this.transformOutgoing(message);
119
+ const segments = this.segmentMessage(peerId, transformed);
120
+ for (const segment of segments) {
121
+ this.inner.send(peerId, segment, reliable);
122
+ }
123
+ }
124
+ /**
125
+ * Broadcast a message to all connected peers.
126
+ * Each peer receives independently segmented messages with unique message IDs.
127
+ */
128
+ broadcast(message, reliable) {
129
+ const transformed = this.transformOutgoing(message);
130
+ for (const peerId of this.connectedPeers) {
131
+ const segments = this.segmentMessage(peerId, transformed);
132
+ for (const segment of segments) {
133
+ this.inner.send(peerId, segment, reliable);
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Get connection quality metrics for a peer.
139
+ */
140
+ getConnectionMetrics(peerId) {
141
+ return this.inner.getConnectionMetrics?.(peerId) ?? null;
142
+ }
143
+ /**
144
+ * Stop the cleanup timer and dispose of the inner transport.
145
+ * Call this when disposing of the transport.
146
+ */
147
+ dispose() {
148
+ this.stopCleanupTimer();
149
+ this.messageIdCounters.clear();
150
+ this.reassemblyBuffers.clear();
151
+ // Dispose of the wrapped transport to prevent memory leaks
152
+ this.inner.dispose?.();
153
+ }
154
+ /**
155
+ * Apply compression to outgoing message data.
156
+ * Returns data with a 1-byte compression header.
157
+ */
158
+ transformOutgoing(message) {
159
+ if (this.config.compression === "never") {
160
+ return this.addCompressionHeader(message, false);
161
+ }
162
+ // Check if message is above threshold
163
+ if (this.config.compression === "auto" &&
164
+ message.length < this.config.compressionThreshold) {
165
+ return this.addCompressionHeader(message, false);
166
+ }
167
+ // Attempt compression
168
+ const compressed = pako.deflate(message);
169
+ // In auto mode, only use compression if it actually reduces size
170
+ if (this.config.compression === "auto" &&
171
+ compressed.length >= message.length) {
172
+ return this.addCompressionHeader(message, false);
173
+ }
174
+ return this.addCompressionHeader(compressed, true);
175
+ }
176
+ /**
177
+ * Add compression header to message data.
178
+ */
179
+ addCompressionHeader(data, isCompressed) {
180
+ const result = new Uint8Array(COMPRESSION_HEADER_SIZE + data.length);
181
+ result[0] = isCompressed ? COMPRESSION_HEADER_GZIP : COMPRESSION_HEADER_RAW;
182
+ result.set(data, COMPRESSION_HEADER_SIZE);
183
+ return result;
184
+ }
185
+ /**
186
+ * Segment a transformed message for sending.
187
+ * Returns an array of segments, each with an 8-byte header.
188
+ */
189
+ segmentMessage(peerId, data) {
190
+ // Calculate max payload size per segment
191
+ const maxPayloadSize = this.config.maxSegmentSize - SEGMENT_HEADER_SIZE;
192
+ if (!this.config.segmentation || data.length <= maxPayloadSize) {
193
+ // Single segment
194
+ return [this.createSegment(peerId, data, 0, 1)];
195
+ }
196
+ // Multiple segments
197
+ const segments = [];
198
+ const totalSegments = Math.ceil(data.length / maxPayloadSize);
199
+ const messageId = this.getNextMessageId(peerId);
200
+ for (let i = 0; i < totalSegments; i++) {
201
+ const start = i * maxPayloadSize;
202
+ const end = Math.min(start + maxPayloadSize, data.length);
203
+ const payload = data.slice(start, end);
204
+ segments.push(this.createSegmentWithId(messageId, payload, i, totalSegments));
205
+ }
206
+ return segments;
207
+ }
208
+ /**
209
+ * Create a segment with auto-generated message ID.
210
+ */
211
+ createSegment(peerId, payload, index, total) {
212
+ const messageId = this.getNextMessageId(peerId);
213
+ return this.createSegmentWithId(messageId, payload, index, total);
214
+ }
215
+ /**
216
+ * Create a segment with a specific message ID.
217
+ */
218
+ createSegmentWithId(messageId, payload, index, total) {
219
+ const segment = new Uint8Array(SEGMENT_HEADER_SIZE + payload.length);
220
+ const view = new DataView(segment.buffer);
221
+ // Write header: msgId:u32, idx:u16, total:u16
222
+ view.setUint32(0, messageId, true);
223
+ view.setUint16(4, index, true);
224
+ view.setUint16(6, total, true);
225
+ // Write payload
226
+ segment.set(payload, SEGMENT_HEADER_SIZE);
227
+ return segment;
228
+ }
229
+ /**
230
+ * Get the next message ID for a peer.
231
+ *
232
+ * Note: Wraps at 2^32 (~4 billion). Collisions after wrap-around are handled by:
233
+ * 1. The total-mismatch check in bufferSegment() (rejects segments with wrong total)
234
+ * 2. The reassembly timeout cleanup (removes stale entries after 5s)
235
+ * 3. Practical impossibility: at 60 msg/sec, wrap-around takes ~2.2 years
236
+ */
237
+ getNextMessageId(peerId) {
238
+ const current = this.messageIdCounters.get(peerId) ?? 0;
239
+ const next = (current + 1) >>> 0; // Keep as unsigned 32-bit
240
+ this.messageIdCounters.set(peerId, next);
241
+ return current;
242
+ }
243
+ /**
244
+ * Handle an incoming message from the inner transport.
245
+ */
246
+ handleIncomingMessage(peerId, data) {
247
+ if (data.length < SEGMENT_HEADER_SIZE) {
248
+ // Invalid segment, ignore
249
+ return;
250
+ }
251
+ // Parse segment header
252
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
253
+ const messageId = view.getUint32(0, true);
254
+ const index = view.getUint16(4, true);
255
+ const total = view.getUint16(6, true);
256
+ // Extract payload
257
+ const payload = data.slice(SEGMENT_HEADER_SIZE);
258
+ if (total === 0) {
259
+ // Invalid total, ignore
260
+ return;
261
+ }
262
+ if (total === 1) {
263
+ // Fast path: single segment message
264
+ this.deliverMessage(peerId, payload);
265
+ return;
266
+ }
267
+ // Multi-segment message: buffer and reassemble
268
+ this.bufferSegment(peerId, messageId, index, total, payload);
269
+ }
270
+ /**
271
+ * Buffer a segment and attempt reassembly.
272
+ */
273
+ bufferSegment(peerId, messageId, index, total, payload) {
274
+ // Validate segment header values
275
+ if (total > MAX_SEGMENTS_PER_MESSAGE || index >= total) {
276
+ return;
277
+ }
278
+ // Get or create peer state
279
+ let peerState = this.reassemblyBuffers.get(peerId);
280
+ if (!peerState) {
281
+ peerState = { messages: new Map() };
282
+ this.reassemblyBuffers.set(peerId, peerState);
283
+ }
284
+ // Get or create message state
285
+ let messageState = peerState.messages.get(messageId);
286
+ if (!messageState) {
287
+ messageState = {
288
+ total,
289
+ segments: new Map(),
290
+ startTime: Date.now(),
291
+ };
292
+ peerState.messages.set(messageId, messageState);
293
+ }
294
+ // Validate total matches
295
+ if (messageState.total !== total) {
296
+ // Mismatched total, discard segment
297
+ return;
298
+ }
299
+ // Ignore duplicate segments
300
+ if (messageState.segments.has(index)) {
301
+ return;
302
+ }
303
+ // Store segment
304
+ messageState.segments.set(index, payload);
305
+ // Check if complete
306
+ if (messageState.segments.size === total) {
307
+ // Reassemble in order
308
+ const reassembled = this.reassembleMessage(messageState);
309
+ peerState.messages.delete(messageId);
310
+ this.deliverMessage(peerId, reassembled);
311
+ }
312
+ }
313
+ /**
314
+ * Reassemble a complete message from segments.
315
+ */
316
+ reassembleMessage(state) {
317
+ // Calculate total size
318
+ let totalSize = 0;
319
+ for (const segment of state.segments.values()) {
320
+ totalSize += segment.length;
321
+ }
322
+ // Reassemble in order
323
+ const result = new Uint8Array(totalSize);
324
+ let offset = 0;
325
+ for (let i = 0; i < state.total; i++) {
326
+ const segment = state.segments.get(i);
327
+ if (segment) {
328
+ result.set(segment, offset);
329
+ offset += segment.length;
330
+ }
331
+ }
332
+ return result;
333
+ }
334
+ /**
335
+ * Decompress and deliver a reassembled message.
336
+ */
337
+ deliverMessage(peerId, data) {
338
+ if (data.length < COMPRESSION_HEADER_SIZE) {
339
+ // Invalid message, ignore
340
+ return;
341
+ }
342
+ const compressionByte = data[0];
343
+ const payload = data.slice(COMPRESSION_HEADER_SIZE);
344
+ let decompressed;
345
+ if (compressionByte === COMPRESSION_HEADER_GZIP) {
346
+ try {
347
+ decompressed = pako.inflate(payload);
348
+ }
349
+ catch {
350
+ // Decompression failed, ignore message
351
+ return;
352
+ }
353
+ }
354
+ else {
355
+ // Raw data
356
+ decompressed = payload;
357
+ }
358
+ this.onMessage?.(peerId, decompressed);
359
+ }
360
+ /**
361
+ * Clean up state for a disconnected peer.
362
+ */
363
+ cleanupPeerState(peerId) {
364
+ this.messageIdCounters.delete(peerId);
365
+ this.reassemblyBuffers.delete(peerId);
366
+ }
367
+ /**
368
+ * Start the periodic cleanup timer.
369
+ */
370
+ startCleanupTimer() {
371
+ // Run cleanup every second
372
+ this.cleanupTimerId = setInterval(() => {
373
+ this.cleanupTimedOutMessages();
374
+ }, 1000);
375
+ // Allow process to exit even if timer is running
376
+ if (this.cleanupTimerId.unref) {
377
+ this.cleanupTimerId.unref();
378
+ }
379
+ }
380
+ /**
381
+ * Stop the cleanup timer.
382
+ */
383
+ stopCleanupTimer() {
384
+ if (this.cleanupTimerId !== null) {
385
+ clearInterval(this.cleanupTimerId);
386
+ this.cleanupTimerId = null;
387
+ }
388
+ }
389
+ /**
390
+ * Remove incomplete messages that have timed out.
391
+ */
392
+ cleanupTimedOutMessages() {
393
+ const now = Date.now();
394
+ for (const [peerId, peerState] of this.reassemblyBuffers) {
395
+ for (const [messageId, messageState] of peerState.messages) {
396
+ if (now - messageState.startTime > this.config.reassemblyTimeout) {
397
+ peerState.messages.delete(messageId);
398
+ }
399
+ }
400
+ // Remove peer state if empty
401
+ if (peerState.messages.size === 0) {
402
+ this.reassemblyBuffers.delete(peerId);
403
+ }
404
+ }
405
+ }
406
+ }
407
+ //# sourceMappingURL=transforming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforming.js","sourceRoot":"","sources":["../../src/transport/transforming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AA4C7B;;GAEG;AACH,MAAM,CAAC,MAAM,qCAAqC,GACjD;IACC,WAAW,EAAE,MAAM;IACnB,oBAAoB,EAAE,GAAG;IACzB,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,KAAK;IACrB,iBAAiB,EAAE,IAAI;CACvB,CAAC;AAEH,+CAA+C;AAC/C,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAEpC,kDAAkD;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAErC,8CAA8C;AAC9C,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAElC,6EAA6E;AAC7E,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,mFAAmF;AACnF,MAAM,wBAAwB,GAAG,IAAI,CAAC,CAAC,yBAAyB;AAwBhE;;;;;GAKG;AACH,MAAM,OAAO,qBAAqB;IAC1B,SAAS,GACf,IAAI,CAAC;IACC,SAAS,GAAsC,IAAI,CAAC;IACpD,YAAY,GAAsC,IAAI,CAAC;IACvD,OAAO,GAEJ,IAAI,CAAC;IAEE,KAAK,CAAmB;IACxB,MAAM,CAA8B;IAErD,yDAAyD;IACxC,iBAAiB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEpE,wDAAwD;IACvC,iBAAiB,GACjC,IAAI,GAAG,EAAE,CAAC;IAEX,oCAAoC;IAC5B,cAAc,GAA0C,IAAI,CAAC;IAErE;;;;;OAKG;IACH,YACC,KAAuB,EACvB,MAA6C;QAE7C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG;YACb,GAAG,qCAAqC;YACxC,GAAG,MAAM;SACT,CAAC;QAEF,oCAAoC;QACpC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;YAC1C,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,EAAE;YACjC,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,EAAE,EAAE;YACpC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC,CAAC;QAEF,sCAAsC;QACtC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC/C,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACxC,CAAC,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAc;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAAc;QACxB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,aAAa;QACZ,qBAAqB;QACrB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,MAAc,EAAE,OAAmB,EAAE,QAAiB;QAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAE1D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACF,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,OAAmB,EAAE,QAAiB;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAEpD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAC1D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC5C,CAAC;QACF,CAAC;IACF,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAE,MAAc;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,OAAO;QACN,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,2DAA2D;QAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IACxB,CAAC;IAED;;;OAGG;IACK,iBAAiB,CAAC,OAAmB;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAED,sCAAsC;QACtC,IACC,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM;YAClC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAChD,CAAC;YACF,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAED,sBAAsB;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEzC,iEAAiE;QACjE,IACC,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM;YAClC,UAAU,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAClC,CAAC;YACF,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACK,oBAAoB,CAC3B,IAAgB,EAChB,YAAqB;QAErB,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,uBAAuB,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACrE,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,sBAAsB,CAAC;QAC5E,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;OAGG;IACK,cAAc,CAAC,MAAc,EAAE,IAAgB;QACtD,yCAAyC;QACzC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,mBAAmB,CAAC;QAExE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC;YAChE,iBAAiB;YACjB,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,oBAAoB;QACpB,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAEhD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,CAAC,GAAG,cAAc,CAAC;YACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAEvC,QAAQ,CAAC,IAAI,CACZ,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,CAAC,CAC9D,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,aAAa,CACpB,MAAc,EACd,OAAmB,EACnB,KAAa,EACb,KAAa;QAEb,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACK,mBAAmB,CAC1B,SAAiB,EACjB,OAAmB,EACnB,KAAa,EACb,KAAa;QAEb,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE1C,8CAA8C;QAC9C,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAE/B,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QAE1C,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACK,gBAAgB,CAAC,MAAc;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,0BAA0B;QAC5D,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,MAAc,EAAE,IAAgB;QAC7D,IAAI,IAAI,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;YACvC,0BAA0B;YAC1B,OAAO;QACR,CAAC;QAED,uBAAuB;QACvB,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACzE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAEtC,kBAAkB;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAEhD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACjB,wBAAwB;YACxB,OAAO;QACR,CAAC;QAED,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACjB,oCAAoC;YACpC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO;QACR,CAAC;QAED,+CAA+C;QAC/C,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACK,aAAa,CACpB,MAAc,EACd,SAAiB,EACjB,KAAa,EACb,KAAa,EACb,OAAmB;QAEnB,iCAAiC;QACjC,IAAI,KAAK,GAAG,wBAAwB,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;YACxD,OAAO;QACR,CAAC;QAED,2BAA2B;QAC3B,IAAI,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,SAAS,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/C,CAAC;QAED,8BAA8B;QAC9B,IAAI,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,YAAY,GAAG;gBACd,KAAK;gBACL,QAAQ,EAAE,IAAI,GAAG,EAAE;gBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;YACF,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACjD,CAAC;QAED,yBAAyB;QACzB,IAAI,YAAY,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAClC,oCAAoC;YACpC,OAAO;QACR,CAAC;QAED,4BAA4B;QAC5B,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO;QACR,CAAC;QAED,gBAAgB;QAChB,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAE1C,oBAAoB;QACpB,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC1C,sBAAsB;YACtB,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACzD,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAErC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,KAA6B;QACtD,uBAAuB;QACvB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;QAC7B,CAAC;QAED,sBAAsB;QACtB,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5B,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;YAC1B,CAAC;QACF,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,MAAc,EAAE,IAAgB;QACtD,IAAI,IAAI,CAAC,MAAM,GAAG,uBAAuB,EAAE,CAAC;YAC3C,0BAA0B;YAC1B,OAAO;QACR,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAEpD,IAAI,YAAwB,CAAC;QAE7B,IAAI,eAAe,KAAK,uBAAuB,EAAE,CAAC;YACjD,IAAI,CAAC;gBACJ,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACR,uCAAuC;gBACvC,OAAO;YACR,CAAC;QACF,CAAC;aAAM,CAAC;YACP,WAAW;YACX,YAAY,GAAG,OAAO,CAAC;QACxB,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,MAAc;QACtC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACK,iBAAiB;QACxB,2BAA2B;QAC3B,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAChC,CAAC,EAAE,IAAI,CAAC,CAAC;QAET,iDAAiD;QACjD,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACF,CAAC;IAED;;OAEG;IACK,gBAAgB;QACvB,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC5B,CAAC;IACF,CAAC;IAED;;OAEG;IACK,uBAAuB;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1D,KAAK,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAC5D,IAAI,GAAG,GAAG,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;oBAClE,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACtC,CAAC;YACF,CAAC;YAED,6BAA6B;YAC7B,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACvC,CAAC;QACF,CAAC;IACF,CAAC;CACD"}