t2-demo-parser 2.2.0 → 3.0.1

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 (95) hide show
  1. package/README.md +170 -7
  2. package/dist/BitStream.d.ts +14 -3
  3. package/dist/BitStream.d.ts.map +1 -1
  4. package/dist/BitStream.js +28 -6
  5. package/dist/BitStream.js.map +1 -1
  6. package/dist/BitWriter.d.ts +29 -0
  7. package/dist/BitWriter.d.ts.map +1 -0
  8. package/dist/BitWriter.js +76 -0
  9. package/dist/BitWriter.js.map +1 -0
  10. package/dist/ClassRegistry.d.ts +23 -28
  11. package/dist/ClassRegistry.d.ts.map +1 -1
  12. package/dist/ClassRegistry.js +75 -84
  13. package/dist/ClassRegistry.js.map +1 -1
  14. package/dist/DataBlockParsers.d.ts.map +1 -1
  15. package/dist/DataBlockParsers.js +60 -85
  16. package/dist/DataBlockParsers.js.map +1 -1
  17. package/dist/DemoParser.d.ts +23 -22
  18. package/dist/DemoParser.d.ts.map +1 -1
  19. package/dist/DemoParser.js +218 -266
  20. package/dist/DemoParser.js.map +1 -1
  21. package/dist/EventParsers.d.ts.map +1 -1
  22. package/dist/EventParsers.js +87 -58
  23. package/dist/EventParsers.js.map +1 -1
  24. package/dist/GhostManager.d.ts +7 -1
  25. package/dist/GhostManager.d.ts.map +1 -1
  26. package/dist/GhostManager.js +231 -146
  27. package/dist/GhostManager.js.map +1 -1
  28. package/dist/HuffmanProcessor.d.ts +15 -0
  29. package/dist/HuffmanProcessor.d.ts.map +1 -1
  30. package/dist/HuffmanProcessor.js +45 -0
  31. package/dist/HuffmanProcessor.js.map +1 -1
  32. package/dist/LiveParser.d.ts +20 -1
  33. package/dist/LiveParser.d.ts.map +1 -1
  34. package/dist/LiveParser.js +31 -12
  35. package/dist/LiveParser.js.map +1 -1
  36. package/dist/PacketParser.d.ts +22 -2
  37. package/dist/PacketParser.d.ts.map +1 -1
  38. package/dist/PacketParser.js +111 -48
  39. package/dist/PacketParser.js.map +1 -1
  40. package/dist/Timeline.d.ts +5 -2
  41. package/dist/Timeline.d.ts.map +1 -1
  42. package/dist/Timeline.js +25 -12
  43. package/dist/Timeline.js.map +1 -1
  44. package/dist/cli.js +3 -0
  45. package/dist/cli.js.map +1 -1
  46. package/dist/dataBlockDataTypes.d.ts +118 -117
  47. package/dist/dataBlockDataTypes.d.ts.map +1 -1
  48. package/dist/dataBlockDataTypes.js.map +1 -1
  49. package/dist/defaultRegistry.d.ts +9 -0
  50. package/dist/defaultRegistry.d.ts.map +1 -0
  51. package/dist/defaultRegistry.js +43 -0
  52. package/dist/defaultRegistry.js.map +1 -0
  53. package/dist/eventDataTypes.d.ts +74 -72
  54. package/dist/eventDataTypes.d.ts.map +1 -1
  55. package/dist/eventDataTypes.js.map +1 -1
  56. package/dist/ghostDataTypes.d.ts +125 -131
  57. package/dist/ghostDataTypes.d.ts.map +1 -1
  58. package/dist/ghostDataTypes.js.map +1 -1
  59. package/dist/index.d.ts +6 -4
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +4 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/types.d.ts +51 -2
  64. package/dist/types.d.ts.map +1 -1
  65. package/dist/types.js +6 -0
  66. package/dist/types.js.map +1 -1
  67. package/package.json +4 -1
  68. package/dist/BitStream.test.d.ts +0 -2
  69. package/dist/BitStream.test.d.ts.map +0 -1
  70. package/dist/BitStream.test.js +0 -419
  71. package/dist/BitStream.test.js.map +0 -1
  72. package/dist/ClassRegistry.test.d.ts +0 -2
  73. package/dist/ClassRegistry.test.d.ts.map +0 -1
  74. package/dist/ClassRegistry.test.js +0 -83
  75. package/dist/ClassRegistry.test.js.map +0 -1
  76. package/dist/DataBlockParsers.test.d.ts +0 -2
  77. package/dist/DataBlockParsers.test.d.ts.map +0 -1
  78. package/dist/DataBlockParsers.test.js +0 -294
  79. package/dist/DataBlockParsers.test.js.map +0 -1
  80. package/dist/DemoParser.test.d.ts +0 -2
  81. package/dist/DemoParser.test.d.ts.map +0 -1
  82. package/dist/DemoParser.test.js +0 -472
  83. package/dist/DemoParser.test.js.map +0 -1
  84. package/dist/GhostStateAccumulator.test.d.ts +0 -2
  85. package/dist/GhostStateAccumulator.test.d.ts.map +0 -1
  86. package/dist/GhostStateAccumulator.test.js +0 -201
  87. package/dist/GhostStateAccumulator.test.js.map +0 -1
  88. package/dist/GhostTracker.test.d.ts +0 -2
  89. package/dist/GhostTracker.test.d.ts.map +0 -1
  90. package/dist/GhostTracker.test.js +0 -64
  91. package/dist/GhostTracker.test.js.map +0 -1
  92. package/dist/IncrementalParser.test.d.ts +0 -2
  93. package/dist/IncrementalParser.test.d.ts.map +0 -1
  94. package/dist/IncrementalParser.test.js +0 -226
  95. package/dist/IncrementalParser.test.js.map +0 -1
@@ -1,4 +1,12 @@
1
1
  import type { BitStream } from "./BitStream.js";
