t2-demo-parser 2.2.0 → 3.0.0
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.
- package/README.md +170 -7
- package/dist/BitStream.d.ts +14 -3
- package/dist/BitStream.d.ts.map +1 -1
- package/dist/BitStream.js +28 -6
- package/dist/BitStream.js.map +1 -1
- package/dist/BitWriter.d.ts +29 -0
- package/dist/BitWriter.d.ts.map +1 -0
- package/dist/BitWriter.js +76 -0
- package/dist/BitWriter.js.map +1 -0
- package/dist/ClassRegistry.d.ts +23 -28
- package/dist/ClassRegistry.d.ts.map +1 -1
- package/dist/ClassRegistry.js +75 -84
- package/dist/ClassRegistry.js.map +1 -1
- package/dist/DataBlockParsers.d.ts.map +1 -1
- package/dist/DataBlockParsers.js +51 -76
- package/dist/DataBlockParsers.js.map +1 -1
- package/dist/DemoParser.d.ts +23 -22
- package/dist/DemoParser.d.ts.map +1 -1
- package/dist/DemoParser.js +218 -266
- package/dist/DemoParser.js.map +1 -1
- package/dist/EventParsers.d.ts.map +1 -1
- package/dist/EventParsers.js +87 -58
- package/dist/EventParsers.js.map +1 -1
- package/dist/GhostManager.d.ts +7 -1
- package/dist/GhostManager.d.ts.map +1 -1
- package/dist/GhostManager.js +231 -146
- package/dist/GhostManager.js.map +1 -1
- package/dist/HuffmanProcessor.d.ts +15 -0
- package/dist/HuffmanProcessor.d.ts.map +1 -1
- package/dist/HuffmanProcessor.js +45 -0
- package/dist/HuffmanProcessor.js.map +1 -1
- package/dist/LiveParser.d.ts +20 -1
- package/dist/LiveParser.d.ts.map +1 -1
- package/dist/LiveParser.js +31 -12
- package/dist/LiveParser.js.map +1 -1
- package/dist/PacketParser.d.ts +22 -2
- package/dist/PacketParser.d.ts.map +1 -1
- package/dist/PacketParser.js +111 -48
- package/dist/PacketParser.js.map +1 -1
- package/dist/Timeline.d.ts +5 -2
- package/dist/Timeline.d.ts.map +1 -1
- package/dist/Timeline.js +25 -12
- package/dist/Timeline.js.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/dataBlockDataTypes.d.ts +111 -112
- package/dist/dataBlockDataTypes.d.ts.map +1 -1
- package/dist/dataBlockDataTypes.js.map +1 -1
- package/dist/defaultRegistry.d.ts +9 -0
- package/dist/defaultRegistry.d.ts.map +1 -0
- package/dist/defaultRegistry.js +43 -0
- package/dist/defaultRegistry.js.map +1 -0
- package/dist/eventDataTypes.d.ts +74 -72
- package/dist/eventDataTypes.d.ts.map +1 -1
- package/dist/eventDataTypes.js.map +1 -1
- package/dist/ghostDataTypes.d.ts +125 -131
- package/dist/ghostDataTypes.d.ts.map +1 -1
- package/dist/ghostDataTypes.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +51 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -1
- package/dist/BitStream.test.d.ts +0 -2
- package/dist/BitStream.test.d.ts.map +0 -1
- package/dist/BitStream.test.js +0 -419
- package/dist/BitStream.test.js.map +0 -1
- package/dist/ClassRegistry.test.d.ts +0 -2
- package/dist/ClassRegistry.test.d.ts.map +0 -1
- package/dist/ClassRegistry.test.js +0 -83
- package/dist/ClassRegistry.test.js.map +0 -1
- package/dist/DataBlockParsers.test.d.ts +0 -2
- package/dist/DataBlockParsers.test.d.ts.map +0 -1
- package/dist/DataBlockParsers.test.js +0 -294
- package/dist/DataBlockParsers.test.js.map +0 -1
- package/dist/DemoParser.test.d.ts +0 -2
- package/dist/DemoParser.test.d.ts.map +0 -1
- package/dist/DemoParser.test.js +0 -472
- package/dist/DemoParser.test.js.map +0 -1
- package/dist/GhostStateAccumulator.test.d.ts +0 -2
- package/dist/GhostStateAccumulator.test.d.ts.map +0 -1
- package/dist/GhostStateAccumulator.test.js +0 -201
- package/dist/GhostStateAccumulator.test.js.map +0 -1
- package/dist/GhostTracker.test.d.ts +0 -2
- package/dist/GhostTracker.test.d.ts.map +0 -1
- package/dist/GhostTracker.test.js +0 -64
- package/dist/GhostTracker.test.js.map +0 -1
- package/dist/IncrementalParser.test.d.ts +0 -2
- package/dist/IncrementalParser.test.d.ts.map +0 -1
- package/dist/IncrementalParser.test.js +0 -226
- package/dist/IncrementalParser.test.js.map +0 -1
package/dist/PacketParser.js
CHANGED
|
@@ -2,6 +2,10 @@ import createDebug from "debug";
|
|
|
2
2
|
import { BitStream } from "./BitStream.js";
|
|
3
3
|
import { DataPacket, MaxGhostCount, GhostMsgEndGhosting, NetEventClassBitSize, NetEventClassFirst, NetObjectClassBitSize, NetObjectClassFirst, } from "./types.js";
|
|
4
4
|
const debugGhosts = createDebug("t2-demo-parser:ghosts");
|
|
5
|
+
const debugEvents = createDebug("t2-demo-parser:events");
|
|
6
|
+
function errorMessage(e) {
|
|
7
|
+
return e instanceof Error ? e.message : String(e);
|
|
8
|
+
}
|
|
5
9
|
/**
|
|
6
10
|
* Parses individual network packets from demo recording blocks.
|
|
7
11
|
*
|
|
@@ -26,6 +30,8 @@ export class PacketParser {
|
|
|
26
30
|
_connectionEstablished = false;
|
|
27
31
|
nextRecvEventSeq = 0;
|
|
28
32
|
pendingGuaranteedEvents = [];
|
|
33
|
+
haltOnFault;
|
|
34
|
+
_fault;
|
|
29
35
|
// Stats
|
|
30
36
|
controlObjectParsed = 0;
|
|
31
37
|
controlObjectFailed = 0;
|
|
@@ -43,10 +49,13 @@ export class PacketParser {
|
|
|
43
49
|
packetsParsed = 0;
|
|
44
50
|
protocolRejected = 0;
|
|
45
51
|
protocolNoDispatch = 0;
|
|
52
|
+
/** Packets received after the parser faulted and halted. */
|
|
53
|
+
packetsDroppedAfterFault = 0;
|
|
46
54
|
constructor(registry, ghostTracker, options) {
|
|
47
55
|
this.registry = registry;
|
|
48
56
|
this.ghostTracker = ghostTracker;
|
|
49
57
|
this.dataBlockDataMap = options?.dataBlockDataMap;
|
|
58
|
+
this.haltOnFault = options?.haltOnFault ?? true;
|
|
50
59
|
if (options?.connectionProtocolState) {
|
|
51
60
|
this.setConnectionProtocolState(options.connectionProtocolState);
|
|
52
61
|
}
|
|
@@ -63,11 +72,24 @@ export class PacketParser {
|
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
74
|
getCompressionPoint() {
|
|
66
|
-
return this.compressionPoint;
|
|
75
|
+
return { ...this.compressionPoint };
|
|
67
76
|
}
|
|
77
|
+
/** Live datablock map (grows as SimDataBlockEvents arrive). */
|
|
68
78
|
getDataBlockDataMap() {
|
|
69
79
|
return this.dataBlockDataMap;
|
|
70
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* The first parse fault, if any. Once set (and `haltOnFault` is on),
|
|
83
|
+
* later packets are returned empty with this fault attached; build a
|
|
84
|
+
* fresh parser (DemoParser.reset(), or a new createLiveParser seeded
|
|
85
|
+
* from a known-good state) to continue.
|
|
86
|
+
*/
|
|
87
|
+
get fault() {
|
|
88
|
+
return this._fault;
|
|
89
|
+
}
|
|
90
|
+
get faulted() {
|
|
91
|
+
return this._fault !== undefined;
|
|
92
|
+
}
|
|
71
93
|
getConnectionContext() {
|
|
72
94
|
const dbMap = this.dataBlockDataMap;
|
|
73
95
|
return {
|
|
@@ -164,6 +186,9 @@ export class PacketParser {
|
|
|
164
186
|
const isAcked = (dnetHeader.ackMask & (1 << ((highestAck - ackSeq) & 0x1f))) !== 0;
|
|
165
187
|
if (isAcked) {
|
|
166
188
|
this.lastRecvAckAck = this.lastSeqRecvdAtSend[ackSeq & 0x1f] >>> 0;
|
|
189
|
+
// ConnectionProtocol::readPacketHeader (FUN_0043d4d0): the first
|
|
190
|
+
// acknowledged packet marks the connection established.
|
|
191
|
+
this._connectionEstablished = true;
|
|
167
192
|
}
|
|
168
193
|
}
|
|
169
194
|
if (seqNumber - this.lastRecvAckAck > 0x20) {
|
|
@@ -178,6 +203,20 @@ export class PacketParser {
|
|
|
178
203
|
const bs = new BitStream(data);
|
|
179
204
|
// 1. Parse dnet header
|
|
180
205
|
const dnetHeader = this.readDnetHeader(bs);
|
|
206
|
+
if (this._fault && this.haltOnFault) {
|
|
207
|
+
// Halted: mirror the engine, which has disconnected by now. The
|
|
208
|
+
// header is still decoded for the caller's benefit, but no state
|
|
209
|
+
// is touched.
|
|
210
|
+
this.packetsDroppedAfterFault++;
|
|
211
|
+
return {
|
|
212
|
+
dnetHeader,
|
|
213
|
+
rateInfo: {},
|
|
214
|
+
gameState: this.emptyGameState(),
|
|
215
|
+
events: [],
|
|
216
|
+
ghosts: [],
|
|
217
|
+
parseFault: this._fault,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
181
220
|
const protocol = this.applyProtocolHeader(dnetHeader);
|
|
182
221
|
this.packetsParsed++;
|
|
183
222
|
// ConnectionProtocol may reject this packet entirely (window/connect checks),
|
|
@@ -224,7 +263,32 @@ export class PacketParser {
|
|
|
224
263
|
const ghosts = gameStateComplete && eventsComplete
|
|
225
264
|
? this.readGhosts(bs, dnetHeader.seqNumber)
|
|
226
265
|
: [];
|
|
266
|
+
const lastGhost = ghosts[ghosts.length - 1];
|
|
227
267
|
bs.setStringBuffer(false);
|
|
268
|
+
let parseFault;
|
|
269
|
+
if (!gameStateComplete) {
|
|
270
|
+
parseFault = {
|
|
271
|
+
stage: "gameState",
|
|
272
|
+
message: `control object ghost ${gameState.controlObjectGhostIndex} could not be read${gameState.controlObjectError ? `: ${gameState.controlObjectError}` : ""}`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
else if (!eventsComplete) {
|
|
276
|
+
parseFault = {
|
|
277
|
+
stage: "event",
|
|
278
|
+
message: `event class ${lastEvent.classId} (${this.registry.getEventParser(lastEvent.classId)?.name ?? "unbound"}) failed to parse: ${lastEvent.error ?? "unknown error"}`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
else if (lastGhost?.failed) {
|
|
282
|
+
parseFault = {
|
|
283
|
+
stage: "ghost",
|
|
284
|
+
message: `ghost ${lastGhost.index} (class ${lastGhost.classId}, ${lastGhost.classId !== undefined
|
|
285
|
+
? (this.registry.getGhostParser(lastGhost.classId)?.name ?? "unbound")
|
|
286
|
+
: "unknown"}) ${lastGhost.type} failed to parse: ${lastGhost.error ?? "unknown error"}`,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (parseFault && !this._fault) {
|
|
290
|
+
this._fault = parseFault;
|
|
291
|
+
}
|
|
228
292
|
return {
|
|
229
293
|
dnetHeader,
|
|
230
294
|
rateInfo,
|
|
@@ -232,6 +296,7 @@ export class PacketParser {
|
|
|
232
296
|
events,
|
|
233
297
|
ghosts,
|
|
234
298
|
ghostSectionStart,
|
|
299
|
+
...(parseFault ? { parseFault } : {}),
|
|
235
300
|
};
|
|
236
301
|
}
|
|
237
302
|
/**
|
|
@@ -336,49 +401,35 @@ export class PacketParser {
|
|
|
336
401
|
if (bs.readFlag()) {
|
|
337
402
|
if (bs.readFlag()) {
|
|
338
403
|
// Control object is dirty — full update via readPacketData.
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
//
|
|
345
|
-
// The candidate order must be a pure function of seeded state
|
|
346
|
-
// (the tracker) so that a parser seeded mid-stream makes the same
|
|
347
|
-
// choice as one that has followed the stream from the start —
|
|
348
|
-
// no history-derived caches here.
|
|
404
|
+
// GameConnection::readPacket (FUN_005fb9f0) resolves the ghost
|
|
405
|
+
// index against the local ghost table and calls the object's
|
|
406
|
+
// virtual readPacketData (vtable+0x108) with no fallback. An
|
|
407
|
+
// untracked index is a null dereference in the engine, and a
|
|
408
|
+
// non-GameBase object has no readPacketData slot, so both are
|
|
409
|
+
// unrecoverable faults here — never a guess.
|
|
349
410
|
const gIndex = bs.readInt(10);
|
|
350
411
|
controlObjectGhostIndex = gIndex;
|
|
351
412
|
controlObjectDataStart = bs.getCurPos();
|
|
352
|
-
const start = bs.savePos();
|
|
353
413
|
const ghost = this.ghostTracker.getGhost(gIndex);
|
|
354
|
-
const
|
|
414
|
+
const entry = ghost
|
|
355
415
|
? this.registry.getGhostParser(ghost.classId)
|
|
356
416
|
: undefined;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
candidates.push(entry);
|
|
369
|
-
};
|
|
370
|
-
addCandidate(preferredEntry);
|
|
371
|
-
addCandidate(playerEntry);
|
|
372
|
-
addCandidate(cameraEntry);
|
|
373
|
-
let parsed = false;
|
|
374
|
-
for (const entry of candidates) {
|
|
375
|
-
bs.restorePos(start);
|
|
417
|
+
let controlObjectError;
|
|
418
|
+
if (!ghost) {
|
|
419
|
+
controlObjectError = `control object ghost ${gIndex} is not tracked`;
|
|
420
|
+
}
|
|
421
|
+
else if (!entry) {
|
|
422
|
+
controlObjectError = `no ghost class bound to classId ${ghost.classId}`;
|
|
423
|
+
}
|
|
424
|
+
else if (!entry.readPacketData) {
|
|
425
|
+
controlObjectError = `${entry.name} is not a GameBase and has no readPacketData`;
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
376
428
|
try {
|
|
377
429
|
const conn = this.getConnectionContext();
|
|
378
430
|
const data = entry.readPacketData(bs, conn);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
continue;
|
|
431
|
+
if (bs.isError()) {
|
|
432
|
+
throw new Error("ran past the end of the packet");
|
|
382
433
|
}
|
|
383
434
|
controlObjectData = data;
|
|
384
435
|
controlObjectDataEnd = bs.getCurPos();
|
|
@@ -387,16 +438,12 @@ export class PacketParser {
|
|
|
387
438
|
compressionPoint = this.compressionPoint;
|
|
388
439
|
}
|
|
389
440
|
this.controlObjectParsed++;
|
|
390
|
-
parsed = true;
|
|
391
|
-
break;
|
|
392
441
|
}
|
|
393
|
-
catch {
|
|
394
|
-
|
|
442
|
+
catch (e) {
|
|
443
|
+
controlObjectError = `${entry.name}.readPacketData: ${errorMessage(e)}`;
|
|
395
444
|
}
|
|
396
445
|
}
|
|
397
|
-
if (
|
|
398
|
-
bs.restorePos(start);
|
|
399
|
-
// No parser — bail from game state
|
|
446
|
+
if (controlObjectError !== undefined) {
|
|
400
447
|
controlObjectDataEnd = controlObjectDataStart;
|
|
401
448
|
this.controlObjectFailed++;
|
|
402
449
|
return {
|
|
@@ -416,6 +463,7 @@ export class PacketParser {
|
|
|
416
463
|
controlObjectDataStart,
|
|
417
464
|
controlObjectDataEnd,
|
|
418
465
|
controlObjectData,
|
|
466
|
+
controlObjectError,
|
|
419
467
|
targetVisibility: [],
|
|
420
468
|
};
|
|
421
469
|
}
|
|
@@ -492,9 +540,6 @@ export class PacketParser {
|
|
|
492
540
|
this.dispatchGuaranteedEvents(dispatchedEvents);
|
|
493
541
|
break;
|
|
494
542
|
}
|
|
495
|
-
else if (!bit) {
|
|
496
|
-
break;
|
|
497
|
-
}
|
|
498
543
|
let sequenceNumber;
|
|
499
544
|
let absoluteSequenceNumber;
|
|
500
545
|
if (!unguaranteedPhase) {
|
|
@@ -519,10 +564,15 @@ export class PacketParser {
|
|
|
519
564
|
try {
|
|
520
565
|
const conn = this.getConnectionContext();
|
|
521
566
|
parsedData = parserEntry.unpack(bs, conn);
|
|
567
|
+
if (bs.isError()) {
|
|
568
|
+
throw new Error("ran past the end of the packet");
|
|
569
|
+
}
|
|
522
570
|
this.eventsParsed++;
|
|
523
571
|
}
|
|
524
|
-
catch {
|
|
572
|
+
catch (e) {
|
|
525
573
|
this.eventsFailed++;
|
|
574
|
+
const error = `${parserEntry.name}: ${errorMessage(e)}`;
|
|
575
|
+
debugEvents("FAIL pkt=%d classId=%d parser=%s bit=%d/%d err=%s", this.packetsParsed, classId, parserEntry.name, dataBitsStart, bs.getMaxPos(), error);
|
|
526
576
|
dispatchedEvents.push({
|
|
527
577
|
classId,
|
|
528
578
|
guaranteed: !unguaranteedPhase,
|
|
@@ -531,6 +581,7 @@ export class PacketParser {
|
|
|
531
581
|
dataBitsStart,
|
|
532
582
|
dataBitsEnd: dataBitsStart,
|
|
533
583
|
failed: true,
|
|
584
|
+
error,
|
|
534
585
|
});
|
|
535
586
|
return dispatchedEvents;
|
|
536
587
|
}
|
|
@@ -545,6 +596,7 @@ export class PacketParser {
|
|
|
545
596
|
dataBitsStart,
|
|
546
597
|
dataBitsEnd: dataBitsStart,
|
|
547
598
|
failed: true,
|
|
599
|
+
error: `no parser bound for event classId ${classId}`,
|
|
548
600
|
});
|
|
549
601
|
return dispatchedEvents;
|
|
550
602
|
}
|
|
@@ -696,15 +748,20 @@ export class PacketParser {
|
|
|
696
748
|
classId,
|
|
697
749
|
updateBitsStart,
|
|
698
750
|
updateBitsEnd: updateBitsStart,
|
|
751
|
+
failed: true,
|
|
752
|
+
error: `no ghost parser bound for classId ${classId} (tracker divergence)`,
|
|
699
753
|
});
|
|
700
754
|
return ghosts;
|
|
701
755
|
}
|
|
702
756
|
let parsed = false;
|
|
757
|
+
let error;
|
|
703
758
|
if (parserEntry) {
|
|
704
759
|
try {
|
|
705
760
|
const conn = this.getConnectionContext();
|
|
706
|
-
conn.currentGhostIndex = index;
|
|
707
761
|
const parsedData = parserEntry.unpackUpdate(bs, isNew, conn);
|
|
762
|
+
if (bs.isError()) {
|
|
763
|
+
throw new Error("ran past the end of the packet");
|
|
764
|
+
}
|
|
708
765
|
const endPos = bs.getCurPos();
|
|
709
766
|
if (isNew && classId !== undefined) {
|
|
710
767
|
this.ghostTracker.createGhost(index, classId, parserEntry.name);
|
|
@@ -726,7 +783,8 @@ export class PacketParser {
|
|
|
726
783
|
catch (e) {
|
|
727
784
|
this.ghostsFailed++;
|
|
728
785
|
const op = isNew ? "create" : "update";
|
|
729
|
-
const message =
|
|
786
|
+
const message = errorMessage(e);
|
|
787
|
+
error = `${parserEntry.name}: ${message}`;
|
|
730
788
|
debugGhosts("FAIL pkt=%d seq=%d #%d idx=%d op=%s classId=%d parser=%s bit=%d/%d trackerSize=%d err=%s", this.packetsParsed, seqNumber, ghosts.length, index, op, classId, parserEntry.name, updateBitsStart, bs.getMaxPos(), this.ghostTracker.size(), message);
|
|
731
789
|
}
|
|
732
790
|
}
|
|
@@ -740,6 +798,11 @@ export class PacketParser {
|
|
|
740
798
|
classId,
|
|
741
799
|
updateBitsStart,
|
|
742
800
|
updateBitsEnd: updateBitsStart,
|
|
801
|
+
failed: true,
|
|
802
|
+
error: error ??
|
|
803
|
+
(parserEntry
|
|
804
|
+
? `${parserEntry.name}: unknown error`
|
|
805
|
+
: `no ghost parser bound for classId ${classId}`),
|
|
743
806
|
});
|
|
744
807
|
return ghosts;
|
|
745
808
|
}
|
package/dist/PacketParser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PacketParser.js","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"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","sourcesContent":["import createDebug from \"debug\";\nimport { BitStream } from \"./BitStream.js\";\nimport {\n DataPacket,\n MaxGhostCount,\n GhostMsgEndGhosting,\n NetEventClassBitSize,\n NetEventClassFirst,\n NetObjectClassBitSize,\n NetObjectClassFirst,\n} from \"./types.js\";\n\nconst debugGhosts = createDebug(\"t2-demo-parser:ghosts\");\nimport type {\n ConnectionProtocolState,\n DnetHeader,\n RateInfo,\n GameState,\n PacketData,\n NetEventInfo,\n GhostUpdate,\n} from \"./types.js\";\nimport type {\n ClassRegistry,\n ConnectionContext,\n GhostParserEntry,\n ParsedData,\n} from \"./ClassRegistry.js\";\nimport type { EventData, SimDataBlockEventData } from \"./eventDataTypes.js\";\nimport type { GhostTracker } from \"./GhostManager.js\";\n\n/**\n * Parses individual network packets from demo recording blocks.\n *\n * Packet layout (from the server connection perspective):\n * 1. dnet header (processRawPacket)\n * 2. Rate info (handlePacket)\n * 3. GameConnection::readPacket — game state, moves, etc.\n * 4. NetConnection::readPacket — events, then ghosts\n */\nexport class PacketParser {\n private registry: ClassRegistry;\n private ghostTracker: GhostTracker;\n private compressionPoint = { x: 0, y: 0, z: 0 };\n private dataBlockDataMap?: Map<number, ParsedData>;\n private lastSeqRecvdAtSend = new Array<number>(32).fill(0);\n private lastSeqRecvd = 0;\n private highestAckedSeq = 0;\n private lastSendSeq = 0;\n private recvAckMask = 0;\n private connectSequence = 0;\n private lastRecvAckAck = 0;\n private _connectionEstablished = false;\n private nextRecvEventSeq = 0;\n private pendingGuaranteedEvents: Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }> = [];\n\n // Stats\n controlObjectParsed = 0;\n controlObjectFailed = 0;\n eventsParsed = 0;\n eventsFailed = 0;\n ghostCreatesParsed = 0;\n ghostUpdatesParsed = 0;\n ghostDeletes = 0;\n ghostsFailed = 0;\n /** Ghosts where our tracker says \"new\" but the classId is unregistered.\n * This indicates a tracker divergence: the server sent UPDATE data\n * (no classId prefix) for a ghost we don't have, so we misread the\n * first 7 bits of update data as a classId. */\n ghostsTrackerDiverged = 0;\n packetsParsed = 0;\n protocolRejected = 0;\n protocolNoDispatch = 0;\n\n constructor(\n registry: ClassRegistry,\n ghostTracker: GhostTracker,\n options?: {\n dataBlockDataMap?: Map<number, ParsedData>;\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 this.registry = registry;\n this.ghostTracker = ghostTracker;\n this.dataBlockDataMap = options?.dataBlockDataMap;\n if (options?.connectionProtocolState) {\n this.setConnectionProtocolState(options.connectionProtocolState);\n }\n if (typeof options?.nextRecvEventSeq === \"number\") {\n this.nextRecvEventSeq = options.nextRecvEventSeq >>> 0;\n }\n if (options?.compressionPoint) {\n this.compressionPoint = { ...options.compressionPoint };\n }\n if (options?.pendingGuaranteedEvents) {\n this.pendingGuaranteedEvents = options.pendingGuaranteedEvents\n .map((entry) => ({ ...entry }))\n .sort((a, b) => a.absoluteSequenceNumber - b.absoluteSequenceNumber);\n }\n }\n\n getCompressionPoint(): { x: number; y: number; z: number } {\n return this.compressionPoint;\n }\n\n getDataBlockDataMap(): Map<number, ParsedData> | undefined {\n return this.dataBlockDataMap;\n }\n\n private getConnectionContext(): ConnectionContext {\n const dbMap = this.dataBlockDataMap;\n return {\n compressionPoint: this.compressionPoint,\n ghostTracker: this.ghostTracker,\n getDataBlockParser: (classId: number) =>\n this.registry.getDataBlockParser(classId),\n getDataBlockData: dbMap\n ? (objectId: number) => dbMap.get(objectId)\n : undefined,\n getGhostParser: (classId: number) =>\n this.registry.getGhostParser(classId),\n };\n }\n\n private _setNextRecvEventSeq(nextRecvEventSeq: number): void {\n this.nextRecvEventSeq = nextRecvEventSeq >>> 0;\n }\n\n setConnectionProtocolState(state: ConnectionProtocolState): void {\n this.lastSeqRecvdAtSend = state.lastSeqRecvdAtSend.slice(0, 32);\n while (this.lastSeqRecvdAtSend.length < 32) {\n this.lastSeqRecvdAtSend.push(0);\n }\n this.lastSeqRecvd = state.lastSeqRecvd >>> 0;\n this.highestAckedSeq = state.highestAckedSeq >>> 0;\n this.lastSendSeq = state.lastSendSeq >>> 0;\n this.recvAckMask = state.ackMask >>> 0;\n this.connectSequence = state.connectSequence >>> 0;\n this.lastRecvAckAck = state.lastRecvAckAck >>> 0;\n this._connectionEstablished = state.connectionEstablished;\n }\n\n /**\n * Export the current protocol window state. Together with\n * `getNextRecvEventSeq`, `getPendingGuaranteedEvents`,\n * `getCompressionPoint`, `getDataBlockDataMap`, and the ghost tracker\n * contents, this captures all cross-packet parser state, so an\n * identically seeded parser continues the stream in lockstep.\n */\n getConnectionProtocolState(): ConnectionProtocolState {\n return {\n lastSeqRecvdAtSend: this.lastSeqRecvdAtSend.slice(),\n lastSeqRecvd: this.lastSeqRecvd,\n highestAckedSeq: this.highestAckedSeq,\n lastSendSeq: this.lastSendSeq,\n ackMask: this.recvAckMask,\n connectSequence: this.connectSequence,\n lastRecvAckAck: this.lastRecvAckAck,\n connectionEstablished: this._connectionEstablished,\n };\n }\n\n getNextRecvEventSeq(): number {\n return this.nextRecvEventSeq;\n }\n\n getPendingGuaranteedEvents(): Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }> {\n return this.pendingGuaranteedEvents.map((entry) => ({ ...entry }));\n }\n\n /**\n * Emulate ConnectionProtocol::buildSendPacketHeader (FUN_0043d2d0, data path).\n * Demo block type 1 indicates a local send-packet trigger.\n */\n onSendPacketTrigger(): void {\n this.lastSendSeq = (this.lastSendSeq + 1) >>> 0;\n this.lastSeqRecvdAtSend[this.lastSendSeq & 0x1f] = this.lastSeqRecvd >>> 0;\n }\n\n /**\n * Emulates ConnectionProtocol::processRawPacket (FUN_0043d4d0).\n * A packet may be syntactically valid but still ignored for game payload\n * dispatch due to sequence/connect-window checks or duplicate seq numbers.\n */\n private applyProtocolHeader(dnetHeader: DnetHeader): {\n accepted: boolean;\n dispatchData: boolean;\n } {\n if (dnetHeader.connectSeqBit !== (this.connectSequence & 1)) {\n return { accepted: false, dispatchData: false };\n }\n if (dnetHeader.ackByteCount > 4 || dnetHeader.packetType > 2) {\n return { accepted: false, dispatchData: false };\n }\n\n let seqNumber =\n (dnetHeader.seqNumber | (this.lastSeqRecvd & 0xffff_fe00)) >>> 0;\n if (seqNumber < this.lastSeqRecvd) {\n seqNumber = (seqNumber + 0x200) >>> 0;\n }\n if (this.lastSeqRecvd + 0x1f < seqNumber) {\n return { accepted: false, dispatchData: false };\n }\n\n let highestAck =\n (dnetHeader.highestAck | (this.highestAckedSeq & 0xffff_fe00)) >>> 0;\n if (highestAck < this.highestAckedSeq) {\n highestAck = (highestAck + 0x200) >>> 0;\n }\n if (this.lastSendSeq < highestAck) {\n return { accepted: false, dispatchData: false };\n }\n\n const seqShift = (seqNumber - this.lastSeqRecvd) & 0x1f;\n this.recvAckMask = (this.recvAckMask << seqShift) >>> 0;\n if (dnetHeader.packetType === DataPacket) {\n this.recvAckMask = (this.recvAckMask | 1) >>> 0;\n }\n\n for (\n let ackSeq = this.highestAckedSeq + 1;\n ackSeq <= highestAck;\n ackSeq++\n ) {\n const isAcked =\n (dnetHeader.ackMask & (1 << ((highestAck - ackSeq) & 0x1f))) !== 0;\n if (isAcked) {\n this.lastRecvAckAck = this.lastSeqRecvdAtSend[ackSeq & 0x1f] >>> 0;\n }\n }\n if (seqNumber - this.lastRecvAckAck > 0x20) {\n this.lastRecvAckAck = seqNumber - 0x20;\n }\n this.highestAckedSeq = highestAck;\n\n const dispatchData =\n this.lastSeqRecvd !== seqNumber && dnetHeader.packetType === DataPacket;\n this.lastSeqRecvd = seqNumber;\n\n return { accepted: true, dispatchData };\n }\n\n parsePacket(data: Uint8Array): PacketData {\n const bs = new BitStream(data);\n\n // 1. Parse dnet header\n const dnetHeader = this.readDnetHeader(bs);\n const protocol = this.applyProtocolHeader(dnetHeader);\n\n this.packetsParsed++;\n\n // ConnectionProtocol may reject this packet entirely (window/connect checks),\n // or accept it but suppress game dispatch (duplicate seq / non-data packet).\n if (!protocol.accepted) {\n this.protocolRejected++;\n return {\n dnetHeader,\n rateInfo: {},\n gameState: this.emptyGameState(),\n events: [],\n ghosts: [],\n };\n }\n if (!protocol.dispatchData) {\n this.protocolNoDispatch++;\n return {\n dnetHeader,\n rateInfo: {},\n gameState: this.emptyGameState(),\n events: [],\n ghosts: [],\n };\n }\n\n // 2. Rate info (NetConnection::handlePacket)\n const rateInfo = this.readRateInfo(bs);\n\n // 3. Game state (GameConnection::readPacket — server connection path)\n bs.setStringBuffer(true);\n const gameState = this.readGameState(bs);\n\n // Only read events/ghosts if game state completed successfully.\n // When game state bails (control object dirty with no parser), the\n // stream position is wrong and we'd read garbage data.\n const gameStateComplete =\n gameState.controlObjectDataStart === undefined ||\n gameState.controlObjectData !== undefined;\n\n // 4. Events (NetConnection::readPacket -> eventReadPacket)\n const events = gameStateComplete ? this.readEvents(bs) : [];\n\n // Only read ghosts if all events were successfully parsed.\n // When an event can't be parsed, readEvents returns early and the\n // stream position is wrong — reading ghosts would produce garbage.\n const lastEvent = events[events.length - 1];\n const eventsComplete = !lastEvent?.failed;\n\n // 5. Ghosts (NetConnection::readPacket -> ghostReadPacket)\n const ghostSectionStart =\n gameStateComplete && eventsComplete ? bs.getCurPos() : undefined;\n const ghosts =\n gameStateComplete && eventsComplete\n ? this.readGhosts(bs, dnetHeader.seqNumber)\n : [];\n\n bs.setStringBuffer(false);\n\n return {\n dnetHeader,\n rateInfo,\n gameState,\n events,\n ghosts,\n ghostSectionStart,\n };\n }\n\n /**\n * Parse the dnet packet header (from processRawPacket in dnet.cc).\n */\n private readDnetHeader(bs: BitStream): DnetHeader {\n const gameFlag = bs.readFlag();\n const connectSeqBit = bs.readInt(1);\n const seqNumber = bs.readInt(9);\n const highestAck = bs.readInt(9);\n const packetType = bs.readInt(2);\n const ackByteCount = bs.readInt(3);\n const ackMask = ackByteCount > 0 ? bs.readInt(8 * ackByteCount) : 0;\n\n return {\n gameFlag,\n connectSeqBit,\n seqNumber,\n highestAck,\n packetType,\n ackByteCount,\n ackMask,\n };\n }\n\n /**\n * Parse rate info from handlePacket in netConnection.cc.\n */\n private readRateInfo(bs: BitStream): RateInfo {\n const info: RateInfo = {};\n if (bs.readFlag()) {\n info.updateDelay = bs.readInt(10);\n info.packetSize = bs.readInt(10);\n }\n if (bs.readFlag()) {\n info.maxUpdateDelay = bs.readInt(10);\n info.maxPacketSize = bs.readInt(10);\n }\n return info;\n }\n\n /**\n * Parse game state from GameConnection::readPacket (server connection path).\n */\n private readGameState(bs: BitStream): GameState {\n const lastMoveAck = bs.readInt(32);\n\n // Damage flash / whiteout\n let damageFlash: number | undefined;\n let whiteOut: number | undefined;\n if (bs.readFlag()) {\n if (bs.readFlag()) {\n damageFlash = bs.readFloat(7);\n }\n if (bs.readFlag()) {\n whiteOut = bs.readFloat(7) * 1.5;\n }\n }\n\n // Lock/homing state\n let selfLocked: boolean | undefined;\n let selfHomed: boolean | undefined;\n if (bs.readFlag()) {\n selfLocked = bs.readFlag();\n selfHomed = bs.readFlag();\n }\n\n // Seeker tracking state\n let seekerTracking: boolean | undefined;\n let seekerTrackingPos: { x: number; y: number; z: number } | undefined;\n let seekerMode: number | undefined;\n let seekerObjectGhostIndex: number | undefined;\n let targetPos: { x: number; y: number; z: number } | undefined;\n if (bs.readFlag()) {\n seekerTracking = bs.readFlag();\n // Binary 0x005fc020: when seekerTracking is true, reads 3×F32 (Point3F)\n // for the seeker target position (stored at connection+0x8454)\n if (seekerTracking) {\n seekerTrackingPos = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n }\n seekerMode = bs.readRangedU32(0, 2);\n if (seekerMode === 1) {\n if (bs.readFlag()) {\n seekerObjectGhostIndex = bs.readRangedU32(0, MaxGhostCount - 1);\n }\n } else if (seekerMode === 2) {\n targetPos = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n }\n }\n\n // Sensor ping/jam flags\n const pinged = bs.readFlag();\n const jammed = bs.readFlag();\n\n // Control object state\n let controlObjectGhostIndex: number | undefined;\n let controlObjectDataStart: number | undefined;\n let controlObjectDataEnd: number | undefined;\n let controlObjectData: ParsedData | undefined;\n let compressionPoint: { x: number; y: number; z: number } | undefined;\n\n if (bs.readFlag()) {\n if (bs.readFlag()) {\n // Control object is dirty — full update via readPacketData.\n // In Tribes 2 (build 25034), only Player and Camera override\n // writePacketData/readPacketData, so the control object is\n // always one of these two classes. We try candidates in order:\n // 1. Tracker classId (may be stale due to ghost index recycling)\n // 2. Player (classId 25) — the normal control object\n // 3. Camera (classId 4) — spectator mode\n // The candidate order must be a pure function of seeded state\n // (the tracker) so that a parser seeded mid-stream makes the same\n // choice as one that has followed the stream from the start —\n // no history-derived caches here.\n const gIndex = bs.readInt(10);\n controlObjectGhostIndex = gIndex;\n controlObjectDataStart = bs.getCurPos();\n const start = bs.savePos();\n const ghost = this.ghostTracker.getGhost(gIndex);\n\n const preferredEntry = ghost\n ? this.registry.getGhostParser(ghost.classId)\n : undefined;\n const playerEntry = this.registry.getGhostParser(25); // Player\n const cameraEntry = this.registry.getGhostParser(4); // Camera\n\n // Build candidate list (deduplicated, only those with readPacketData)\n const candidates: GhostParserEntry[] = [];\n const seen = new Set<string>();\n const addCandidate = (entry: GhostParserEntry | undefined): void => {\n if (!entry?.readPacketData) return;\n if (seen.has(entry.name)) return;\n seen.add(entry.name);\n candidates.push(entry);\n };\n addCandidate(preferredEntry);\n addCandidate(playerEntry);\n addCandidate(cameraEntry);\n\n let parsed = false;\n for (const entry of candidates) {\n bs.restorePos(start);\n try {\n const conn = this.getConnectionContext();\n const data = entry.readPacketData!(bs, conn);\n const bitsConsumed = bs.getCurPos() - controlObjectDataStart!;\n if (bitsConsumed <= 0 || bs.isError()) {\n continue;\n }\n\n controlObjectData = data;\n controlObjectDataEnd = bs.getCurPos();\n if (conn.compressionPoint !== this.compressionPoint) {\n this.compressionPoint = conn.compressionPoint;\n compressionPoint = this.compressionPoint;\n }\n this.controlObjectParsed++;\n parsed = true;\n break;\n } catch {\n // Try next candidate.\n }\n }\n\n if (!parsed) {\n bs.restorePos(start);\n // No parser — bail from game state\n controlObjectDataEnd = controlObjectDataStart;\n this.controlObjectFailed++;\n return {\n lastMoveAck,\n damageFlash,\n whiteOut,\n selfLocked,\n selfHomed,\n seekerTracking,\n seekerTrackingPos,\n seekerMode,\n seekerObjectGhostIndex,\n targetPos,\n pinged,\n jammed,\n controlObjectGhostIndex,\n controlObjectDataStart,\n controlObjectDataEnd,\n controlObjectData,\n targetVisibility: [],\n };\n }\n } else {\n // Compression point update — always accept (engine doesn't validate)\n compressionPoint = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n this.compressionPoint = compressionPoint;\n }\n }\n\n // Target visibility masks\n const targetVisibility: { index: number; mask: number }[] = [];\n while (bs.readFlag()) {\n targetVisibility.push({\n index: bs.readInt(4),\n mask: bs.readInt(32),\n });\n }\n\n // Camera FOV\n let cameraFov: number | undefined;\n if (bs.readFlag()) {\n cameraFov = bs.readInt(8);\n }\n\n return {\n lastMoveAck,\n damageFlash,\n whiteOut,\n selfLocked,\n selfHomed,\n seekerTracking,\n seekerTrackingPos,\n seekerMode,\n seekerObjectGhostIndex,\n targetPos,\n pinged,\n jammed,\n controlObjectGhostIndex,\n controlObjectDataStart,\n controlObjectDataEnd,\n controlObjectData,\n compressionPoint,\n targetVisibility:\n targetVisibility.length > 0 ? targetVisibility : undefined,\n cameraFov,\n };\n }\n\n /**\n * Parse events from eventReadPacket in netEvent.cc.\n *\n * Two phases:\n * 1. Unguaranteed events: while(readFlag) { classId(6b) + unpack }\n * 2. Guaranteed events: while(readFlag) { seqFlag(1b), [seq(7b)], classId(6b) + unpack }\n */\n private readEvents(bs: BitStream): NetEventInfo[] {\n const dispatchedEvents: NetEventInfo[] = [];\n let unguaranteedPhase = true;\n let prevGuaranteedSeq = -2;\n\n while (true) {\n const bit = bs.readFlag();\n if (unguaranteedPhase && !bit) {\n // Transition to guaranteed phase. Binary immediately reads one more\n // continuation bit for that phase.\n unguaranteedPhase = false;\n const guaranteedBit = bs.readFlag();\n if (!guaranteedBit) {\n this.dispatchGuaranteedEvents(dispatchedEvents);\n break;\n }\n } else if (!unguaranteedPhase && !bit) {\n this.dispatchGuaranteedEvents(dispatchedEvents);\n break;\n } else if (!bit) {\n break;\n }\n\n let sequenceNumber: number | undefined;\n let absoluteSequenceNumber: number | undefined;\n if (!unguaranteedPhase) {\n if (bs.readFlag()) {\n sequenceNumber = (prevGuaranteedSeq + 1) & 0x7f;\n } else {\n sequenceNumber = bs.readInt(7);\n }\n prevGuaranteedSeq = sequenceNumber;\n absoluteSequenceNumber =\n sequenceNumber | (this.nextRecvEventSeq & 0xffffff80);\n if (absoluteSequenceNumber < this.nextRecvEventSeq) {\n absoluteSequenceNumber += 0x80;\n }\n }\n\n const classId = bs.readInt(NetEventClassBitSize) + NetEventClassFirst;\n const dataBitsStart = bs.getCurPos();\n\n const parserEntry = this.registry.getEventParser(classId);\n let parsedData: ParsedData | undefined;\n\n if (parserEntry) {\n try {\n const conn = this.getConnectionContext();\n parsedData = parserEntry.unpack(bs, conn);\n this.eventsParsed++;\n } catch {\n this.eventsFailed++;\n dispatchedEvents.push({\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n return dispatchedEvents;\n }\n } else {\n // No parser — cannot advance safely.\n dispatchedEvents.push({\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n return dispatchedEvents;\n }\n\n const event: NetEventInfo = {\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: bs.getCurPos(),\n parsedData,\n };\n\n if (unguaranteedPhase) {\n dispatchedEvents.push(event);\n if (parsedData) {\n this.applyEventSideEffects(parsedData);\n }\n } else if (absoluteSequenceNumber !== undefined) {\n this.enqueueGuaranteedEvent(absoluteSequenceNumber, event);\n }\n }\n\n return dispatchedEvents;\n }\n\n private enqueueGuaranteedEvent(\n absoluteSequenceNumber: number,\n event: NetEventInfo,\n ): void {\n let insertAt = 0;\n while (\n insertAt < this.pendingGuaranteedEvents.length &&\n this.pendingGuaranteedEvents[insertAt].absoluteSequenceNumber <\n absoluteSequenceNumber\n ) {\n insertAt++;\n }\n this.pendingGuaranteedEvents.splice(insertAt, 0, {\n absoluteSequenceNumber,\n event,\n });\n }\n\n private dispatchGuaranteedEvents(dispatchedEvents: NetEventInfo[]): void {\n while (\n this.pendingGuaranteedEvents.length > 0 &&\n this.pendingGuaranteedEvents[0].absoluteSequenceNumber ===\n this.nextRecvEventSeq\n ) {\n const queued = this.pendingGuaranteedEvents.shift();\n if (!queued) break;\n this.nextRecvEventSeq = (this.nextRecvEventSeq + 1) >>> 0;\n dispatchedEvents.push(queued.event);\n if (queued.event.parsedData) {\n this.applyEventSideEffects(queued.event.parsedData);\n }\n }\n }\n\n /**\n * Apply event side effects that alter ghost index state.\n * These effects occur before ghostReadPacket on the same packet.\n */\n private applyEventSideEffects(parsedData: ParsedData): void {\n const eventType = parsedData.type;\n\n if (eventType === \"GhostingMessageEvent\") {\n const message = parsedData.message;\n // Tribes 2 handleGhostMessage EndGhosting (netGhost.cc:706) deletes\n // ONLY local ghosts. Datablocks are connection-lifetime state and\n // must be retained: the server's transmitDataBlocks skips datablocks\n // already sent on this connection (gameConnection.cc\n // cTransmitDataBlocks: only modifiedKey > mDataBlockModifiedKey is\n // re-sent), so on a mission change most datablocks are NOT re-sent\n // and clearing the map here leaves the new mission's ghosts\n // unresolvable.\n if (typeof message === \"number\" && message === GhostMsgEndGhosting) {\n this.ghostTracker.clear();\n }\n return;\n }\n\n if (eventType === \"GhostAlwaysObjectEvent\") {\n const ghostIndex = parsedData.ghostIndex;\n const classId = parsedData.classId;\n if (typeof ghostIndex === \"number\" && typeof classId === \"number\") {\n const parserEntry = this.registry.getGhostParser(classId);\n this.ghostTracker.createGhost(\n ghostIndex,\n classId,\n parserEntry?.name ?? `unknown_${classId}`,\n );\n }\n }\n\n // SimDataBlockEvent: accumulate parsed DataBlock data by objectId\n // (exported for seeding and consumed by downstream renderers).\n if (eventType === \"SimDataBlockEvent\" && this.dataBlockDataMap) {\n const dbEvent = parsedData as SimDataBlockEventData;\n if (dbEvent.dataBlockData && typeof dbEvent.objectId === \"number\") {\n this.dataBlockDataMap.set(dbEvent.objectId, dbEvent.dataBlockData);\n }\n }\n }\n\n /**\n * Parse ghosts from ghostReadPacket in netGhost.cc.\n */\n private readGhosts(bs: BitStream, seqNumber: number): GhostUpdate[] {\n const ghosts: GhostUpdate[] = [];\n\n if (!bs.readFlag()) {\n return ghosts;\n }\n\n const idSize = bs.readInt(3) + 3;\n\n while (bs.readFlag()) {\n // If the stream ran out of data during the moreFlag read, the\n // readFlag returned false (terminating the loop) with error set.\n // Check here for the case where readFlag returned true but the\n // subsequent header reads exhaust the stream.\n if (bs.isError()) break;\n\n const index = bs.readInt(idSize);\n\n // If the stream ran out of data during header reads, stop processing.\n // Without this check, exhausted reads return 0 (defaulting index to 0,\n // classId to 0) and the ghost parser runs on empty data, producing\n // a \"successful\" parse that consumed 0 bits.\n if (bs.isError()) break;\n\n if (bs.readFlag()) {\n // Ghost is being deleted\n this.ghostTracker.deleteGhost(index);\n this.ghostDeletes++;\n ghosts.push({\n index,\n type: \"delete\",\n updateBitsStart: bs.getCurPos(),\n updateBitsEnd: bs.getCurPos(),\n });\n continue;\n }\n\n const isNew = !this.ghostTracker.hasGhost(index);\n let classId: number | undefined;\n\n if (isNew) {\n classId = bs.readInt(NetObjectClassBitSize) + NetObjectClassFirst;\n } else {\n classId = this.ghostTracker.getGhost(index)?.classId;\n }\n\n const updateBitsStart = bs.getCurPos();\n const parserEntry =\n classId !== undefined\n ? this.registry.getGhostParser(classId)\n : undefined;\n\n // Detect tracker divergence: we think this is a new ghost (not in our\n // tracker) but the classId is unregistered. This almost certainly means\n // the server sent UPDATE data (no classId prefix) for a ghost our tracker\n // lost, and we misread the first 7 bits of update data as a classId.\n // This is engine-consistent — the real client would also fail here\n // because classId lookup would return NULL, triggering packet drop.\n if (isNew && !parserEntry) {\n this.ghostsTrackerDiverged++;\n debugGhosts(\n \"DIVERGED pkt=%d seq=%d idx=%d classId=%d bit=%d/%d trackerSize=%d \" +\n \"(server sent UPDATE for ghost not in our tracker; 7-bit classId is actually update data)\",\n this.packetsParsed,\n seqNumber,\n index,\n classId,\n updateBitsStart,\n bs.getMaxPos(),\n this.ghostTracker.size(),\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n });\n return ghosts;\n }\n\n let parsed = false;\n\n if (parserEntry) {\n try {\n const conn = this.getConnectionContext();\n conn.currentGhostIndex = index;\n const parsedData = parserEntry.unpackUpdate(bs, isNew, conn);\n const endPos = bs.getCurPos();\n\n if (isNew && classId !== undefined) {\n this.ghostTracker.createGhost(index, classId, parserEntry.name);\n this.ghostCreatesParsed++;\n } else {\n this.ghostUpdatesParsed++;\n }\n\n ghosts.push({\n index,\n type: isNew ? \"create\" : \"update\",\n classId,\n updateBitsStart,\n updateBitsEnd: endPos,\n parsedData,\n });\n parsed = true;\n } catch (e) {\n this.ghostsFailed++;\n const op = isNew ? \"create\" : \"update\";\n const message = e instanceof Error ? e.message : String(e);\n debugGhosts(\n \"FAIL pkt=%d seq=%d #%d idx=%d op=%s classId=%d parser=%s bit=%d/%d trackerSize=%d err=%s\",\n this.packetsParsed,\n seqNumber,\n ghosts.length,\n index,\n op,\n classId,\n parserEntry.name,\n updateBitsStart,\n bs.getMaxPos(),\n this.ghostTracker.size(),\n message,\n );\n }\n }\n\n if (parsed) continue;\n\n debugGhosts(\n \"STOP pkt=%d seq=%d idx=%d op=%s classId=%d parser=%s bit=%d/%d\",\n this.packetsParsed,\n seqNumber,\n index,\n isNew ? \"create\" : \"update\",\n classId,\n parserEntry?.name ?? \"NONE\",\n updateBitsStart,\n bs.getMaxPos(),\n );\n\n // Record and stop — can't parse this ghost's data.\n ghosts.push({\n index,\n type: isNew ? \"create\" : \"update\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n });\n return ghosts;\n }\n\n return ghosts;\n }\n\n private emptyGameState(): GameState {\n return {\n lastMoveAck: 0,\n pinged: false,\n jammed: false,\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PacketParser.js","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"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","sourcesContent":["import createDebug from \"debug\";\nimport { BitStream } from \"./BitStream.js\";\nimport {\n DataPacket,\n MaxGhostCount,\n GhostMsgEndGhosting,\n NetEventClassBitSize,\n NetEventClassFirst,\n NetObjectClassBitSize,\n NetObjectClassFirst,\n} from \"./types.js\";\nimport type {\n ConnectionProtocolState,\n DnetHeader,\n RateInfo,\n GameState,\n PacketData,\n ParseFault,\n NetEventInfo,\n GhostUpdate,\n} from \"./types.js\";\nimport type {\n ClassRegistry,\n ConnectionContext,\n ParsedData,\n} from \"./ClassRegistry.js\";\nimport type { EventData, SimDataBlockEventData } from \"./eventDataTypes.js\";\nimport type { GhostTracker } from \"./GhostManager.js\";\n\nconst debugGhosts = createDebug(\"t2-demo-parser:ghosts\");\nconst debugEvents = createDebug(\"t2-demo-parser:events\");\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/**\n * Parses individual network packets from demo recording blocks.\n *\n * Packet layout (from the server connection perspective):\n * 1. dnet header (processRawPacket)\n * 2. Rate info (handlePacket)\n * 3. GameConnection::readPacket — game state, moves, etc.\n * 4. NetConnection::readPacket — events, then ghosts\n */\nexport class PacketParser {\n private registry: ClassRegistry;\n private ghostTracker: GhostTracker;\n private compressionPoint = { x: 0, y: 0, z: 0 };\n private dataBlockDataMap?: Map<number, ParsedData>;\n private lastSeqRecvdAtSend = new Array<number>(32).fill(0);\n private lastSeqRecvd = 0;\n private highestAckedSeq = 0;\n private lastSendSeq = 0;\n private recvAckMask = 0;\n private connectSequence = 0;\n private lastRecvAckAck = 0;\n private _connectionEstablished = false;\n private nextRecvEventSeq = 0;\n private pendingGuaranteedEvents: Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }> = [];\n private readonly haltOnFault: boolean;\n private _fault?: ParseFault;\n\n // Stats\n controlObjectParsed = 0;\n controlObjectFailed = 0;\n eventsParsed = 0;\n eventsFailed = 0;\n ghostCreatesParsed = 0;\n ghostUpdatesParsed = 0;\n ghostDeletes = 0;\n ghostsFailed = 0;\n /** Ghosts where our tracker says \"new\" but the classId is unregistered.\n * This indicates a tracker divergence: the server sent UPDATE data\n * (no classId prefix) for a ghost we don't have, so we misread the\n * first 7 bits of update data as a classId. */\n ghostsTrackerDiverged = 0;\n packetsParsed = 0;\n protocolRejected = 0;\n protocolNoDispatch = 0;\n /** Packets received after the parser faulted and halted. */\n packetsDroppedAfterFault = 0;\n\n constructor(\n registry: ClassRegistry,\n ghostTracker: GhostTracker,\n options?: {\n dataBlockDataMap?: Map<number, ParsedData>;\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 * Stop parsing after the first packet that faults (default true).\n * The engine drops the connection on an unreadable packet, and every\n * later packet would be parsed against ghost/event state that no\n * longer mirrors the server. Set false to keep going regardless.\n */\n haltOnFault?: boolean;\n },\n ) {\n this.registry = registry;\n this.ghostTracker = ghostTracker;\n this.dataBlockDataMap = options?.dataBlockDataMap;\n this.haltOnFault = options?.haltOnFault ?? true;\n if (options?.connectionProtocolState) {\n this.setConnectionProtocolState(options.connectionProtocolState);\n }\n if (typeof options?.nextRecvEventSeq === \"number\") {\n this.nextRecvEventSeq = options.nextRecvEventSeq >>> 0;\n }\n if (options?.compressionPoint) {\n this.compressionPoint = { ...options.compressionPoint };\n }\n if (options?.pendingGuaranteedEvents) {\n this.pendingGuaranteedEvents = options.pendingGuaranteedEvents\n .map((entry) => ({ ...entry }))\n .sort((a, b) => a.absoluteSequenceNumber - b.absoluteSequenceNumber);\n }\n }\n\n getCompressionPoint(): { x: number; y: number; z: number } {\n return { ...this.compressionPoint };\n }\n\n /** Live datablock map (grows as SimDataBlockEvents arrive). */\n getDataBlockDataMap(): ReadonlyMap<number, ParsedData> | undefined {\n return this.dataBlockDataMap;\n }\n\n /**\n * The first parse fault, if any. Once set (and `haltOnFault` is on),\n * later packets are returned empty with this fault attached; build a\n * fresh parser (DemoParser.reset(), or a new createLiveParser seeded\n * from a known-good state) to continue.\n */\n get fault(): ParseFault | undefined {\n return this._fault;\n }\n\n get faulted(): boolean {\n return this._fault !== undefined;\n }\n\n private getConnectionContext(): ConnectionContext {\n const dbMap = this.dataBlockDataMap;\n return {\n compressionPoint: this.compressionPoint,\n ghostTracker: this.ghostTracker,\n getDataBlockParser: (classId: number) =>\n this.registry.getDataBlockParser(classId),\n getDataBlockData: dbMap\n ? (objectId: number) => dbMap.get(objectId)\n : undefined,\n getGhostParser: (classId: number) =>\n this.registry.getGhostParser(classId),\n };\n }\n\n private _setNextRecvEventSeq(nextRecvEventSeq: number): void {\n this.nextRecvEventSeq = nextRecvEventSeq >>> 0;\n }\n\n setConnectionProtocolState(state: ConnectionProtocolState): void {\n this.lastSeqRecvdAtSend = state.lastSeqRecvdAtSend.slice(0, 32);\n while (this.lastSeqRecvdAtSend.length < 32) {\n this.lastSeqRecvdAtSend.push(0);\n }\n this.lastSeqRecvd = state.lastSeqRecvd >>> 0;\n this.highestAckedSeq = state.highestAckedSeq >>> 0;\n this.lastSendSeq = state.lastSendSeq >>> 0;\n this.recvAckMask = state.ackMask >>> 0;\n this.connectSequence = state.connectSequence >>> 0;\n this.lastRecvAckAck = state.lastRecvAckAck >>> 0;\n this._connectionEstablished = state.connectionEstablished;\n }\n\n /**\n * Export the current protocol window state. Together with\n * `getNextRecvEventSeq`, `getPendingGuaranteedEvents`,\n * `getCompressionPoint`, `getDataBlockDataMap`, and the ghost tracker\n * contents, this captures all cross-packet parser state, so an\n * identically seeded parser continues the stream in lockstep.\n */\n getConnectionProtocolState(): ConnectionProtocolState {\n return {\n lastSeqRecvdAtSend: this.lastSeqRecvdAtSend.slice(),\n lastSeqRecvd: this.lastSeqRecvd,\n highestAckedSeq: this.highestAckedSeq,\n lastSendSeq: this.lastSendSeq,\n ackMask: this.recvAckMask,\n connectSequence: this.connectSequence,\n lastRecvAckAck: this.lastRecvAckAck,\n connectionEstablished: this._connectionEstablished,\n };\n }\n\n getNextRecvEventSeq(): number {\n return this.nextRecvEventSeq;\n }\n\n getPendingGuaranteedEvents(): Array<{\n absoluteSequenceNumber: number;\n event: NetEventInfo;\n }> {\n return this.pendingGuaranteedEvents.map((entry) => ({ ...entry }));\n }\n\n /**\n * Emulate ConnectionProtocol::buildSendPacketHeader (FUN_0043d2d0, data path).\n * Demo block type 1 indicates a local send-packet trigger.\n */\n onSendPacketTrigger(): void {\n this.lastSendSeq = (this.lastSendSeq + 1) >>> 0;\n this.lastSeqRecvdAtSend[this.lastSendSeq & 0x1f] = this.lastSeqRecvd >>> 0;\n }\n\n /**\n * Emulates ConnectionProtocol::processRawPacket (FUN_0043d4d0).\n * A packet may be syntactically valid but still ignored for game payload\n * dispatch due to sequence/connect-window checks or duplicate seq numbers.\n */\n private applyProtocolHeader(dnetHeader: DnetHeader): {\n accepted: boolean;\n dispatchData: boolean;\n } {\n if (dnetHeader.connectSeqBit !== (this.connectSequence & 1)) {\n return { accepted: false, dispatchData: false };\n }\n if (dnetHeader.ackByteCount > 4 || dnetHeader.packetType > 2) {\n return { accepted: false, dispatchData: false };\n }\n\n let seqNumber =\n (dnetHeader.seqNumber | (this.lastSeqRecvd & 0xffff_fe00)) >>> 0;\n if (seqNumber < this.lastSeqRecvd) {\n seqNumber = (seqNumber + 0x200) >>> 0;\n }\n if (this.lastSeqRecvd + 0x1f < seqNumber) {\n return { accepted: false, dispatchData: false };\n }\n\n let highestAck =\n (dnetHeader.highestAck | (this.highestAckedSeq & 0xffff_fe00)) >>> 0;\n if (highestAck < this.highestAckedSeq) {\n highestAck = (highestAck + 0x200) >>> 0;\n }\n if (this.lastSendSeq < highestAck) {\n return { accepted: false, dispatchData: false };\n }\n\n const seqShift = (seqNumber - this.lastSeqRecvd) & 0x1f;\n this.recvAckMask = (this.recvAckMask << seqShift) >>> 0;\n if (dnetHeader.packetType === DataPacket) {\n this.recvAckMask = (this.recvAckMask | 1) >>> 0;\n }\n\n for (\n let ackSeq = this.highestAckedSeq + 1;\n ackSeq <= highestAck;\n ackSeq++\n ) {\n const isAcked =\n (dnetHeader.ackMask & (1 << ((highestAck - ackSeq) & 0x1f))) !== 0;\n if (isAcked) {\n this.lastRecvAckAck = this.lastSeqRecvdAtSend[ackSeq & 0x1f] >>> 0;\n // ConnectionProtocol::readPacketHeader (FUN_0043d4d0): the first\n // acknowledged packet marks the connection established.\n this._connectionEstablished = true;\n }\n }\n if (seqNumber - this.lastRecvAckAck > 0x20) {\n this.lastRecvAckAck = seqNumber - 0x20;\n }\n this.highestAckedSeq = highestAck;\n\n const dispatchData =\n this.lastSeqRecvd !== seqNumber && dnetHeader.packetType === DataPacket;\n this.lastSeqRecvd = seqNumber;\n\n return { accepted: true, dispatchData };\n }\n\n parsePacket(data: Uint8Array): PacketData {\n const bs = new BitStream(data);\n\n // 1. Parse dnet header\n const dnetHeader = this.readDnetHeader(bs);\n\n if (this._fault && this.haltOnFault) {\n // Halted: mirror the engine, which has disconnected by now. The\n // header is still decoded for the caller's benefit, but no state\n // is touched.\n this.packetsDroppedAfterFault++;\n return {\n dnetHeader,\n rateInfo: {},\n gameState: this.emptyGameState(),\n events: [],\n ghosts: [],\n parseFault: this._fault,\n };\n }\n\n const protocol = this.applyProtocolHeader(dnetHeader);\n\n this.packetsParsed++;\n\n // ConnectionProtocol may reject this packet entirely (window/connect checks),\n // or accept it but suppress game dispatch (duplicate seq / non-data packet).\n if (!protocol.accepted) {\n this.protocolRejected++;\n return {\n dnetHeader,\n rateInfo: {},\n gameState: this.emptyGameState(),\n events: [],\n ghosts: [],\n };\n }\n if (!protocol.dispatchData) {\n this.protocolNoDispatch++;\n return {\n dnetHeader,\n rateInfo: {},\n gameState: this.emptyGameState(),\n events: [],\n ghosts: [],\n };\n }\n\n // 2. Rate info (NetConnection::handlePacket)\n const rateInfo = this.readRateInfo(bs);\n\n // 3. Game state (GameConnection::readPacket — server connection path)\n bs.setStringBuffer(true);\n const gameState = this.readGameState(bs);\n\n // Only read events/ghosts if game state completed successfully.\n // When game state bails (control object dirty with no parser), the\n // stream position is wrong and we'd read garbage data.\n const gameStateComplete =\n gameState.controlObjectDataStart === undefined ||\n gameState.controlObjectData !== undefined;\n\n // 4. Events (NetConnection::readPacket -> eventReadPacket)\n const events = gameStateComplete ? this.readEvents(bs) : [];\n\n // Only read ghosts if all events were successfully parsed.\n // When an event can't be parsed, readEvents returns early and the\n // stream position is wrong — reading ghosts would produce garbage.\n const lastEvent = events[events.length - 1];\n const eventsComplete = !lastEvent?.failed;\n\n // 5. Ghosts (NetConnection::readPacket -> ghostReadPacket)\n const ghostSectionStart =\n gameStateComplete && eventsComplete ? bs.getCurPos() : undefined;\n const ghosts =\n gameStateComplete && eventsComplete\n ? this.readGhosts(bs, dnetHeader.seqNumber)\n : [];\n const lastGhost = ghosts[ghosts.length - 1];\n\n bs.setStringBuffer(false);\n\n let parseFault: ParseFault | undefined;\n if (!gameStateComplete) {\n parseFault = {\n stage: \"gameState\",\n message: `control object ghost ${gameState.controlObjectGhostIndex} could not be read${\n gameState.controlObjectError ? `: ${gameState.controlObjectError}` : \"\"\n }`,\n };\n } else if (!eventsComplete) {\n parseFault = {\n stage: \"event\",\n message: `event class ${lastEvent.classId} (${\n this.registry.getEventParser(lastEvent.classId)?.name ?? \"unbound\"\n }) failed to parse: ${lastEvent.error ?? \"unknown error\"}`,\n };\n } else if (lastGhost?.failed) {\n parseFault = {\n stage: \"ghost\",\n message: `ghost ${lastGhost.index} (class ${lastGhost.classId}, ${\n lastGhost.classId !== undefined\n ? (this.registry.getGhostParser(lastGhost.classId)?.name ?? \"unbound\")\n : \"unknown\"\n }) ${lastGhost.type} failed to parse: ${lastGhost.error ?? \"unknown error\"}`,\n };\n }\n if (parseFault && !this._fault) {\n this._fault = parseFault;\n }\n\n return {\n dnetHeader,\n rateInfo,\n gameState,\n events,\n ghosts,\n ghostSectionStart,\n ...(parseFault ? { parseFault } : {}),\n };\n }\n\n /**\n * Parse the dnet packet header (from processRawPacket in dnet.cc).\n */\n private readDnetHeader(bs: BitStream): DnetHeader {\n const gameFlag = bs.readFlag();\n const connectSeqBit = bs.readInt(1);\n const seqNumber = bs.readInt(9);\n const highestAck = bs.readInt(9);\n const packetType = bs.readInt(2);\n const ackByteCount = bs.readInt(3);\n const ackMask = ackByteCount > 0 ? bs.readInt(8 * ackByteCount) : 0;\n\n return {\n gameFlag,\n connectSeqBit,\n seqNumber,\n highestAck,\n packetType,\n ackByteCount,\n ackMask,\n };\n }\n\n /**\n * Parse rate info from handlePacket in netConnection.cc.\n */\n private readRateInfo(bs: BitStream): RateInfo {\n const info: RateInfo = {};\n if (bs.readFlag()) {\n info.updateDelay = bs.readInt(10);\n info.packetSize = bs.readInt(10);\n }\n if (bs.readFlag()) {\n info.maxUpdateDelay = bs.readInt(10);\n info.maxPacketSize = bs.readInt(10);\n }\n return info;\n }\n\n /**\n * Parse game state from GameConnection::readPacket (server connection path).\n */\n private readGameState(bs: BitStream): GameState {\n const lastMoveAck = bs.readInt(32);\n\n // Damage flash / whiteout\n let damageFlash: number | undefined;\n let whiteOut: number | undefined;\n if (bs.readFlag()) {\n if (bs.readFlag()) {\n damageFlash = bs.readFloat(7);\n }\n if (bs.readFlag()) {\n whiteOut = bs.readFloat(7) * 1.5;\n }\n }\n\n // Lock/homing state\n let selfLocked: boolean | undefined;\n let selfHomed: boolean | undefined;\n if (bs.readFlag()) {\n selfLocked = bs.readFlag();\n selfHomed = bs.readFlag();\n }\n\n // Seeker tracking state\n let seekerTracking: boolean | undefined;\n let seekerTrackingPos: { x: number; y: number; z: number } | undefined;\n let seekerMode: number | undefined;\n let seekerObjectGhostIndex: number | undefined;\n let targetPos: { x: number; y: number; z: number } | undefined;\n if (bs.readFlag()) {\n seekerTracking = bs.readFlag();\n // Binary 0x005fc020: when seekerTracking is true, reads 3×F32 (Point3F)\n // for the seeker target position (stored at connection+0x8454)\n if (seekerTracking) {\n seekerTrackingPos = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n }\n seekerMode = bs.readRangedU32(0, 2);\n if (seekerMode === 1) {\n if (bs.readFlag()) {\n seekerObjectGhostIndex = bs.readRangedU32(0, MaxGhostCount - 1);\n }\n } else if (seekerMode === 2) {\n targetPos = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n }\n }\n\n // Sensor ping/jam flags\n const pinged = bs.readFlag();\n const jammed = bs.readFlag();\n\n // Control object state\n let controlObjectGhostIndex: number | undefined;\n let controlObjectDataStart: number | undefined;\n let controlObjectDataEnd: number | undefined;\n let controlObjectData: ParsedData | undefined;\n let compressionPoint: { x: number; y: number; z: number } | undefined;\n\n if (bs.readFlag()) {\n if (bs.readFlag()) {\n // Control object is dirty — full update via readPacketData.\n // GameConnection::readPacket (FUN_005fb9f0) resolves the ghost\n // index against the local ghost table and calls the object's\n // virtual readPacketData (vtable+0x108) with no fallback. An\n // untracked index is a null dereference in the engine, and a\n // non-GameBase object has no readPacketData slot, so both are\n // unrecoverable faults here — never a guess.\n const gIndex = bs.readInt(10);\n controlObjectGhostIndex = gIndex;\n controlObjectDataStart = bs.getCurPos();\n const ghost = this.ghostTracker.getGhost(gIndex);\n const entry = ghost\n ? this.registry.getGhostParser(ghost.classId)\n : undefined;\n\n let controlObjectError: string | undefined;\n if (!ghost) {\n controlObjectError = `control object ghost ${gIndex} is not tracked`;\n } else if (!entry) {\n controlObjectError = `no ghost class bound to classId ${ghost.classId}`;\n } else if (!entry.readPacketData) {\n controlObjectError = `${entry.name} is not a GameBase and has no readPacketData`;\n } else {\n try {\n const conn = this.getConnectionContext();\n const data = entry.readPacketData(bs, conn);\n if (bs.isError()) {\n throw new Error(\"ran past the end of the packet\");\n }\n controlObjectData = data;\n controlObjectDataEnd = bs.getCurPos();\n if (conn.compressionPoint !== this.compressionPoint) {\n this.compressionPoint = conn.compressionPoint;\n compressionPoint = this.compressionPoint;\n }\n this.controlObjectParsed++;\n } catch (e) {\n controlObjectError = `${entry.name}.readPacketData: ${errorMessage(e)}`;\n }\n }\n\n if (controlObjectError !== undefined) {\n controlObjectDataEnd = controlObjectDataStart;\n this.controlObjectFailed++;\n return {\n lastMoveAck,\n damageFlash,\n whiteOut,\n selfLocked,\n selfHomed,\n seekerTracking,\n seekerTrackingPos,\n seekerMode,\n seekerObjectGhostIndex,\n targetPos,\n pinged,\n jammed,\n controlObjectGhostIndex,\n controlObjectDataStart,\n controlObjectDataEnd,\n controlObjectData,\n controlObjectError,\n targetVisibility: [],\n };\n }\n } else {\n // Compression point update — always accept (engine doesn't validate)\n compressionPoint = {\n x: bs.readF32(),\n y: bs.readF32(),\n z: bs.readF32(),\n };\n this.compressionPoint = compressionPoint;\n }\n }\n\n // Target visibility masks\n const targetVisibility: { index: number; mask: number }[] = [];\n while (bs.readFlag()) {\n targetVisibility.push({\n index: bs.readInt(4),\n mask: bs.readInt(32),\n });\n }\n\n // Camera FOV\n let cameraFov: number | undefined;\n if (bs.readFlag()) {\n cameraFov = bs.readInt(8);\n }\n\n return {\n lastMoveAck,\n damageFlash,\n whiteOut,\n selfLocked,\n selfHomed,\n seekerTracking,\n seekerTrackingPos,\n seekerMode,\n seekerObjectGhostIndex,\n targetPos,\n pinged,\n jammed,\n controlObjectGhostIndex,\n controlObjectDataStart,\n controlObjectDataEnd,\n controlObjectData,\n compressionPoint,\n targetVisibility:\n targetVisibility.length > 0 ? targetVisibility : undefined,\n cameraFov,\n };\n }\n\n /**\n * Parse events from eventReadPacket in netEvent.cc.\n *\n * Two phases:\n * 1. Unguaranteed events: while(readFlag) { classId(6b) + unpack }\n * 2. Guaranteed events: while(readFlag) { seqFlag(1b), [seq(7b)], classId(6b) + unpack }\n */\n private readEvents(bs: BitStream): NetEventInfo[] {\n const dispatchedEvents: NetEventInfo[] = [];\n let unguaranteedPhase = true;\n let prevGuaranteedSeq = -2;\n\n while (true) {\n const bit = bs.readFlag();\n if (unguaranteedPhase && !bit) {\n // Transition to guaranteed phase. Binary immediately reads one more\n // continuation bit for that phase.\n unguaranteedPhase = false;\n const guaranteedBit = bs.readFlag();\n if (!guaranteedBit) {\n this.dispatchGuaranteedEvents(dispatchedEvents);\n break;\n }\n } else if (!unguaranteedPhase && !bit) {\n this.dispatchGuaranteedEvents(dispatchedEvents);\n break;\n }\n\n let sequenceNumber: number | undefined;\n let absoluteSequenceNumber: number | undefined;\n if (!unguaranteedPhase) {\n if (bs.readFlag()) {\n sequenceNumber = (prevGuaranteedSeq + 1) & 0x7f;\n } else {\n sequenceNumber = bs.readInt(7);\n }\n prevGuaranteedSeq = sequenceNumber;\n absoluteSequenceNumber =\n sequenceNumber | (this.nextRecvEventSeq & 0xffffff80);\n if (absoluteSequenceNumber < this.nextRecvEventSeq) {\n absoluteSequenceNumber += 0x80;\n }\n }\n\n const classId = bs.readInt(NetEventClassBitSize) + NetEventClassFirst;\n const dataBitsStart = bs.getCurPos();\n\n const parserEntry = this.registry.getEventParser(classId);\n let parsedData: ParsedData | undefined;\n\n if (parserEntry) {\n try {\n const conn = this.getConnectionContext();\n parsedData = parserEntry.unpack(bs, conn);\n if (bs.isError()) {\n throw new Error(\"ran past the end of the packet\");\n }\n this.eventsParsed++;\n } catch (e) {\n this.eventsFailed++;\n const error = `${parserEntry.name}: ${errorMessage(e)}`;\n debugEvents(\n \"FAIL pkt=%d classId=%d parser=%s bit=%d/%d err=%s\",\n this.packetsParsed,\n classId,\n parserEntry.name,\n dataBitsStart,\n bs.getMaxPos(),\n error,\n );\n dispatchedEvents.push({\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n error,\n });\n return dispatchedEvents;\n }\n } else {\n // No parser — cannot advance safely.\n dispatchedEvents.push({\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n error: `no parser bound for event classId ${classId}`,\n });\n return dispatchedEvents;\n }\n\n const event: NetEventInfo = {\n classId,\n guaranteed: !unguaranteedPhase,\n sequenceNumber,\n absoluteSequenceNumber,\n dataBitsStart,\n dataBitsEnd: bs.getCurPos(),\n parsedData,\n };\n\n if (unguaranteedPhase) {\n dispatchedEvents.push(event);\n if (parsedData) {\n this.applyEventSideEffects(parsedData);\n }\n } else if (absoluteSequenceNumber !== undefined) {\n this.enqueueGuaranteedEvent(absoluteSequenceNumber, event);\n }\n }\n\n return dispatchedEvents;\n }\n\n private enqueueGuaranteedEvent(\n absoluteSequenceNumber: number,\n event: NetEventInfo,\n ): void {\n let insertAt = 0;\n while (\n insertAt < this.pendingGuaranteedEvents.length &&\n this.pendingGuaranteedEvents[insertAt].absoluteSequenceNumber <\n absoluteSequenceNumber\n ) {\n insertAt++;\n }\n this.pendingGuaranteedEvents.splice(insertAt, 0, {\n absoluteSequenceNumber,\n event,\n });\n }\n\n private dispatchGuaranteedEvents(dispatchedEvents: NetEventInfo[]): void {\n while (\n this.pendingGuaranteedEvents.length > 0 &&\n this.pendingGuaranteedEvents[0].absoluteSequenceNumber ===\n this.nextRecvEventSeq\n ) {\n const queued = this.pendingGuaranteedEvents.shift();\n if (!queued) break;\n this.nextRecvEventSeq = (this.nextRecvEventSeq + 1) >>> 0;\n dispatchedEvents.push(queued.event);\n if (queued.event.parsedData) {\n this.applyEventSideEffects(queued.event.parsedData);\n }\n }\n }\n\n /**\n * Apply event side effects that alter ghost index state.\n * These effects occur before ghostReadPacket on the same packet.\n */\n private applyEventSideEffects(parsedData: ParsedData): void {\n const eventType = parsedData.type;\n\n if (eventType === \"GhostingMessageEvent\") {\n const message = parsedData.message;\n // Tribes 2 handleGhostMessage EndGhosting (netGhost.cc:706) deletes\n // ONLY local ghosts. Datablocks are connection-lifetime state and\n // must be retained: the server's transmitDataBlocks skips datablocks\n // already sent on this connection (gameConnection.cc\n // cTransmitDataBlocks: only modifiedKey > mDataBlockModifiedKey is\n // re-sent), so on a mission change most datablocks are NOT re-sent\n // and clearing the map here leaves the new mission's ghosts\n // unresolvable.\n if (typeof message === \"number\" && message === GhostMsgEndGhosting) {\n this.ghostTracker.clear();\n }\n return;\n }\n\n if (eventType === \"GhostAlwaysObjectEvent\") {\n const ghostIndex = parsedData.ghostIndex;\n const classId = parsedData.classId;\n if (typeof ghostIndex === \"number\" && typeof classId === \"number\") {\n const parserEntry = this.registry.getGhostParser(classId);\n this.ghostTracker.createGhost(\n ghostIndex,\n classId,\n parserEntry?.name ?? `unknown_${classId}`,\n );\n }\n }\n\n // SimDataBlockEvent: accumulate parsed DataBlock data by objectId\n // (exported for seeding and consumed by downstream renderers).\n if (eventType === \"SimDataBlockEvent\" && this.dataBlockDataMap) {\n const dbEvent = parsedData as SimDataBlockEventData;\n if (dbEvent.dataBlockData && typeof dbEvent.objectId === \"number\") {\n this.dataBlockDataMap.set(dbEvent.objectId, dbEvent.dataBlockData);\n }\n }\n }\n\n /**\n * Parse ghosts from ghostReadPacket in netGhost.cc.\n */\n private readGhosts(bs: BitStream, seqNumber: number): GhostUpdate[] {\n const ghosts: GhostUpdate[] = [];\n\n if (!bs.readFlag()) {\n return ghosts;\n }\n\n const idSize = bs.readInt(3) + 3;\n\n while (bs.readFlag()) {\n // If the stream ran out of data during the moreFlag read, the\n // readFlag returned false (terminating the loop) with error set.\n // Check here for the case where readFlag returned true but the\n // subsequent header reads exhaust the stream.\n if (bs.isError()) break;\n\n const index = bs.readInt(idSize);\n\n // If the stream ran out of data during header reads, stop processing.\n // Without this check, exhausted reads return 0 (defaulting index to 0,\n // classId to 0) and the ghost parser runs on empty data, producing\n // a \"successful\" parse that consumed 0 bits.\n if (bs.isError()) break;\n\n if (bs.readFlag()) {\n // Ghost is being deleted\n this.ghostTracker.deleteGhost(index);\n this.ghostDeletes++;\n ghosts.push({\n index,\n type: \"delete\",\n updateBitsStart: bs.getCurPos(),\n updateBitsEnd: bs.getCurPos(),\n });\n continue;\n }\n\n const isNew = !this.ghostTracker.hasGhost(index);\n let classId: number | undefined;\n\n if (isNew) {\n classId = bs.readInt(NetObjectClassBitSize) + NetObjectClassFirst;\n } else {\n classId = this.ghostTracker.getGhost(index)?.classId;\n }\n\n const updateBitsStart = bs.getCurPos();\n const parserEntry =\n classId !== undefined\n ? this.registry.getGhostParser(classId)\n : undefined;\n\n // Detect tracker divergence: we think this is a new ghost (not in our\n // tracker) but the classId is unregistered. This almost certainly means\n // the server sent UPDATE data (no classId prefix) for a ghost our tracker\n // lost, and we misread the first 7 bits of update data as a classId.\n // This is engine-consistent — the real client would also fail here\n // because classId lookup would return NULL, triggering packet drop.\n if (isNew && !parserEntry) {\n this.ghostsTrackerDiverged++;\n debugGhosts(\n \"DIVERGED pkt=%d seq=%d idx=%d classId=%d bit=%d/%d trackerSize=%d \" +\n \"(server sent UPDATE for ghost not in our tracker; 7-bit classId is actually update data)\",\n this.packetsParsed,\n seqNumber,\n index,\n classId,\n updateBitsStart,\n bs.getMaxPos(),\n this.ghostTracker.size(),\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n failed: true,\n error: `no ghost parser bound for classId ${classId} (tracker divergence)`,\n });\n return ghosts;\n }\n\n let parsed = false;\n let error: string | undefined;\n\n if (parserEntry) {\n try {\n const conn = this.getConnectionContext();\n const parsedData = parserEntry.unpackUpdate(bs, isNew, conn);\n if (bs.isError()) {\n throw new Error(\"ran past the end of the packet\");\n }\n const endPos = bs.getCurPos();\n\n if (isNew && classId !== undefined) {\n this.ghostTracker.createGhost(index, classId, parserEntry.name);\n this.ghostCreatesParsed++;\n } else {\n this.ghostUpdatesParsed++;\n }\n\n ghosts.push({\n index,\n type: isNew ? \"create\" : \"update\",\n classId,\n updateBitsStart,\n updateBitsEnd: endPos,\n parsedData,\n });\n parsed = true;\n } catch (e) {\n this.ghostsFailed++;\n const op = isNew ? \"create\" : \"update\";\n const message = errorMessage(e);\n error = `${parserEntry.name}: ${message}`;\n debugGhosts(\n \"FAIL pkt=%d seq=%d #%d idx=%d op=%s classId=%d parser=%s bit=%d/%d trackerSize=%d err=%s\",\n this.packetsParsed,\n seqNumber,\n ghosts.length,\n index,\n op,\n classId,\n parserEntry.name,\n updateBitsStart,\n bs.getMaxPos(),\n this.ghostTracker.size(),\n message,\n );\n }\n }\n\n if (parsed) continue;\n\n debugGhosts(\n \"STOP pkt=%d seq=%d idx=%d op=%s classId=%d parser=%s bit=%d/%d\",\n this.packetsParsed,\n seqNumber,\n index,\n isNew ? \"create\" : \"update\",\n classId,\n parserEntry?.name ?? \"NONE\",\n updateBitsStart,\n bs.getMaxPos(),\n );\n\n // Record and stop — can't parse this ghost's data.\n ghosts.push({\n index,\n type: isNew ? \"create\" : \"update\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n failed: true,\n error:\n error ??\n (parserEntry\n ? `${parserEntry.name}: unknown error`\n : `no ghost parser bound for classId ${classId}`),\n });\n return ghosts;\n }\n\n return ghosts;\n }\n\n private emptyGameState(): GameState {\n return {\n lastMoveAck: 0,\n pinged: false,\n jammed: false,\n };\n }\n}\n"]}
|
package/dist/Timeline.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export interface GameEvent {
|
|
|
38
38
|
/** Complete timeline extracted from a demo file. */
|
|
39
39
|
export interface DemoTimeline {
|
|
40
40
|
durationMs: number;
|
|
41
|
+
/** Simulation tick length (MoveTickMs); keyframe times are multiples of it. */
|
|
41
42
|
tickIntervalMs: number;
|
|
42
43
|
packetCount: number;
|
|
43
44
|
ghostInstances: GhostInstance[];
|
|
@@ -47,8 +48,10 @@ export interface DemoTimeline {
|
|
|
47
48
|
/**
|
|
48
49
|
* Extracts a time-indexed DemoTimeline from a parsed DemoFile.
|
|
49
50
|
*
|
|
50
|
-
*
|
|
51
|
-
* the
|
|
51
|
+
* Each Move block is one fixed 32ms simulation tick, so a packet's
|
|
52
|
+
* timestamp is the number of Move blocks that precede it × 32ms. This is
|
|
53
|
+
* exact demo time (the recorder writes a Move block every tick whether or
|
|
54
|
+
* not a packet arrived), and it matches `DemoParser.bufferedMoveTicks`.
|
|
52
55
|
*/
|
|
53
56
|
export declare function buildTimeline(demo: DemoFile, registry: ClassRegistry): DemoTimeline;
|
|
54
57
|
export interface TimelineStats {
|
package/dist/Timeline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Timeline.d.ts","sourceRoot":"","sources":["../src/Timeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EAKT,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEjD,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAM3B,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,gCAAgC;AAChC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAMD
|
|
1
|
+
{"version":3,"file":"Timeline.d.ts","sourceRoot":"","sources":["../src/Timeline.ts"],"names":[],"mappings":"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"}
|