2
+ import type { BitWriter } from "./BitWriter.js";
3
+ /** Strings longer than this cannot be encoded (8-bit length prefix). */
4
+ export declare const MaxHuffStringLength = 255;
5
+ /**
6
+ * Port of the engine's HuffmanProcessor (bitStream.cc). The tree is built
7
+ * once from the fixed frequency table, so decoding depends on nothing but
8
+ * the wire bits.
9
+ */
2
10
  export declare class HuffmanProcessor {
3
11
  private nodes;
4
12
  private leaves;
@@ -7,6 +15,13 @@ export declare class HuffmanProcessor {
7
15
  private determineIndex;
8
16
  private generateCodes;
9
17
  readHuffBuffer(stream: BitStream): string;
18
+ /**
19
+ * Encode a string the way the engine's writeHuffBuffer does: a flag
20
+ * selecting compressed vs. raw bytes (compressed only when it is
21
+ * shorter), an 8-bit length, then either Huffman codes or raw bytes.
22
+ * Characters are written as Latin-1 bytes (code units above 255 throw).
23
+ */
24
+ writeHuffBuffer(writer: BitWriter, value: string): void;
10
25
  }
11
26
  export declare const huffProcessor: HuffmanProcessor;
12
27
  //# sourceMappingURL=HuffmanProcessor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HuffmanProcessor.d.ts","sourceRoot":"","sources":["../src/HuffmanProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwDhD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAS;IAE5B,WAAW,IAAI,IAAI;IA0EnB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,aAAa;IAerB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;CAgC1C;AAGD,eAAO,MAAM,aAAa,kBAAyB,CAAC"}
1
+ {"version":3,"file":"HuffmanProcessor.d.ts","sourceRoot":"","sources":["../src/HuffmanProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwDhD,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAS;IAE5B,WAAW,IAAI,IAAI;IA0EnB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,aAAa;IAerB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAiCzC;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAgCxD;AAGD,eAAO,MAAM,aAAa,kBAAyB,CAAC"}
@@ -30,6 +30,13 @@ function wrapGetPop(w) {
30
30
  return w.node.pop;
31
31
  return w.leaf.pop;
32
32
  }
33
+ /** Strings longer than this cannot be encoded (8-bit length prefix). */
34
+ export const MaxHuffStringLength = 255;
35
+ /**
36
+ * Port of the engine's HuffmanProcessor (bitStream.cc). The tree is built
37
+ * once from the fixed frequency table, so decoding depends on nothing but
38
+ * the wire bits.
39
+ */
33
40
  export class HuffmanProcessor {
34
41
  nodes = [];
35
42
  leaves = [];
@@ -157,6 +164,44 @@ export class HuffmanProcessor {
157
164
  return String.fromCharCode(...bytes);
158
165
  }
159
166
  }
167
+ /**
168
+ * Encode a string the way the engine's writeHuffBuffer does: a flag
169
+ * selecting compressed vs. raw bytes (compressed only when it is
170
+ * shorter), an 8-bit length, then either Huffman codes or raw bytes.
171
+ * Characters are written as Latin-1 bytes (code units above 255 throw).
172
+ */
173
+ writeHuffBuffer(writer, value) {
174
+ if (!this.tablesBuilt) {
175
+ this.buildTables();
176
+ }
177
+ if (value.length > MaxHuffStringLength) {
178
+ throw new RangeError(`string too long for Huffman buffer: ${value.length} > ${MaxHuffStringLength}`);
179
+ }
180
+ const codes = new Array(value.length);
181
+ let numBits = 0;
182
+ for (let i = 0; i < value.length; i++) {
183
+ const c = value.charCodeAt(i);
184
+ if (c > 255) {
185
+ throw new RangeError(`non-Latin-1 character at index ${i}`);
186
+ }
187
+ codes[i] = c;
188
+ numBits += this.leaves[c].numBits;
189
+ }
190
+ if (numBits >= value.length * 8) {
191
+ writer.writeFlag(false);
192
+ writer.writeInt(value.length, 8);
193
+ for (const c of codes)
194
+ writer.writeInt(c, 8);
195
+ }
196
+ else {
197
+ writer.writeFlag(true);
198
+ writer.writeInt(value.length, 8);
199
+ for (const c of codes) {
200
+ const leaf = this.leaves[c];
201
+ writer.writeInt(leaf.code, leaf.numBits);
202
+ }
203
+ }
204
+ }
160
205
  }
161
206
  // Singleton instance matching the C++ g_huffProcessor
162
207
  export const huffProcessor = new HuffmanProcessor();
@@ -1 +1 @@
1
- {"version":3,"file":"HuffmanProcessor.js","sourceRoot":"","sources":["../src/HuffmanProcessor.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,cAAc,GAAa;IAC/B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ;IACxD,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ;IACnE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ;IAC5E,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ;IAC/E,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ;IACxE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS;IAC7F,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,UAAU;IAChF,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,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","sourcesContent":["import type { BitStream } from \"./BitStream.js\";\n\n// Hardcoded character frequency table from the V12 engine (bitStream.cc)\n// These are used to build the Huffman tree for string compression.\nconst CSM_CHAR_FREQS: number[] = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 329, 21, 0, 0, 0, 0, 0, // 0-15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31\n 2809, 68, 0, 27, 0, 58, 3, 62, 4, 7, 0, 0, 15, 65, 554, 3, // 32-47\n 394, 404, 189, 117, 30, 51, 27, 15, 34, 32, 80, 1, 142, 3, 142, 39, // 48-63\n 0, 144, 125, 44, 122, 275, 70, 135, 61, 127, 8, 12, 113, 246, 122, 36, // 64-79\n 185, 1, 149, 309, 335, 12, 11, 14, 54, 151, 0, 0, 2, 0, 0, 211, // 80-95\n 0, 2090, 344, 736, 993, 2872, 701, 605, 646, 1552, 328, 305, 1240, 735, 1533, 1713, // 96-111\n 562, 3, 1775, 1149, 1469, 979, 407, 553, 59, 279, 31, 0, 0, 0, 68, 0, // 112-127\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-255\n];\n\nconst PROB_BOOST = 1;\n\nfunction isAlphaNumeric(c: number): boolean {\n return (\n (c >= 48 && c <= 57) || // 0-9\n (c >= 65 && c <= 90) || // A-Z\n (c >= 97 && c <= 122) // a-z\n );\n}\n\ninterface HuffNode {\n pop: number;\n index0: number;\n index1: number;\n}\n\ninterface HuffLeaf {\n pop: number;\n symbol: number;\n numBits: number;\n code: number;\n}\n\ninterface HuffWrap {\n node: HuffNode | null;\n leaf: HuffLeaf | null;\n}\n\nfunction wrapGetPop(w: HuffWrap): number {\n if (w.node) return w.node.pop;\n return w.leaf!.pop;\n}\n\nexport class HuffmanProcessor {\n private nodes: HuffNode[] = [];\n private leaves: HuffLeaf[] = [];\n private tablesBuilt = false;\n\n buildTables(): void {\n if (this.tablesBuilt) return;\n this.tablesBuilt = true;\n\n // Initialize leaves from frequency table\n this.leaves = [];\n for (let i = 0; i < 256; i++) {\n this.leaves.push({\n pop:\n CSM_CHAR_FREQS[i] +\n (isAlphaNumeric(i) ? PROB_BOOST : 0) +\n PROB_BOOST,\n symbol: i,\n numBits: 0,\n code: 0,\n });\n }\n\n // Initialize nodes array with one placeholder at index 0\n this.nodes = [{ pop: 0, index0: 0, index1: 0 }];\n\n // Build wraps array\n let currWraps = 256;\n const wraps: HuffWrap[] = [];\n for (let i = 0; i < 256; i++) {\n wraps.push({ node: null, leaf: this.leaves[i] });\n }\n\n // Build the Huffman tree by repeatedly combining the two lowest-population wraps\n while (currWraps !== 1) {\n let min1 = 0xfffffffe;\n let min2 = 0xffffffff;\n let index1 = -1;\n let index2 = -1;\n\n for (let i = 0; i < currWraps; i++) {\n const pop = wrapGetPop(wraps[i]);\n if (pop < min1) {\n min2 = min1;\n index2 = index1;\n min1 = pop;\n index1 = i;\n } else if (pop < min2) {\n min2 = pop;\n index2 = i;\n }\n }\n\n // Create a new node combining the two smallest\n const newNode: HuffNode = {\n pop: wrapGetPop(wraps[index1]) + wrapGetPop(wraps[index2]),\n index0: this.determineIndex(wraps[index1]),\n index1: this.determineIndex(wraps[index2]),\n };\n this.nodes.push(newNode);\n\n // Replace the lower-indexed wrap with the new node, remove the higher-indexed one\n const mergeIndex = index1 < index2 ? index1 : index2;\n const nukeIndex = index1 > index2 ? index1 : index2;\n wraps[mergeIndex] = { node: newNode, leaf: null };\n\n if (nukeIndex !== currWraps - 1) {\n wraps[nukeIndex] = wraps[currWraps - 1];\n }\n currWraps--;\n }\n\n // The root node should be at nodes[0]\n this.nodes[0] = wraps[0].node!;\n\n // Generate Huffman codes by walking the tree\n this.generateCodes(0, 0, 0);\n }\n\n private determineIndex(wrap: HuffWrap): number {\n if (wrap.leaf !== null) {\n // Leaf index is encoded as -(leafArrayIndex + 1)\n const leafIdx = this.leaves.indexOf(wrap.leaf);\n return -(leafIdx + 1);\n } else {\n return this.nodes.indexOf(wrap.node!);\n }\n }\n\n private generateCodes(code: number, nodeIndex: number, depth: number): void {\n if (nodeIndex < 0) {\n // Leaf node\n const leaf = this.leaves[-(nodeIndex + 1)];\n leaf.code = code;\n leaf.numBits = depth;\n } else {\n const node = this.nodes[nodeIndex];\n // Go left (0 bit)\n this.generateCodes(code, node.index0, depth + 1);\n // Go right (1 bit)\n this.generateCodes(code | (1 << depth), node.index1, depth + 1);\n }\n }\n\n readHuffBuffer(stream: BitStream): string {\n if (!this.tablesBuilt) {\n this.buildTables();\n }\n\n if (stream.readFlag()) {\n // Huffman-compressed string\n const len = stream.readInt(8);\n const chars: number[] = [];\n for (let i = 0; i < len; i++) {\n let index = 0;\n while (true) {\n if (index >= 0) {\n if (stream.readFlag()) {\n index = this.nodes[index].index1;\n } else {\n index = this.nodes[index].index0;\n }\n } else {\n chars.push(this.leaves[-(index + 1)].symbol);\n break;\n }\n }\n }\n return String.fromCharCode(...chars);\n } else {\n // Uncompressed string\n const len = stream.readInt(8);\n const bytes = stream.readBytes(len);\n return String.fromCharCode(...bytes);\n }\n }\n}\n\n// Singleton instance matching the C++ g_huffProcessor\nexport const huffProcessor = new HuffmanProcessor();\n"]}
1
+ {"version":3,"file":"HuffmanProcessor.js","sourceRoot":"","sources":["../src/HuffmanProcessor.ts"],"names":[],"mappings":"AAGA,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,cAAc,GAAa;IAC/B,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ;IACxD,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ;IACnE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ;IAC5E,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ;IAC/E,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ;IACxE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS;IAC7F,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,UAAU;IAChF,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU;IAC1D,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,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","sourcesContent":["import type { BitStream } from \"./BitStream.js\";\nimport type { BitWriter } from \"./BitWriter.js\";\n\n// Hardcoded character frequency table from the V12 engine (bitStream.cc)\n// These are used to build the Huffman tree for string compression.\nconst CSM_CHAR_FREQS: number[] = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 329, 21, 0, 0, 0, 0, 0, // 0-15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31\n 2809, 68, 0, 27, 0, 58, 3, 62, 4, 7, 0, 0, 15, 65, 554, 3, // 32-47\n 394, 404, 189, 117, 30, 51, 27, 15, 34, 32, 80, 1, 142, 3, 142, 39, // 48-63\n 0, 144, 125, 44, 122, 275, 70, 135, 61, 127, 8, 12, 113, 246, 122, 36, // 64-79\n 185, 1, 149, 309, 335, 12, 11, 14, 54, 151, 0, 0, 2, 0, 0, 211, // 80-95\n 0, 2090, 344, 736, 993, 2872, 701, 605, 646, 1552, 328, 305, 1240, 735, 1533, 1713, // 96-111\n 562, 3, 1775, 1149, 1469, 979, 407, 553, 59, 279, 31, 0, 0, 0, 68, 0, // 112-127\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-255\n];\n\nconst PROB_BOOST = 1;\n\nfunction isAlphaNumeric(c: number): boolean {\n return (\n (c >= 48 && c <= 57) || // 0-9\n (c >= 65 && c <= 90) || // A-Z\n (c >= 97 && c <= 122) // a-z\n );\n}\n\ninterface HuffNode {\n pop: number;\n index0: number;\n index1: number;\n}\n\ninterface HuffLeaf {\n pop: number;\n symbol: number;\n numBits: number;\n code: number;\n}\n\ninterface HuffWrap {\n node: HuffNode | null;\n leaf: HuffLeaf | null;\n}\n\nfunction wrapGetPop(w: HuffWrap): number {\n if (w.node) return w.node.pop;\n return w.leaf!.pop;\n}\n\n/** Strings longer than this cannot be encoded (8-bit length prefix). */\nexport const MaxHuffStringLength = 255;\n\n/**\n * Port of the engine's HuffmanProcessor (bitStream.cc). The tree is built\n * once from the fixed frequency table, so decoding depends on nothing but\n * the wire bits.\n */\nexport class HuffmanProcessor {\n private nodes: HuffNode[] = [];\n private leaves: HuffLeaf[] = [];\n private tablesBuilt = false;\n\n buildTables(): void {\n if (this.tablesBuilt) return;\n this.tablesBuilt = true;\n\n // Initialize leaves from frequency table\n this.leaves = [];\n for (let i = 0; i < 256; i++) {\n this.leaves.push({\n pop:\n CSM_CHAR_FREQS[i] +\n (isAlphaNumeric(i) ? PROB_BOOST : 0) +\n PROB_BOOST,\n symbol: i,\n numBits: 0,\n code: 0,\n });\n }\n\n // Initialize nodes array with one placeholder at index 0\n this.nodes = [{ pop: 0, index0: 0, index1: 0 }];\n\n // Build wraps array\n let currWraps = 256;\n const wraps: HuffWrap[] = [];\n for (let i = 0; i < 256; i++) {\n wraps.push({ node: null, leaf: this.leaves[i] });\n }\n\n // Build the Huffman tree by repeatedly combining the two lowest-population wraps\n while (currWraps !== 1) {\n let min1 = 0xfffffffe;\n let min2 = 0xffffffff;\n let index1 = -1;\n let index2 = -1;\n\n for (let i = 0; i < currWraps; i++) {\n const pop = wrapGetPop(wraps[i]);\n if (pop < min1) {\n min2 = min1;\n index2 = index1;\n min1 = pop;\n index1 = i;\n } else if (pop < min2) {\n min2 = pop;\n index2 = i;\n }\n }\n\n // Create a new node combining the two smallest\n const newNode: HuffNode = {\n pop: wrapGetPop(wraps[index1]) + wrapGetPop(wraps[index2]),\n index0: this.determineIndex(wraps[index1]),\n index1: this.determineIndex(wraps[index2]),\n };\n this.nodes.push(newNode);\n\n // Replace the lower-indexed wrap with the new node, remove the higher-indexed one\n const mergeIndex = index1 < index2 ? index1 : index2;\n const nukeIndex = index1 > index2 ? index1 : index2;\n wraps[mergeIndex] = { node: newNode, leaf: null };\n\n if (nukeIndex !== currWraps - 1) {\n wraps[nukeIndex] = wraps[currWraps - 1];\n }\n currWraps--;\n }\n\n // The root node should be at nodes[0]\n this.nodes[0] = wraps[0].node!;\n\n // Generate Huffman codes by walking the tree\n this.generateCodes(0, 0, 0);\n }\n\n private determineIndex(wrap: HuffWrap): number {\n if (wrap.leaf !== null) {\n // Leaf index is encoded as -(leafArrayIndex + 1)\n const leafIdx = this.leaves.indexOf(wrap.leaf);\n return -(leafIdx + 1);\n } else {\n return this.nodes.indexOf(wrap.node!);\n }\n }\n\n private generateCodes(code: number, nodeIndex: number, depth: number): void {\n if (nodeIndex < 0) {\n // Leaf node\n const leaf = this.leaves[-(nodeIndex + 1)];\n leaf.code = code;\n leaf.numBits = depth;\n } else {\n const node = this.nodes[nodeIndex];\n // Go left (0 bit)\n this.generateCodes(code, node.index0, depth + 1);\n // Go right (1 bit)\n this.generateCodes(code | (1 << depth), node.index1, depth + 1);\n }\n }\n\n readHuffBuffer(stream: BitStream): string {\n if (!this.tablesBuilt) {\n this.buildTables();\n }\n\n if (stream.readFlag()) {\n // Huffman-compressed string\n const len = stream.readInt(8);\n const chars: number[] = [];\n for (let i = 0; i < len; i++) {\n let index = 0;\n while (true) {\n if (index >= 0) {\n if (stream.readFlag()) {\n index = this.nodes[index].index1;\n } else {\n index = this.nodes[index].index0;\n }\n } else {\n chars.push(this.leaves[-(index + 1)].symbol);\n break;\n }\n }\n }\n return String.fromCharCode(...chars);\n } else {\n // Uncompressed string\n const len = stream.readInt(8);\n const bytes = stream.readBytes(len);\n return String.fromCharCode(...bytes);\n }\n }\n\n /**\n * Encode a string the way the engine's writeHuffBuffer does: a flag\n * selecting compressed vs. raw bytes (compressed only when it is\n * shorter), an 8-bit length, then either Huffman codes or raw bytes.\n * Characters are written as Latin-1 bytes (code units above 255 throw).\n */\n writeHuffBuffer(writer: BitWriter, value: string): void {\n if (!this.tablesBuilt) {\n this.buildTables();\n }\n if (value.length > MaxHuffStringLength) {\n throw new RangeError(\n `string too long for Huffman buffer: ${value.length} > ${MaxHuffStringLength}`,\n );\n }\n const codes = new Array<number>(value.length);\n let numBits = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value.charCodeAt(i);\n if (c > 255) {\n throw new RangeError(`non-Latin-1 character at index ${i}`);\n }\n codes[i] = c;\n numBits += this.leaves[c].numBits;\n }\n if (numBits >= value.length * 8) {\n writer.writeFlag(false);\n writer.writeInt(value.length, 8);\n for (const c of codes) writer.writeInt(c, 8);\n } else {\n writer.writeFlag(true);\n writer.writeInt(value.length, 8);\n for (const c of codes) {\n const leaf = this.leaves[c];\n writer.writeInt(leaf.code, leaf.numBits);\n }\n }\n }\n}\n\n// Singleton instance matching the C++ g_huffProcessor\nexport const huffProcessor = new HuffmanProcessor();\n"]}
@@ -1,4 +1,4 @@
1
- import { ClassRegistry } from "./ClassRegistry.js";
1
+ import type { ClassRegistry } from "./ClassRegistry.js";
2
2
  import { GhostTracker } from "./GhostManager.js";
3
3
  import { PacketParser } from "./PacketParser.js";
4
4
  import type { ConnectionProtocolState, NetEventInfo } from "./types.js";
@@ -27,6 +27,8 @@ export interface LiveParserSeed {
27
27
  absoluteSequenceNumber: number;
28
28
  event: NetEventInfo;
29
29
  }>;
30
+ /** Passed to PacketParser; see its `haltOnFault` option (default true). */
31
+ haltOnFault?: boolean;
30
32
  }
31
33
  /**
32
34
  * Protocol state for a parser that passively observes the server→client
@@ -38,8 +40,25 @@ export interface LiveParserSeed {
38
40
  * connection: `lastSeqRecvd` starts at 0, so the 9-bit sequence window
39
41
  * check rejects packets attached mid-stream (seed
40
42
  * `connectionProtocolState` from the exporter in that case).
43
+ *
44
+ * This is parser-only state. Never write it into a .rec initial block:
45
+ * Tribes2.exe requires `notifyCount === lastSendSeq - highestAckedSeq`
46
+ * and treats `lastSendSeq - highestAckedSeq > 0x1d` as a full send window
47
+ * (no notify is queued for a SendPacket marker), so a demo seeded with
48
+ * this value crashes on the first acknowledged packet. Use
49
+ * `freshConnectionProtocolState` for a recording that starts at connect
50
+ * time.
41
51
  */
42
52
  export declare function passiveObserverProtocolState(firstPacketByte: number): ConnectionProtocolState;
53
+ /**
54
+ * The ConnectionProtocol state of a connection that has not yet exchanged
55
+ * a sequenced packet — what a demo whose stream starts at connect time
56
+ * must seed (with a notify count of 0, since nothing is in flight). The
57
+ * recorder must then write one SendPacket marker per packet it actually
58
+ * sends, before the received packet that acks it; Tribes2.exe replays
59
+ * those markers through checkPacketSend to rebuild the notify queue.
60
+ */
61
+ export declare function freshConnectionProtocolState(connectSequence: number): ConnectionProtocolState;
43
62
  /**
44
63
  * Create a parser stack for live server connections. Sets up the same
45
64
  * registry bindings as DemoParser but without requiring a demo file,
@@ -1 +1 @@
1
- {"version":3,"file":"LiveParser.d.ts","sourceRoot":"","sources":["../src/LiveParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAYjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5C,wEAAwE;IACxE,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,uBAAuB,CAAC,EAAE,KAAK,CAAC;QAC9B,sBAAsB,EAAE,MAAM,CAAC;QAC/B,KAAK,EAAE,YAAY,CAAC;KACrB,CAAC,CAAC;CACJ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,GACtB,uBAAuB,CAWzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,aAAa,CA0CrE"}
1
+ {"version":3,"file":"LiveParser.d.ts","sourceRoot":"","sources":["../src/LiveParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5C,wEAAwE;IACxE,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,uBAAuB,CAAC,EAAE,KAAK,CAAC;QAC9B,sBAAsB,EAAE,MAAM,CAAC;QAC/B,KAAK,EAAE,YAAY,CAAC;KACrB,CAAC,CAAC;IACH,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,GACtB,uBAAuB,CAWzB;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,GACtB,uBAAuB,CAWzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,aAAa,CAgCrE"}
@@ -1,10 +1,6 @@
1
- import { ClassRegistry } from "./ClassRegistry.js";
1
+ import { createDefaultRegistry } from "./defaultRegistry.js";
2
2
  import { GhostTracker } from "./GhostManager.js";
3
3
  import { PacketParser } from "./PacketParser.js";
4
- import { registerEventParsers } from "./EventParsers.js";
5
- import { registerGhostParsers } from "./GhostManager.js";
6
- import { registerDataBlockParsers } from "./DataBlockParsers.js";
7
- import { DataBlockClassFirst, DataBlockClassNames, NetObjectClassFirst, NetObjectClassNames, NetEventClassFirst, NetEventClassNames, } from "./types.js";
8
4
  /**
9
5
  * Protocol state for a parser that passively observes the server→client
10
6
  * stream while something else (e.g. a relay) owns the client→server side.
@@ -15,6 +11,14 @@ import { DataBlockClassFirst, DataBlockClassNames, NetObjectClassFirst, NetObjec
15
11
  * connection: `lastSeqRecvd` starts at 0, so the 9-bit sequence window
16
12
  * check rejects packets attached mid-stream (seed
17
13
  * `connectionProtocolState` from the exporter in that case).
14
+ *
15
+ * This is parser-only state. Never write it into a .rec initial block:
16
+ * Tribes2.exe requires `notifyCount === lastSendSeq - highestAckedSeq`
17
+ * and treats `lastSendSeq - highestAckedSeq > 0x1d` as a full send window
18
+ * (no notify is queued for a SendPacket marker), so a demo seeded with
19
+ * this value crashes on the first acknowledged packet. Use
20
+ * `freshConnectionProtocolState` for a recording that starts at connect
21
+ * time.
18
22
  */
19
23
  export function passiveObserverProtocolState(firstPacketByte) {
20
24
  return {
@@ -28,6 +32,26 @@ export function passiveObserverProtocolState(firstPacketByte) {
28
32
  connectionEstablished: true,
29
33
  };
30
34
  }
35
+ /**
36
+ * The ConnectionProtocol state of a connection that has not yet exchanged
37
+ * a sequenced packet — what a demo whose stream starts at connect time
38
+ * must seed (with a notify count of 0, since nothing is in flight). The
39
+ * recorder must then write one SendPacket marker per packet it actually
40
+ * sends, before the received packet that acks it; Tribes2.exe replays
41
+ * those markers through checkPacketSend to rebuild the notify queue.
42
+ */
43
+ export function freshConnectionProtocolState(connectSequence) {
44
+ return {
45
+ lastSeqRecvdAtSend: new Array(32).fill(0),
46
+ lastSeqRecvd: 0,
47
+ highestAckedSeq: 0,
48
+ lastSendSeq: 0,
49
+ ackMask: 0,
50
+ connectSequence: connectSequence >>> 0,
51
+ lastRecvAckAck: 0,
52
+ connectionEstablished: true,
53
+ };
54
+ }
31
55
  /**
32
56
  * Create a parser stack for live server connections. Sets up the same
33
57
  * registry bindings as DemoParser but without requiring a demo file,
@@ -39,14 +63,8 @@ export function passiveObserverProtocolState(firstPacketByte) {
39
63
  * continue parsing at a packet boundary in lockstep with the exporter.
40
64
  */
41
65
  export function createLiveParser(seed) {
42
- const registry = new ClassRegistry();
66
+ const registry = createDefaultRegistry();
43
67
  const ghostTracker = new GhostTracker();
44
- registerEventParsers(registry);
45
- registerGhostParsers(registry);
46
- registerDataBlockParsers(registry);
47
- registry.bindDeterministicDataBlocks(DataBlockClassNames, DataBlockClassFirst);
48
- registry.bindDeterministicGhosts(NetObjectClassNames, NetObjectClassFirst);
49
- registry.bindDeterministicEvents(NetEventClassNames, NetEventClassFirst);
50
68
  const dataBlockDataMap = new Map();
51
69
  if (seed?.dataBlocks) {
52
70
  for (const [objectId, data] of seed.dataBlocks) {
@@ -65,6 +83,7 @@ export function createLiveParser(seed) {
65
83
  nextRecvEventSeq: seed?.nextRecvEventSeq,
66
84
  compressionPoint: seed?.compressionPoint,
67
85
  pendingGuaranteedEvents: seed?.pendingGuaranteedEvents,
86
+ haltOnFault: seed?.haltOnFault,
68
87
  });
69
88
  return { registry, ghostTracker, packetParser };
70
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LiveParser.js","sourceRoot":"","sources":["../src/LiveParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAwBpB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC1C,eAAuB;IAEvB,OAAO;QACL,kBAAkB,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,CAAC;QAClB,WAAW,EAAE,UAAU;QACvB,OAAO,EAAE,CAAC;QACV,eAAe,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC;QAC3C,cAAc,EAAE,CAAC;QACjB,qBAAqB,EAAE,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAqB;IACpD,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IAExC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/B,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/B,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,QAAQ,CAAC,2BAA2B,CAClC,mBAAmB,EACnB,mBAAmB,CACpB,CAAC;IACF,QAAQ,CAAC,uBAAuB,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC;IAC3E,QAAQ,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;IAEzE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAsB,CAAC;IACvD,IAAI,IAAI,EAAE,UAAU,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3D,YAAY,CAAC,WAAW,CACtB,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,EACb,WAAW,EAAE,IAAI,IAAI,WAAW,KAAK,CAAC,OAAO,EAAE,CAChD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE;QAC5D,gBAAgB;QAChB,uBAAuB,EAAE,IAAI,EAAE,uBAAuB;QACtD,gBAAgB,EAAE,IAAI,EAAE,gBAAgB;QACxC,gBAAgB,EAAE,IAAI,EAAE,gBAAgB;QACxC,uBAAuB,EAAE,IAAI,EAAE,uBAAuB;KACvD,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import { ClassRegistry } from \"./ClassRegistry.js\";\nimport { GhostTracker } from \"./GhostManager.js\";\nimport { PacketParser } from \"./PacketParser.js\";\nimport { registerEventParsers } from \"./EventParsers.js\";\nimport { registerGhostParsers } from \"./GhostManager.js\";\nimport { registerDataBlockParsers } from \"./DataBlockParsers.js\";\nimport {\n DataBlockClassFirst,\n DataBlockClassNames,\n NetObjectClassFirst,\n NetObjectClassNames,\n NetEventClassFirst,\n NetEventClassNames,\n} from \"./types.js\";\nimport type { ConnectionProtocolState, NetEventInfo } from \"./types.js\";\nimport type { ParsedData } from \"./ClassRegistry.js\";\n\nexport interface LiveParserKit {\n registry: ClassRegistry;\n ghostTracker: GhostTracker;\n packetParser: PacketParser;\n}\n\nexport interface LiveParserSeed {\n /** objectId → parsed datablock data, copied into the parser's map. */\n dataBlocks?: Iterable<[number, ParsedData]>;\n /** Existing ghosts, so mid-stream updates aren't misread as creates. */\n ghosts?: Iterable<{ index: number; classId: number }>;\n connectionProtocolState?: ConnectionProtocolState;\n nextRecvEventSeq?: number;\n compressionPoint?: { x: number; y: number; z: number };\n pendingGuaranteedEvents?: Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }>;\n}\n\n/**\n * Protocol state for a parser that passively observes the server→client\n * stream while something else (e.g. a relay) owns the client→server side.\n * `lastSendSeq` is set very high so ack validation (lastSendSeq <\n * highestAck → reject) never fires when the server acks sequences the\n * observer didn't send. The connect-sequence bit is taken from the first\n * observed packet's header byte. Intended for the first packets of a\n * connection: `lastSeqRecvd` starts at 0, so the 9-bit sequence window\n * check rejects packets attached mid-stream (seed\n * `connectionProtocolState` from the exporter in that case).\n */\nexport function passiveObserverProtocolState(\n firstPacketByte: number,\n): ConnectionProtocolState {\n return {\n lastSeqRecvdAtSend: new Array(32).fill(0),\n lastSeqRecvd: 0,\n highestAckedSeq: 0,\n lastSendSeq: 0x1fffffff,\n ackMask: 0,\n connectSequence: (firstPacketByte >> 1) & 1,\n lastRecvAckAck: 0,\n connectionEstablished: true,\n };\n}\n\n/**\n * Create a parser stack for live server connections. Sets up the same\n * registry bindings as DemoParser but without requiring a demo file,\n * and includes a dataBlockDataMap for incremental datablock accumulation\n * via SimDataBlockEvent.\n *\n * With a seed, the stack resumes an in-progress stream from exported\n * state (mirroring DemoParser.setupPacketParser), so a late joiner can\n * continue parsing at a packet boundary in lockstep with the exporter.\n */\nexport function createLiveParser(seed?: LiveParserSeed): LiveParserKit {\n const registry = new ClassRegistry();\n const ghostTracker = new GhostTracker();\n\n registerEventParsers(registry);\n registerGhostParsers(registry);\n registerDataBlockParsers(registry);\n\n registry.bindDeterministicDataBlocks(\n DataBlockClassNames,\n DataBlockClassFirst,\n );\n registry.bindDeterministicGhosts(NetObjectClassNames, NetObjectClassFirst);\n registry.bindDeterministicEvents(NetEventClassNames, NetEventClassFirst);\n\n const dataBlockDataMap = new Map<number, ParsedData>();\n if (seed?.dataBlocks) {\n for (const [objectId, data] of seed.dataBlocks) {\n dataBlockDataMap.set(objectId, data);\n }\n }\n\n if (seed?.ghosts) {\n for (const ghost of seed.ghosts) {\n const parserEntry = registry.getGhostParser(ghost.classId);\n ghostTracker.createGhost(\n ghost.index,\n ghost.classId,\n parserEntry?.name ?? `unknown_${ghost.classId}`,\n );\n }\n }\n\n const packetParser = new PacketParser(registry, ghostTracker, {\n dataBlockDataMap,\n connectionProtocolState: seed?.connectionProtocolState,\n nextRecvEventSeq: seed?.nextRecvEventSeq,\n compressionPoint: seed?.compressionPoint,\n pendingGuaranteedEvents: seed?.pendingGuaranteedEvents,\n });\n\n return { registry, ghostTracker, packetParser };\n}\n"]}
1
+ {"version":3,"file":"LiveParser.js","sourceRoot":"","sources":["../src/LiveParser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA0BjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,4BAA4B,CAC1C,eAAuB;IAEvB,OAAO;QACL,kBAAkB,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,CAAC;QAClB,WAAW,EAAE,UAAU;QACvB,OAAO,EAAE,CAAC;QACV,eAAe,EAAE,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC;QAC3C,cAAc,EAAE,CAAC;QACjB,qBAAqB,EAAE,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAC1C,eAAuB;IAEvB,OAAO;QACL,kBAAkB,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,CAAC;QAClB,WAAW,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;QACV,eAAe,EAAE,eAAe,KAAK,CAAC;QACtC,cAAc,EAAE,CAAC;QACjB,qBAAqB,EAAE,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAqB;IACpD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IAExC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAsB,CAAC;IACvD,IAAI,IAAI,EAAE,UAAU,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3D,YAAY,CAAC,WAAW,CACtB,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,EACb,WAAW,EAAE,IAAI,IAAI,WAAW,KAAK,CAAC,OAAO,EAAE,CAChD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE;QAC5D,gBAAgB;QAChB,uBAAuB,EAAE,IAAI,EAAE,uBAAuB;QACtD,gBAAgB,EAAE,IAAI,EAAE,gBAAgB;QACxC,gBAAgB,EAAE,IAAI,EAAE,gBAAgB;QACxC,uBAAuB,EAAE,IAAI,EAAE,uBAAuB;QACtD,WAAW,EAAE,IAAI,EAAE,WAAW;KAC/B,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import type { ClassRegistry } from \"./ClassRegistry.js\";\nimport { createDefaultRegistry } from \"./defaultRegistry.js\";\nimport { GhostTracker } from \"./GhostManager.js\";\nimport { PacketParser } from \"./PacketParser.js\";\nimport type { ConnectionProtocolState, NetEventInfo } from \"./types.js\";\nimport type { ParsedData } from \"./ClassRegistry.js\";\n\nexport interface LiveParserKit {\n registry: ClassRegistry;\n ghostTracker: GhostTracker;\n packetParser: PacketParser;\n}\n\nexport interface LiveParserSeed {\n /** objectId → parsed datablock data, copied into the parser's map. */\n dataBlocks?: Iterable<[number, ParsedData]>;\n /** Existing ghosts, so mid-stream updates aren't misread as creates. */\n ghosts?: Iterable<{ index: number; classId: number }>;\n connectionProtocolState?: ConnectionProtocolState;\n nextRecvEventSeq?: number;\n compressionPoint?: { x: number; y: number; z: number };\n pendingGuaranteedEvents?: Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }>;\n /** Passed to PacketParser; see its `haltOnFault` option (default true). */\n haltOnFault?: boolean;\n}\n\n/**\n * Protocol state for a parser that passively observes the server→client\n * stream while something else (e.g. a relay) owns the client→server side.\n * `lastSendSeq` is set very high so ack validation (lastSendSeq <\n * highestAck → reject) never fires when the server acks sequences the\n * observer didn't send. The connect-sequence bit is taken from the first\n * observed packet's header byte. Intended for the first packets of a\n * connection: `lastSeqRecvd` starts at 0, so the 9-bit sequence window\n * check rejects packets attached mid-stream (seed\n * `connectionProtocolState` from the exporter in that case).\n *\n * This is parser-only state. Never write it into a .rec initial block:\n * Tribes2.exe requires `notifyCount === lastSendSeq - highestAckedSeq`\n * and treats `lastSendSeq - highestAckedSeq > 0x1d` as a full send window\n * (no notify is queued for a SendPacket marker), so a demo seeded with\n * this value crashes on the first acknowledged packet. Use\n * `freshConnectionProtocolState` for a recording that starts at connect\n * time.\n */\nexport function passiveObserverProtocolState(\n firstPacketByte: number,\n): ConnectionProtocolState {\n return {\n lastSeqRecvdAtSend: new Array(32).fill(0),\n lastSeqRecvd: 0,\n highestAckedSeq: 0,\n lastSendSeq: 0x1fffffff,\n ackMask: 0,\n connectSequence: (firstPacketByte >> 1) & 1,\n lastRecvAckAck: 0,\n connectionEstablished: true,\n };\n}\n\n/**\n * The ConnectionProtocol state of a connection that has not yet exchanged\n * a sequenced packet — what a demo whose stream starts at connect time\n * must seed (with a notify count of 0, since nothing is in flight). The\n * recorder must then write one SendPacket marker per packet it actually\n * sends, before the received packet that acks it; Tribes2.exe replays\n * those markers through checkPacketSend to rebuild the notify queue.\n */\nexport function freshConnectionProtocolState(\n connectSequence: number,\n): ConnectionProtocolState {\n return {\n lastSeqRecvdAtSend: new Array(32).fill(0),\n lastSeqRecvd: 0,\n highestAckedSeq: 0,\n lastSendSeq: 0,\n ackMask: 0,\n connectSequence: connectSequence >>> 0,\n lastRecvAckAck: 0,\n connectionEstablished: true,\n };\n}\n\n/**\n * Create a parser stack for live server connections. Sets up the same\n * registry bindings as DemoParser but without requiring a demo file,\n * and includes a dataBlockDataMap for incremental datablock accumulation\n * via SimDataBlockEvent.\n *\n * With a seed, the stack resumes an in-progress stream from exported\n * state (mirroring DemoParser.setupPacketParser), so a late joiner can\n * continue parsing at a packet boundary in lockstep with the exporter.\n */\nexport function createLiveParser(seed?: LiveParserSeed): LiveParserKit {\n const registry = createDefaultRegistry();\n const ghostTracker = new GhostTracker();\n\n const dataBlockDataMap = new Map<number, ParsedData>();\n if (seed?.dataBlocks) {\n for (const [objectId, data] of seed.dataBlocks) {\n dataBlockDataMap.set(objectId, data);\n }\n }\n\n if (seed?.ghosts) {\n for (const ghost of seed.ghosts) {\n const parserEntry = registry.getGhostParser(ghost.classId);\n ghostTracker.createGhost(\n ghost.index,\n ghost.classId,\n parserEntry?.name ?? `unknown_${ghost.classId}`,\n );\n }\n }\n\n const packetParser = new PacketParser(registry, ghostTracker, {\n dataBlockDataMap,\n connectionProtocolState: seed?.connectionProtocolState,\n nextRecvEventSeq: seed?.nextRecvEventSeq,\n compressionPoint: seed?.compressionPoint,\n pendingGuaranteedEvents: seed?.pendingGuaranteedEvents,\n haltOnFault: seed?.haltOnFault,\n });\n\n return { registry, ghostTracker, packetParser };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { ConnectionProtocolState, PacketData, NetEventInfo } from "./types.js";
1
+ import type { ConnectionProtocolState, PacketData, ParseFault, NetEventInfo } from "./types.js";
2
2
  import type { ClassRegistry, ParsedData } from "./ClassRegistry.js";
3
3
  import type { GhostTracker } from "./GhostManager.js";
4
4
  /**
@@ -25,6 +25,8 @@ export declare class PacketParser {
25
25
  private _connectionEstablished;
26
26
  private nextRecvEventSeq;
27
27
  private pendingGuaranteedEvents;
28
+ private readonly haltOnFault;
29
+ private _fault?;
28
30
  controlObjectParsed: number;
29
31
  controlObjectFailed: number;
30
32
  eventsParsed: number;
@@ -41,6 +43,8 @@ export declare class PacketParser {
41
43
  packetsParsed: number;
42
44
  protocolRejected: number;
43
45
  protocolNoDispatch: number;
46
+ /** Packets received after the parser faulted and halted. */
47
+ packetsDroppedAfterFault: number;
44
48
  constructor(registry: ClassRegistry, ghostTracker: GhostTracker, options?: {
45
49
  dataBlockDataMap?: Map<number, ParsedData>;
46
50
  connectionProtocolState?: ConnectionProtocolState;
@@ -54,13 +58,29 @@ export declare class PacketParser {
54
58
  absoluteSequenceNumber: number;
55
59
  event: NetEventInfo;
56
60
  }>;
61
+ /**
62
+ * Stop parsing after the first packet that faults (default true).
63
+ * The engine drops the connection on an unreadable packet, and every
64
+ * later packet would be parsed against ghost/event state that no
65
+ * longer mirrors the server. Set false to keep going regardless.
66
+ */
67
+ haltOnFault?: boolean;
57
68
  });
58
69
  getCompressionPoint(): {
59
70
  x: number;
60
71
  y: number;
61
72
  z: number;
62
73
  };
63
- getDataBlockDataMap(): Map<number, ParsedData> | undefined;
74
+ /** Live datablock map (grows as SimDataBlockEvents arrive). */
75
+ getDataBlockDataMap(): ReadonlyMap<number, ParsedData> | undefined;
76
+ /**
77
+ * The first parse fault, if any. Once set (and `haltOnFault` is on),
78
+ * later packets are returned empty with this fault attached; build a
79
+ * fresh parser (DemoParser.reset(), or a new createLiveParser seeded
80
+ * from a known-good state) to continue.
81
+ */
82
+ get fault(): ParseFault | undefined;
83
+ get faulted(): boolean;
64
84
  private getConnectionContext;
65
85
  private _setNextRecvEventSeq;
66
86
  setConnectionProtocolState(state: ConnectionProtocolState): void;
@@ -1 +1 @@
1
- {"version":3,"file":"PacketParser.d.ts","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PacketParser.d.ts","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"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"}