t2-demo-parser 4.0.0 → 4.1.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/dist/DemoParser.d.ts +46 -1
- package/dist/DemoParser.d.ts.map +1 -1
- package/dist/DemoParser.js +24 -0
- package/dist/DemoParser.js.map +1 -1
- package/dist/PacketParser.d.ts +37 -0
- package/dist/PacketParser.d.ts.map +1 -1
- package/dist/PacketParser.js +47 -2
- package/dist/PacketParser.js.map +1 -1
- package/package.json +1 -1
package/dist/DemoParser.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PacketParser } from "./PacketParser.js";
|
|
2
2
|
import type { ClassRegistry } from "./ClassRegistry.js";
|
|
3
3
|
import { GhostTracker } from "./GhostManager.js";
|
|
4
|
-
import type { DemoHeader, DemoFile, DemoBlock, InitialBlockData, LoadResult } from "./types.js";
|
|
4
|
+
import type { DemoHeader, DemoFile, DemoBlock, InitialBlockData, NetEventInfo, LoadResult } from "./types.js";
|
|
5
5
|
export declare class DemoParser {
|
|
6
6
|
private buffer;
|
|
7
7
|
private view;
|
|
@@ -17,6 +17,7 @@ export declare class DemoParser {
|
|
|
17
17
|
private _blockStreamOffset;
|
|
18
18
|
private _blockCount?;
|
|
19
19
|
private _blockCursor;
|
|
20
|
+
private readonly checkpointOwner;
|
|
20
21
|
private readonly _incremental;
|
|
21
22
|
private _complete;
|
|
22
23
|
private _inflator?;
|
|
@@ -120,6 +121,50 @@ export declare class DemoParser {
|
|
|
120
121
|
* Throws if load() has not been called.
|
|
121
122
|
*/
|
|
122
123
|
nextBlock(): DemoBlock | undefined;
|
|
124
|
+
/** Capture a block boundary without copying the recording or inflater. */
|
|
125
|
+
createCheckpoint(): {
|
|
126
|
+
owner: {};
|
|
127
|
+
blockStreamOffset: number;
|
|
128
|
+
blockCursor: number;
|
|
129
|
+
ghosts: ReadonlyMap<number, import("./ClassRegistry.js").GhostEntry>;
|
|
130
|
+
packetState: {
|
|
131
|
+
dataBlockDataMap: Map<number, import("./ClassRegistry.js").ParsedData> | undefined;
|
|
132
|
+
compressionPoint: {
|
|
133
|
+
x: number;
|
|
134
|
+
y: number;
|
|
135
|
+
z: number;
|
|
136
|
+
};
|
|
137
|
+
lastSeqRecvdAtSend: number[];
|
|
138
|
+
lastSeqRecvd: number;
|
|
139
|
+
highestAckedSeq: number;
|
|
140
|
+
lastSendSeq: number;
|
|
141
|
+
recvAckMask: number;
|
|
142
|
+
connectSequence: number;
|
|
143
|
+
lastRecvAckAck: number;
|
|
144
|
+
_connectionEstablished: boolean;
|
|
145
|
+
nextRecvEventSeq: number;
|
|
146
|
+
pendingGuaranteedEvents: {
|
|
147
|
+
absoluteSequenceNumber: number;
|
|
148
|
+
event: NetEventInfo;
|
|
149
|
+
}[];
|
|
150
|
+
_fault: import("./types.js").ParseFault | undefined;
|
|
151
|
+
controlObjectParsed: number;
|
|
152
|
+
controlObjectFailed: number;
|
|
153
|
+
eventsParsed: number;
|
|
154
|
+
eventsFailed: number;
|
|
155
|
+
ghostCreatesParsed: number;
|
|
156
|
+
ghostUpdatesParsed: number;
|
|
157
|
+
ghostDeletes: number;
|
|
158
|
+
ghostsFailed: number;
|
|
159
|
+
ghostsTrackerDiverged: number;
|
|
160
|
+
packetsParsed: number;
|
|
161
|
+
protocolRejected: number;
|
|
162
|
+
protocolNoDispatch: number;
|
|
163
|
+
packetsDroppedAfterFault: number;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
/** Checkpoints belong to this parser, including after its download grows. */
|
|
167
|
+
restoreCheckpoint(checkpoint: ReturnType<DemoParser["createCheckpoint"]>): void;
|
|
123
168
|
/**
|
|
124
169
|
* Reset stepping state: resets stream offset and cursor to 0,
|
|
125
170
|
* clears cached block count, and re-initializes the PacketParser
|
package/dist/DemoParser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DemoParser.d.ts","sourceRoot":"","sources":["../src/DemoParser.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,oBAAoB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAY,MAAM,mBAAmB,CAAC;AAqB3D,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,SAAS,EACT,gBAAgB,
|
|
1
|
+
{"version":3,"file":"DemoParser.d.ts","sourceRoot":"","sources":["../src/DemoParser.ts"],"names":[],"mappings":"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"}
|
package/dist/DemoParser.js
CHANGED
|
@@ -42,6 +42,7 @@ export class DemoParser {
|
|
|
42
42
|
_blockStreamOffset = 0;
|
|
43
43
|
_blockCount;
|
|
44
44
|
_blockCursor = 0;
|
|
45
|
+
checkpointOwner = {};
|
|
45
46
|
// Incremental mode: the compressed block stream arrives in chunks via
|
|
46
47
|
// push() and is inflated as it goes; nextBlock() treats the end of the
|
|
47
48
|
// decompressed data as a frontier (more may arrive) until finish().
|
|
@@ -400,6 +401,29 @@ export class DemoParser {
|
|
|
400
401
|
}
|
|
401
402
|
return block;
|
|
402
403
|
}
|
|
404
|
+
/** Capture a block boundary without copying the recording or inflater. */
|
|
405
|
+
createCheckpoint() {
|
|
406
|
+
if (!this._loaded)
|
|
407
|
+
throw new Error("must call load() first");
|
|
408
|
+
return {
|
|
409
|
+
owner: this.checkpointOwner,
|
|
410
|
+
blockStreamOffset: this._blockStreamOffset,
|
|
411
|
+
blockCursor: this._blockCursor,
|
|
412
|
+
ghosts: structuredClone(this.ghostTracker.getAllGhosts()),
|
|
413
|
+
packetState: this.packetParser.saveState(),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/** Checkpoints belong to this parser, including after its download grows. */
|
|
417
|
+
restoreCheckpoint(checkpoint) {
|
|
418
|
+
if (checkpoint.owner !== this.checkpointOwner)
|
|
419
|
+
throw new Error("Checkpoint belongs to a different demo parser");
|
|
420
|
+
this._blockStreamOffset = checkpoint.blockStreamOffset;
|
|
421
|
+
this._blockCursor = checkpoint.blockCursor;
|
|
422
|
+
this.ghostTracker.clear();
|
|
423
|
+
for (const [index, ghost] of checkpoint.ghosts)
|
|
424
|
+
this.ghostTracker.createGhost(index, ghost.classId, ghost.className);
|
|
425
|
+
this.packetParser.restoreState(checkpoint.packetState);
|
|
426
|
+
}
|
|
403
427
|
/**
|
|
404
428
|
* Reset stepping state: resets stream offset and cursor to 0,
|
|
405
429
|
* clears cached block count, and re-initializes the PacketParser
|
package/dist/DemoParser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DemoParser.js","sourceRoot":"","sources":["../src/DemoParser.ts"],"names":[],"mappings":"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","sourcesContent":["import { inflate, Inflate } from \"fflate\";\nimport createDebug from \"debug\";\nimport type { MoveData } from \"./ghostDataTypes.js\";\nimport { BitStream } from \"./BitStream.js\";\nimport { PacketParser } from \"./PacketParser.js\";\nimport type { ClassRegistry, GhostParserEntry } from \"./ClassRegistry.js\";\nimport { createDefaultRegistry } from \"./defaultRegistry.js\";\nimport { GhostTracker, readMove } from \"./GhostManager.js\";\nimport {\n BlockTypePacket,\n BlockTypeSendPacket,\n BlockTypeMove,\n BlockTypeInfo,\n DemoIdentString,\n DemoProtocolVersion,\n MaxTriggerKeys,\n NetEventClassBitSize,\n NetEventClassFirst,\n NetObjectClassBitSize,\n NetObjectClassFirst,\n GhostIdBitSize,\n DataBlockClassFirst,\n DataBlockClassNames,\n SimDBEventObjectIdBits,\n SimDBEventClassIdBits,\n SimDBEventIndexBits,\n SimDBEventTotalBits,\n} from \"./types.js\";\nimport type {\n DemoHeader,\n DemoFile,\n DemoBlock,\n InitialBlockData,\n ConnectionProtocolState,\n DataBlockHeader,\n ParsedDataBlock,\n PathManagerEntry,\n TargetEntry,\n Move,\n InfoBlock,\n GhostUpdate,\n NetEventInfo,\n LoadResult,\n} from \"./types.js\";\n\nconst debug = createDebug(\"t2-demo-parser\");\n/**\n * Sequence numbers assigned to ordered events carried in the demo start\n * block: past every 32-bit sequence, so they stay queued without ever\n * matching `nextRecvEventSeq` (see setupPacketParser).\n */\nconst START_BLOCK_EVENT_SEQ_BASE = 0x1_0000_0000;\n\nconst debugInitial = createDebug(\"t2-demo-parser:initial\");\nconst debugBlocks = createDebug(\"t2-demo-parser:blocks\");\n\n/**\n * Read a U32 count and reject it unless `minBitsPerEntry × count` bits\n * remain: exhausted reads return 0 without throwing, so a corrupt count\n * would otherwise spin allocating until memory ran out.\n */\nfunction readCheckedCount(\n bs: BitStream,\n minBitsPerEntry: number,\n what: string,\n): number {\n const count = bs.readU32();\n if (count > bs.getRemainingBits() / minBitsPerEntry) {\n throw new Error(`Invalid ${what}: ${count}`);\n }\n return count;\n}\n\nexport class DemoParser {\n private buffer: Uint8Array;\n private view: DataView;\n private offset: number;\n private registry: ClassRegistry;\n private ghostTracker: GhostTracker;\n private packetParser: PacketParser;\n // Stepping API state\n private _loaded = false;\n private _header?: DemoHeader;\n private _initialBlock?: InitialBlockData;\n private _decompressedData?: Uint8Array;\n private _decompressedView?: DataView;\n private _blockStreamOffset = 0;\n private _blockCount?: number;\n private _blockCursor = 0;\n // Incremental mode: the compressed block stream arrives in chunks via\n // push() and is inflated as it goes; nextBlock() treats the end of the\n // decompressed data as a frontier (more may arrive) until finish().\n private readonly _incremental: boolean;\n private _complete = true;\n private _inflator?: Inflate;\n /** The zlib stream announced its own end (final deflate block seen) —\n * later bytes are trailing garbage and further pushes would throw. */\n private _streamEnded = false;\n /** Backing store for the growing decompressed stream (incremental\n * mode). `_decompressedData` is always a length-exact subarray of\n * this, so every existing `.length`-based read stays correct. */\n private _backing?: Uint8Array;\n private _decompressedLength = 0;\n // Buffered-time scan state (see bufferedMoveTicks).\n private _scanOffset = 0;\n private _bufferedMoveTicks = 0;\n\n private readonly _ignoreProtocolVersion: boolean;\n private readonly _haltOnFault: boolean | undefined;\n\n constructor(\n buffer: Uint8Array,\n options?: {\n /** Feed the compressed block stream in chunks via push()/finish(). */\n incremental?: boolean;\n /**\n * Parse demos whose protocol version differs from build 25034's\n * (0x330004). The game itself refuses to play them, and the block\n * formats are not guaranteed to match, so expect faults.\n */\n ignoreProtocolVersion?: boolean;\n /** Passed to PacketParser; see its `haltOnFault` option. */\n haltOnFault?: boolean;\n },\n ) {\n this.buffer = buffer;\n this.view = new DataView(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength,\n );\n this.offset = 0;\n this._incremental = options?.incremental === true;\n this._ignoreProtocolVersion = options?.ignoreProtocolVersion === true;\n this._haltOnFault = options?.haltOnFault;\n // Parser catalogs bound to their deterministic classIds (derived from\n // binary analysis of the Tribes 2 executable).\n this.registry = createDefaultRegistry();\n this.ghostTracker = new GhostTracker();\n this.packetParser = new PacketParser(this.registry, this.ghostTracker);\n }\n\n getRegistry(): ClassRegistry {\n return this.registry;\n }\n\n getGhostTracker(): GhostTracker {\n return this.ghostTracker;\n }\n\n getPacketParser(): PacketParser {\n return this.packetParser;\n }\n\n // --- Stepping API getters ---\n\n get loaded(): boolean {\n return this._loaded;\n }\n\n get header(): DemoHeader {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._header!;\n }\n\n get initialBlock(): InitialBlockData {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._initialBlock!;\n }\n\n get blockCount(): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._blockCount === undefined) {\n // Lazy scan: walk decompressed buffer counting U16 headers\n let count = 0;\n this._walkBlockHeaders(0, () => {\n count++;\n });\n this._blockCount = count;\n }\n return this._blockCount;\n }\n\n /**\n * Walk complete block headers from byte offset `from`, calling `visit`\n * for each; returns the offset of the first incomplete block (or the\n * end of the data).\n */\n private _walkBlockHeaders(\n from: number,\n visit: (type: number, size: number) => void,\n ): number {\n const data = this._decompressedData;\n const view = this._decompressedView;\n if (!data || !view) return from;\n let off = from;\n while (off + 2 <= data.length) {\n const typeSize = view.getUint16(off, true);\n const size = typeSize & 0xfff;\n if (off + 2 + size > data.length) break;\n visit(typeSize >> 12, size);\n off += 2 + size;\n }\n return off;\n }\n\n get blockCursor(): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._blockCursor;\n }\n\n // --- Stepping API methods ---\n\n /**\n * Async load: parses header, initial block (DataBlocks, events,\n * ghosts, control object, mission name), and asynchronously decompresses\n * the block stream. No block indexing — blocks are read lazily via nextBlock().\n *\n * Idempotent — second call returns cached result.\n */\n async load(): Promise<LoadResult> {\n if (this._loaded) {\n return {\n header: this._header!,\n initialBlock: this._initialBlock!,\n };\n }\n\n // Phase 1: header + initial block\n const header = this.readHeader();\n debug(\n 'header: \"%s\" version=0x%s length=%dms (%smin) initialBlockSize=%d',\n header.identString,\n header.protocolVersion.toString(16),\n header.demoLengthMs,\n (header.demoLengthMs / 1000 / 60).toFixed(1),\n header.initialBlockSize,\n );\n\n if (this.buffer.length < this.offset + header.initialBlockSize) {\n if (this._incremental) {\n throw new RangeError(\n `incremental parser needs the full initial block up front: have ${\n this.buffer.length - this.offset\n } bytes, need ${header.initialBlockSize}`,\n );\n }\n throw new RangeError(\n `truncated demo: initial block needs ${header.initialBlockSize} bytes, have ${\n this.buffer.length - this.offset\n }`,\n );\n }\n const initialBlockData = this.buffer.subarray(\n this.offset,\n this.offset + header.initialBlockSize,\n );\n const initialBlock = this.readInitialBlock(initialBlockData);\n this.offset += header.initialBlockSize;\n\n if (this._incremental) {\n // Phase 2 (incremental): streaming inflate. Compressed bytes\n // arrive via push(); whatever tail the constructor buffer already\n // holds past the initial block is the first chunk. fflate's\n // Inflate emits decompressed output synchronously during push.\n this._complete = false;\n this._decompressedLength = 0;\n this._backing = new Uint8Array(1 << 20);\n this._decompressedData = this._backing.subarray(0, 0);\n this._decompressedView = new DataView(this._backing.buffer, 0, 0);\n this._inflator = new Inflate((chunk, final) => {\n this._appendDecompressed(chunk);\n if (final) this._streamEnded = true;\n });\n const tail = this.buffer.subarray(this.offset);\n // The prefix buffer has served its purpose (header + initial block\n // are parsed); don't retain arbitrary compressed tail bytes twice.\n if (tail.length > 0) this._inflator.push(tail);\n } else {\n // Phase 2: async decompress block stream\n const compressedData = this.buffer.subarray(this.offset);\n debug(\"compressed block stream: %d bytes\", compressedData.length);\n\n const decompressedData = await new Promise<Uint8Array>(\n (resolve, reject) => {\n inflate(compressedData, (err, data) => {\n if (err) reject(err);\n else resolve(data);\n });\n },\n );\n debug(\"decompressed block stream: %d bytes\", decompressedData.length);\n\n this._decompressedData = decompressedData;\n this._decompressedView = new DataView(\n decompressedData.buffer,\n decompressedData.byteOffset,\n decompressedData.byteLength,\n );\n }\n\n // Phase 3: set up PacketParser with seeded ghost tracker\n this.setupPacketParser(initialBlock);\n\n // Cache results\n this._header = header;\n this._initialBlock = initialBlock;\n this._blockStreamOffset = 0;\n this._blockCursor = 0;\n this._loaded = true;\n\n return { header, initialBlock };\n }\n\n /**\n * Parse just the fixed-size demo header from a byte prefix, without\n * constructing a parser. Throws RangeError when `bytes` is too short —\n * callers streaming a download retry as more data arrives. The\n * returned `byteLength` is where the initial block begins; the block\n * stream begins at `byteLength + header.initialBlockSize`.\n */\n static peekHeader(bytes: Uint8Array): {\n header: DemoHeader;\n byteLength: number;\n } {\n if (bytes.length < 1) throw new RangeError(\"incomplete header\");\n const strLen = bytes[0];\n const byteLength = 1 + strLen + 12;\n if (bytes.length < byteLength) throw new RangeError(\"incomplete header\");\n const identString = new TextDecoder(\"ascii\").decode(\n bytes.subarray(1, 1 + strLen),\n );\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const protocolVersion = view.getUint32(1 + strLen, true);\n const demoLengthMs = view.getUint32(1 + strLen + 4, true);\n const initialBlockSize = view.getUint32(1 + strLen + 8, true);\n return {\n header: { identString, protocolVersion, demoLengthMs, initialBlockSize },\n byteLength,\n };\n }\n\n /**\n * Incremental mode only: feed the next chunk of raw (compressed) block\n * stream bytes as they arrive. Inflation happens synchronously; any\n * blocks completed by this chunk become readable via nextBlock().\n * The chunk is not retained.\n */\n push(chunk: Uint8Array): void {\n if (!this._incremental) throw new Error(\"not an incremental parser\");\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._complete) throw new Error(\"already finished\");\n if (chunk.length === 0 || this._streamEnded) return;\n this._inflator!.push(chunk);\n }\n\n /**\n * Incremental mode only: signal that the download is complete. Flushes\n * the inflator; after this, running out of blocks means the true end\n * of the demo rather than the frontier.\n */\n finish(): void {\n if (!this._incremental) throw new Error(\"not an incremental parser\");\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._complete) return;\n if (!this._streamEnded) {\n try {\n this._inflator!.push(new Uint8Array(0), true);\n } catch (err) {\n // A truncated zlib stream: the blocks inflated so far remain\n // valid (nextBlock bounds-checks the tail) — degrade to a\n // shorter demo rather than failing the whole load.\n debug(\"finish(): inflate flush failed: %o\", err);\n }\n }\n this._inflator = undefined;\n this._complete = true;\n // Trim: the doubling backing store can overshoot by up to 2× —\n // release the slack now that the final length is known.\n if (this._backing && this._backing.length > this._decompressedLength) {\n const exact = this._backing.slice(0, this._decompressedLength);\n this._backing = exact;\n this._decompressedData = exact;\n this._decompressedView = new DataView(\n exact.buffer,\n exact.byteOffset,\n exact.byteLength,\n );\n }\n }\n\n /**\n * False only in incremental mode before finish(): nextBlock()\n * returning undefined then means \"frontier — more data may arrive\",\n * not the end of the demo.\n */\n get isComplete(): boolean {\n return this._complete;\n }\n\n /**\n * Bytes of decompressed block stream available so far. Grows during\n * an incremental feed; consumers that latched an \"out of blocks\"\n * state can compare against it to know new data has arrived.\n */\n get decompressedByteLength(): number {\n return this._incremental\n ? this._decompressedLength\n : (this._decompressedData?.length ?? 0);\n }\n\n /**\n * Move-tick blocks in the decompressed stream so far — each is one\n * fixed 32ms simulation tick, so this measures buffered DEMO TIME\n * exactly (compressed bytes don't: quiet stretches pack far denser).\n * Independent of the read cursor; unaffected by reset(). Maintained\n * incrementally as data arrives; a full lazy scan on first access\n * covers the one-shot mode.\n */\n get bufferedMoveTicks(): number {\n this._scanBufferedTicks();\n return this._bufferedMoveTicks;\n }\n\n private _scanBufferedTicks(): void {\n let ticks = this._bufferedMoveTicks;\n this._scanOffset = this._walkBlockHeaders(this._scanOffset, (type) => {\n if (type === BlockTypeMove) ticks++;\n });\n this._bufferedMoveTicks = ticks;\n }\n\n private _appendDecompressed(chunk: Uint8Array): void {\n if (chunk.length === 0) return;\n const needed = this._decompressedLength + chunk.length;\n let backing = this._backing!;\n if (needed > backing.length) {\n let capacity = backing.length;\n while (capacity < needed) capacity *= 2;\n const grown = new Uint8Array(capacity);\n grown.set(backing.subarray(0, this._decompressedLength));\n backing = grown;\n this._backing = grown;\n }\n backing.set(chunk, this._decompressedLength);\n this._decompressedLength = needed;\n // Refresh the exact-length views; subarray shares memory, so this is\n // cheap and keeps every `.length`-based reader (nextBlock,\n // blockCount) correct without touching them.\n this._decompressedData = backing.subarray(0, needed);\n this._decompressedView = new DataView(backing.buffer, 0, needed);\n // The lazily-cached block count no longer covers the new bytes.\n this._blockCount = undefined;\n }\n\n /**\n * Read and parse the next block from the decompressed buffer.\n * Returns the parsed block, or undefined when all blocks are exhausted.\n * Each block is transient — only one in memory at a time.\n * Throws if load() has not been called.\n */\n nextBlock(): DemoBlock | undefined {\n if (!this._loaded) throw new Error(\"must call load() first\");\n const data = this._decompressedData!;\n const view = this._decompressedView!;\n const off = this._blockStreamOffset;\n\n if (off + 2 > data.length) return undefined;\n\n const typeSize = view.getUint16(off, true);\n const type = typeSize >> 12;\n const size = typeSize & 0xfff;\n\n if (off + 2 + size > data.length) {\n debugBlocks(\n \"block %d: size %d would exceed decompressed data (offset=%d remaining=%d), stopping\",\n this._blockCursor,\n size,\n off + 2,\n data.length - off - 2,\n );\n return undefined;\n }\n\n const blockData = data.subarray(off + 2, off + 2 + size);\n this._blockStreamOffset = off + 2 + size;\n\n const block: DemoBlock = {\n index: this._blockCursor,\n type,\n size,\n data: blockData,\n };\n this._blockCursor++;\n\n // PacketParser reports problems through parseFault rather than\n // throwing; anything that does escape is a parser bug, and the raw\n // block plus the error text is kept for diagnosis.\n try {\n if (type === BlockTypePacket) {\n block.parsed = this.packetParser.parsePacket(blockData);\n } else if (type === BlockTypeSendPacket) {\n this.packetParser.onSendPacketTrigger();\n } else if (type === BlockTypeMove && size === 64) {\n block.parsed = this.readRawMove(blockData);\n } else if (type === BlockTypeInfo && size === 8) {\n block.parsed = this.readInfoBlock(blockData);\n }\n } catch (e) {\n block.parseError = e instanceof Error ? e.message : String(e);\n debugBlocks(\n \"block %d (type %d, %d bytes) threw: %s\",\n block.index,\n type,\n size,\n block.parseError,\n );\n }\n\n return block;\n }\n\n /**\n * Reset stepping state: resets stream offset and cursor to 0,\n * clears cached block count, and re-initializes the PacketParser\n * with a fresh ghost tracker seeded from the initial block.\n * Throws if load() has not been called.\n */\n reset(): void {\n if (!this._loaded) throw new Error(\"must call load() first\");\n\n this._blockStreamOffset = 0;\n this._blockCursor = 0;\n this._blockCount = undefined;\n\n // Fresh ghost tracker + packet parser\n this.setupPacketParser(this._initialBlock!);\n }\n\n /**\n * Fast-forward through N blocks, processing each but not returning them.\n * Returns the number of blocks actually processed (may be less than count\n * if the stream is exhausted).\n * Throws if load() has not been called.\n */\n processBlocks(count: number): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n let processed = 0;\n for (let i = 0; i < count; i++) {\n if (!this.nextBlock()) break;\n processed++;\n }\n return processed;\n }\n\n /**\n * Set up a fresh PacketParser seeded from the initial block's ghosts\n * and with the DataBlock data map for ghost parsers. Replaces\n * this.ghostTracker and this.packetParser.\n */\n private setupPacketParser(initialBlock: InitialBlockData): void {\n // Build DataBlock data map (objectId → parsed data)\n const dataBlockDataMap = new Map<number, Record<string, unknown>>();\n for (const [objectId, db] of initialBlock.dataBlocks) {\n dataBlockDataMap.set(objectId, db.data);\n }\n\n // Seed ghost tracker from initial block ghosts\n const gt = new GhostTracker();\n for (const ghost of initialBlock.initialGhosts) {\n if (ghost.type !== \"create\" || ghost.classId === undefined) continue;\n const parserEntry = this.registry.getGhostParser(ghost.classId);\n gt.createGhost(\n ghost.index,\n ghost.classId,\n parserEntry?.name ?? `unknown_${ghost.classId}`,\n );\n }\n\n const pp = new PacketParser(this.registry, gt, {\n dataBlockDataMap,\n connectionProtocolState: initialBlock.connectionState,\n nextRecvEventSeq: initialBlock.nextRecvEventSeq,\n compressionPoint: initialBlock.initialCompressionPoint,\n // NetConnection::eventReadStartBlock (FUN_00583ac0) appends the\n // start block's in-flight ordered events to the wait queue without\n // a sequence number (the field is never written; NetEvent's\n // constructor leaves it uninitialized), so in the engine they can\n // only ever dispatch by accident of heap contents. The deterministic\n // stand-in keeps them queued behind every possible real sequence\n // number, where they neither dispatch nor block dispatch.\n pendingGuaranteedEvents: initialBlock.initialEvents\n .filter((event) => !event.failed)\n .map((event, i) => ({\n absoluteSequenceNumber: START_BLOCK_EVENT_SEQ_BASE + i,\n event,\n })),\n haltOnFault: this._haltOnFault,\n });\n\n this.ghostTracker = gt;\n this.packetParser = pp;\n }\n\n /**\n * Full parse: async load + drain all blocks.\n */\n async parseFullDemo(): Promise<DemoFile> {\n const { header, initialBlock } = await this.load();\n const blocks: DemoBlock[] = [];\n let block: DemoBlock | undefined;\n while ((block = this.nextBlock())) blocks.push(block);\n return { header, initialBlock, blocks };\n }\n\n /**\n * Read and validate the header the way GameConnection's demo playback\n * does: the ident string must match and the protocol version must be\n * the one this build speaks (unless `ignoreProtocolVersion` is set).\n */\n private readHeader(): DemoHeader {\n const { header, byteLength } = DemoParser.peekHeader(\n this.buffer.subarray(this.offset),\n );\n this.offset += byteLength;\n if (header.identString !== DemoIdentString) {\n throw new Error(\n `not a Tribes 2 recording: ident string ${JSON.stringify(header.identString)}`,\n );\n }\n if (header.protocolVersion !== DemoProtocolVersion) {\n const detail = `protocol version 0x${header.protocolVersion.toString(16)} (expected 0x${DemoProtocolVersion.toString(16)})`;\n if (!this._ignoreProtocolVersion) {\n throw new Error(\n `unsupported demo ${detail}; the game rejects it too. Pass { ignoreProtocolVersion: true } to try anyway.`,\n );\n }\n debug(\"parsing demo with unexpected %s\", detail);\n }\n return header;\n }\n\n /** Parse the initial block: DataBlocks, scores, targets, connection state,\n * events, ghosts, control object, and mission name. */\n private readInitialBlock(data: Uint8Array): InitialBlockData {\n const bs = new BitStream(data);\n\n // --- A. Tagged string table (1024 entries) ---\n const taggedStrings = new Map<number, string>();\n for (let i = 0; i < 1024; i++) {\n if (bs.readFlag()) {\n taggedStrings.set(i, bs.readString());\n }\n }\n debugInitial(\n \"after tagged strings bit=%d count=%d\",\n bs.getCurPos(),\n taggedStrings.size,\n );\n\n // --- B.1 U32 datablockCount ---\n const expectedDataBlockCount = bs.readU32();\n\n // --- B.2 DataBlock loop ---\n const dataBlockHeaders: DataBlockHeader[] = [];\n const dataBlocks = new Map<number, ParsedDataBlock>();\n let dataBlockCount = 0;\n\n while (bs.readFlag()) {\n dataBlockCount++;\n const modified = bs.readFlag();\n if (!modified) {\n continue;\n }\n\n const objectId = bs.readInt(SimDBEventObjectIdBits);\n const classId = bs.readInt(SimDBEventClassIdBits) + DataBlockClassFirst;\n const index = bs.readInt(SimDBEventIndexBits);\n const total = bs.readInt(SimDBEventTotalBits);\n const dataBitsStart = bs.getCurPos();\n\n dataBlockHeaders.push({ objectId, classId, index, total, dataBitsStart });\n\n const parserEntry = this.registry.getDataBlockParser(classId);\n if (parserEntry) {\n const parsedData = parserEntry.unpackData(bs);\n dataBlocks.set(objectId, {\n classId,\n className: parserEntry.name,\n objectId,\n data: parsedData,\n });\n } else {\n const className =\n classId >= DataBlockClassFirst &&\n classId < DataBlockClassFirst + DataBlockClassNames.length\n ? DataBlockClassNames[classId - DataBlockClassFirst]\n : `unknown(${classId})`;\n throw new Error(\n `No parser for DataBlock classId ${classId} (${className}) at bit ${dataBitsStart}`,\n );\n }\n }\n\n debug(\n \"all %d/%d DataBlocks parsed (%d payloads), bit position after DataBlocks: %d\",\n dataBlockCount,\n expectedDataBlockCount,\n dataBlocks.size,\n bs.getCurPos(),\n );\n\n // --- B.3 $firstPerson (U8 boolean from GameConnection::writeDemoStartBlock) ---\n const firstPerson = bs.readU8() !== 0;\n // --- B.4 6× U32 connection fields ---\n // @0x8384, @0x8388, @0x83f8, @0x83fc, @0x8400, @0x8434\n const connectionFields: number[] = [];\n for (let i = 0; i < 6; i++) connectionFields.push(bs.readU32());\n\n // --- B.5 16× U32 state array ---\n // @0x83b8 + i*4, i=0..15\n const stateArray: number[] = [];\n for (let i = 0; i < 16; i++) stateArray.push(bs.readU32());\n\n // --- B.6 U32 move count ---\n // A packed move is at least 3 + 18 + 1 + 6 = 28 bits (FUN_00601800).\n const moveCount = readCheckedCount(bs, 28, \"move count\");\n\n // --- B.7 Queued moves × count (FUN_00601800) ---\n const moves: MoveData[] = [];\n for (let i = 0; i < moveCount; i++) {\n moves.push(readMove(bs));\n }\n debugInitial(\n \"after queued moves bit=%d moveCount=%d\",\n bs.getCurPos(),\n moveCount,\n );\n\n // B.8: FUN_005fb130 — clears internal state, no bitstream I/O\n\n // --- B.8 DemoValues ---\n const demoValues = this.readDemoValues(bs);\n debugInitial(\n \"after demo values bit=%d demoValues=%d\",\n bs.getCurPos(),\n demoValues.length,\n );\n\n // --- B.9 Complex TargetManager (FUN_00670660) ---\n const { sensorGroupColors, targets: targetEntries } =\n this.readComplexTargetManager(bs);\n debugInitial(\n \"after complex target manager bit=%d targets=%d sensorGroupColors=%d\",\n bs.getCurPos(),\n targetEntries.length,\n sensorGroupColors.length,\n );\n\n // --- B.10 Parent: NetConnection::readDemoStartBlock (FUN_00588260) ---\n\n // B.10a ConnectionProtocol (FUN_0043d820)\n const connectionState = this.readConnectionProtocol(bs);\n debugInitial(\n \"after connection protocol bit=%d lastRecv=%d highestAck=%d lastSend=%d connected=%s\",\n bs.getCurPos(),\n connectionState.lastSeqRecvd,\n connectionState.highestAckedSeq,\n connectionState.lastSendSeq,\n connectionState.connectionEstablished,\n );\n\n // B.10b RTT, B.10c packet loss\n const roundTripTime = bs.readF32();\n const packetLoss = bs.readF32();\n debugInitial(\n \"after RTT/loss bit=%d rtt=%d loss=%d\",\n bs.getCurPos(),\n roundTripTime,\n packetLoss,\n );\n\n // B.10d PathManager (FUN_00591ce0)\n const pathManager = this.readPathManager(bs);\n debugInitial(\n \"after path manager bit=%d entries=%d\",\n bs.getCurPos(),\n pathManager.length,\n );\n\n // B.10e Notify count only (FUN_00588260).\n // The reader allocates notify nodes in memory but does not consume\n // per-notify records from the bitstream in this phase.\n const notifyCount = bs.readU32();\n // Engine invariant (verified in build 25034): the start block carries\n // one PacketNotify per in-flight packet, i.e. exactly\n // lastSendSeq - highestAckedSeq of them. checkPacketSend\n // (FUN_005877e0) refuses to queue a notify while windowFull\n // (FUN_0043d720: lastSendSeq - highestAckedSeq > 0x1d), and\n // handleNotify (FUN_005874d0) pops the queue head with no null check on\n // every newly acked sequence, so a mismatched seed crashes playback on\n // the first ack. Every Tribes2.exe recording satisfies this exactly.\n const warnings: string[] = [];\n const inFlight =\n (connectionState.lastSendSeq - connectionState.highestAckedSeq) >>> 0;\n if (notifyCount !== inFlight) {\n warnings.push(\n `notify count ${notifyCount} does not match in-flight packets ` +\n `(lastSendSeq ${connectionState.lastSendSeq} - highestAckedSeq ` +\n `${connectionState.highestAckedSeq} = ${inFlight}); Tribes2.exe ` +\n `dereferences an empty notify queue on the first ack`,\n );\n }\n debugInitial(\n \"after notify count bit=%d notifyCount=%d\",\n bs.getCurPos(),\n notifyCount,\n );\n\n // --- B.10f through B.15: events, ghosts, control object, mission ---\n // Uses a temporary ghost tracker for initial-block ghost parsing only.\n const totalBits = bs.getBuffer().length * 8;\n const ibGhostTracker = new GhostTracker();\n const savedGhostTracker = this.ghostTracker;\n this.ghostTracker = ibGhostTracker;\n\n let initialEvents: NetEventInfo[] = [];\n let nextRecvEventSeq = 0;\n let ghostingSequence = 0;\n let initialGhosts: GhostUpdate[] = [];\n let controlObjectGhostIndex = -1;\n let controlObjectData: Record<string, unknown> | undefined;\n let initialCompressionPoint:\n { x: number; y: number; z: number } | undefined;\n let missionName = \"\";\n let missionCRC = 0;\n let phase2Error: string | undefined;\n try {\n debugInitial(\n \"phase2 start bit=%d remaining=%d\",\n bs.getCurPos(),\n totalBits - bs.getCurPos(),\n );\n\n // B.10f Events\n ({ nextRecvEventSeq, events: initialEvents } =\n this.readEventStartBlock(bs));\n debugInitial(\n \"after initial events bit=%d count=%d\",\n bs.getCurPos(),\n initialEvents.length,\n );\n\n // B.10g Ghosts\n const ghostResult = this.readGhostStartBlock(bs, dataBlocks);\n ghostingSequence = ghostResult.ghostingSequence;\n initialGhosts = ghostResult.ghosts;\n const lastInitialGhost = initialGhosts[initialGhosts.length - 1];\n if (lastInitialGhost?.failed) {\n // The engine sets \"Invalid packet.\" here and drops the connection\n // once the start block is done; the fields below are still read,\n // misaligned, exactly as it reads them.\n phase2Error ??= `initial ghost ${lastInitialGhost.index} (classId ${lastInitialGhost.classId}) failed: ${lastInitialGhost.error}`;\n }\n debugInitial(\n \"after initial ghosts bit=%d count=%d seq=%d\",\n bs.getCurPos(),\n initialGhosts.length,\n ghostingSequence,\n );\n\n // B.11 controlObjectGhostIndex\n controlObjectGhostIndex = bs.readS32();\n debugInitial(\n \"after control ghost index bit=%d control=%d\",\n bs.getCurPos(),\n controlObjectGhostIndex,\n );\n\n // B.12 If != -1: controlObject readPacketData\n if (controlObjectGhostIndex !== -1) {\n // The engine resolves the ghost and calls its readPacketData with\n // no fallback; if we cannot, every later read in the initial\n // block (mission name, CRC) would be misaligned, so fail phase 2.\n const ghost = ibGhostTracker.getGhost(controlObjectGhostIndex);\n if (!ghost) {\n throw new Error(\n `control object ghost ${controlObjectGhostIndex} not found among initial ghosts`,\n );\n }\n const parser = this.registry.getGhostParser(ghost.classId);\n if (!parser?.readPacketData) {\n throw new Error(\n `control object ghost ${controlObjectGhostIndex} (${ghost.className}) has no readPacketData parser`,\n );\n }\n // getGhostParser enables the nested vehicle readPacketData when\n // the recorder was piloting at recording start.\n const conn = {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: ibGhostTracker,\n getGhostParser: (classId: number) =>\n this.registry.getGhostParser(classId),\n };\n controlObjectData = parser.readPacketData(bs, conn);\n // The control object's readPacketData establishes the\n // connection's compression point (its position) — carry it\n // into the packet parser seed.\n initialCompressionPoint = conn.compressionPoint;\n debugInitial(\n \"after control readPacketData bit=%d parser=%s\",\n bs.getCurPos(),\n parser.name,\n );\n }\n\n // B.13 $MissionName\n missionName = bs.readString();\n // B.14 mMissionCRC\n missionCRC = bs.readU32();\n // B.15 Simple TargetManager ×2. FUN_006021b0 reads U8 + 4×U32 at the\n // current bit position; the binary does not byte-align here.\n this.readSimpleTargetManager(bs);\n this.readSimpleTargetManager(bs);\n debugInitial(\n 'after sequential tail bit=%d mission=\"%s\" CRC=0x%s',\n bs.getCurPos(),\n missionName,\n missionCRC.toString(16),\n );\n } catch (e) {\n phase2Error = e instanceof Error ? e.message : String(e);\n } finally {\n this.ghostTracker = savedGhostTracker;\n }\n\n const remaining = totalBits - bs.getCurPos();\n const missionPrintableRatio =\n missionName.length > 0\n ? missionName.split(\"\").filter((c) => {\n const code = c.charCodeAt(0);\n return code >= 0x20 && code <= 0x7e;\n }).length / missionName.length\n : 1;\n const phase2Valid =\n missionName.length > 0 &&\n missionPrintableRatio >= 0.8 &&\n phase2Error === undefined;\n\n debug(\n 'initial block: events=%d ghosts=%d ghostingSeq=%d controlObj=%d mission=\"%s\" CRC=0x%s valid=%s%s',\n initialEvents.length,\n initialGhosts.length,\n ghostingSequence,\n controlObjectGhostIndex,\n missionName,\n missionCRC.toString(16),\n phase2Valid,\n phase2Error ? ` error=${phase2Error}` : \"\",\n );\n for (const warning of warnings) {\n debug(\"initial block warning: %s\", warning);\n }\n\n return {\n taggedStrings,\n dataBlockHeaders,\n dataBlockCount,\n dataBlocks,\n firstPerson,\n connectionFields,\n stateArray,\n moves,\n demoValues,\n sensorGroupColors,\n targetEntries,\n connectionState,\n roundTripTime,\n packetLoss,\n pathManager,\n notifyCount,\n nextRecvEventSeq,\n ghostingSequence,\n initialGhosts,\n initialEvents,\n controlObjectGhostIndex,\n controlObjectData,\n initialCompressionPoint,\n missionName,\n missionCRC,\n phase2TrailingBits: remaining,\n phase2Valid,\n phase2Error,\n warnings,\n };\n }\n\n /**\n * Read DemoValues from FUN_005fb5c0 lines 388966-388980.\n * Format: while(readFlag()) { readString(value) }\n * Variable names are derived from index ($DemoValue_0, $DemoValue_1, etc.).\n */\n private readDemoValues(bs: BitStream): string[] {\n const values: string[] = [];\n while (bs.readFlag()) {\n values.push(bs.readString());\n }\n return values;\n }\n\n /**\n * Read Complex TargetManager from FUN_00670660.\n *\n * Phase 1: 4×U8 initial data\n * Phase 2: 32×32 grid — each cell: readFlag + if true: 4×U8\n * Phase 3: 512 target entries with conditional fields\n */\n private readComplexTargetManager(bs: BitStream): {\n sensorGroupColors: import(\"./types.js\").SensorGroupColor[];\n targets: TargetEntry[];\n } {\n // Phase 1: FUN_0043efe0 — read 4 bytes (4×U8)\n bs.readU8();\n bs.readU8();\n bs.readU8();\n bs.readU8();\n\n // Phase 2: 32×32 sensor group color grid (IFF colors).\n // sensorGroupColors[group][targetGroup] = RGBA determines how targetGroup\n // appears to group (e.g., red for enemy, green for friendly).\n const sensorGroupColors: import(\"./types.js\").SensorGroupColor[] = [];\n for (let group = 0; group < 32; group++) {\n for (let targetGroup = 0; targetGroup < 32; targetGroup++) {\n if (bs.readFlag()) {\n sensorGroupColors.push({\n group,\n targetGroup,\n r: bs.readU8(),\n g: bs.readU8(),\n b: bs.readU8(),\n a: bs.readU8(),\n });\n }\n }\n }\n\n // Phase 3: 512 target entries\n const targets: TargetEntry[] = [];\n for (let i = 0; i < 512; i++) {\n if (!bs.readFlag()) continue; // Target not active\n\n const entry: TargetEntry = {\n targetId: i,\n sensorGroup: 0,\n targetData: 0,\n damageLevel: 0,\n };\n\n // Conditional sensor data\n if (bs.readFlag()) {\n entry.sensorData = bs.readU32(); // F32 sensorData\n }\n // Conditional voice map data\n if (bs.readFlag()) {\n entry.voiceMapData = bs.readU32(); // F32 voiceMapData\n }\n // 5 conditional strings: name, skin, skinPref, voice, typeDescription\n if (bs.readFlag()) entry.name = bs.readString();\n if (bs.readFlag()) entry.skin = bs.readString();\n if (bs.readFlag()) entry.skinPref = bs.readString();\n if (bs.readFlag()) entry.voice = bs.readString();\n if (bs.readFlag()) entry.typeDescription = bs.readString();\n\n // Always-read fields\n entry.sensorGroup = bs.readInt(5); // team/type\n entry.targetData = bs.readInt(9); // target data\n\n // Targets >= 32 have additional DataBlock reference\n if (i >= 32) {\n if (bs.readFlag()) {\n entry.dataBlockRef = bs.readInt(11); // DataBlock reference (FUN_00436d10: readClassId)\n }\n // Virtual call notification — no bitstream I/O\n }\n\n // Damage level: readFloat(7) — always read for all active targets\n entry.damageLevel = bs.readFloat(7);\n\n targets.push(entry);\n }\n\n return { sensorGroupColors, targets };\n }\n\n /**\n * Read PathManager from FUN_00591ce0.\n * Decompiled format:\n * - U32 entryCount\n * - repeat entryCount:\n * - U32 entryId\n * - U32 recordCount\n * - repeat recordCount:\n * - U32 field0\n * - U32 field1\n * - U32 field2\n * - U32 auxField\n */\n private readPathManager(bs: BitStream): PathManagerEntry[] {\n const entries: PathManagerEntry[] = [];\n const entryCount = readCheckedCount(bs, 64, \"PathManager entry count\");\n for (let i = 0; i < entryCount; i++) {\n const entryId = bs.readU32();\n const recordCount = readCheckedCount(bs, 128, \"PathManager record count\");\n const records: {\n field0: number;\n field1: number;\n field2: number;\n auxField: number;\n }[] = [];\n for (let j = 0; j < recordCount; j++) {\n records.push({\n field0: bs.readU32(),\n field1: bs.readU32(),\n field2: bs.readU32(),\n auxField: bs.readU32(),\n });\n }\n entries.push({ entryId, records });\n }\n return entries;\n }\n\n /**\n * Read Simple TargetManager from FUN_006021b0.\n * Format: U8 flag + 4×U32 = 136 bits total.\n */\n private readSimpleTargetManager(bs: BitStream): void {\n bs.readU8(); // _read(1) = 8 bits\n bs.readU32(); // 4× _read(4)\n bs.readU32();\n bs.readU32();\n bs.readU32();\n }\n\n private readConnectionProtocol(bs: BitStream): ConnectionProtocolState {\n const lastSeqRecvdAtSend: number[] = [];\n for (let i = 0; i < 32; i++) {\n lastSeqRecvdAtSend.push(bs.readU32());\n }\n const lastSeqRecvd = bs.readU32();\n const highestAckedSeq = bs.readU32();\n const lastSendSeq = bs.readU32();\n const ackMask = bs.readU32();\n const connectSequence = bs.readU32();\n const lastRecvAckAck = bs.readU32();\n const connectionEstablished = bs.readBool();\n\n return {\n lastSeqRecvdAtSend,\n lastSeqRecvd,\n highestAckedSeq,\n lastSendSeq,\n ackMask,\n connectSequence,\n lastRecvAckAck,\n connectionEstablished,\n };\n }\n\n private readEventStartBlock(bs: BitStream): {\n nextRecvEventSeq: number;\n events: NetEventInfo[];\n } {\n const nextRecvEventSeq = bs.readU32();\n const events: NetEventInfo[] = [];\n debugInitial(\n \"event block: nextRecvEventSeq=%d bit=%d\",\n nextRecvEventSeq,\n bs.getCurPos(),\n );\n while (bs.readFlag()) {\n const classId = bs.readInt(NetEventClassBitSize) + NetEventClassFirst;\n const dataBitsStart = bs.getCurPos();\n\n // Try to parse the event payload using the registry\n const parserEntry = this.registry.getEventParser(classId);\n let parsedData: Record<string, unknown> | undefined;\n\n if (parserEntry) {\n try {\n const conn = {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: this.ghostTracker,\n getDataBlockParser: (cid: number) =>\n this.registry.getDataBlockParser(cid),\n };\n parsedData = parserEntry.unpack(bs, conn);\n } catch {\n // Can't parse — stop here\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n break;\n }\n } else {\n // No parser — can't advance past this event\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n break;\n }\n\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: bs.getCurPos(),\n parsedData,\n });\n debugInitial(\n \" event classId=%d bits=%d\",\n classId,\n bs.getCurPos() - dataBitsStart,\n );\n }\n return { nextRecvEventSeq, events };\n }\n\n private readGhostStartBlock(\n bs: BitStream,\n dataBlocks: Map<number, ParsedDataBlock>,\n ): { ghostingSequence: number; ghosts: GhostUpdate[] } {\n const ghostingSequence = bs.readU32();\n const ghosts: GhostUpdate[] = [];\n debugInitial(\n \"ghost block: seq=%d bit=%d\",\n ghostingSequence,\n bs.getCurPos(),\n );\n const totalBits = bs.getBuffer().length * 8;\n\n // DataBlock data lookup for ghost parsers that resolve datablock\n // fields during unpack.\n const dataBlockDataMap = new Map<number, Record<string, unknown>>();\n for (const [objectId, db] of dataBlocks) {\n dataBlockDataMap.set(objectId, db.data);\n }\n\n while (bs.readFlag()) {\n if (bs.isError()) break;\n\n const index = bs.readInt(GhostIdBitSize);\n const classId = bs.readInt(NetObjectClassBitSize) + NetObjectClassFirst;\n const updateBitsStart = bs.getCurPos();\n\n // NetConnection::ghostReadStartBlock (FUN_00585220): create the\n // object from the class id, call its unpackUpdate, register it.\n // An unknown class id or a failed registration is \"Invalid packet.\"\n // — the engine stops reading ghosts and the connection is dead.\n // There is no second candidate and no plausibility check.\n const entry = this.registry.getGhostParser(classId);\n if (!entry) {\n debugInitial(\n \" ghost idx=%d classId=%d NO CLASS (stopping at bit=%d)\",\n index,\n classId,\n updateBitsStart,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n failed: true,\n error: `no ghost class bound to classId ${classId}`,\n });\n break;\n }\n\n let parsedData: Record<string, unknown>;\n try {\n parsedData =\n entry.unpackUpdate(bs, true, {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: this.ghostTracker,\n getDataBlockData: (objectId: number) =>\n dataBlockDataMap.get(objectId),\n getDataBlockParser: (cid: number) =>\n this.registry.getDataBlockParser(cid),\n }) ?? {};\n if (bs.isError()) {\n throw new Error(\"ran past the end of the initial block\");\n }\n } catch (e) {\n const error = `${entry.name}: ${e instanceof Error ? e.message : String(e)}`;\n debugInitial(\n \" ghost idx=%d classId=%d parser=%s FAILED at bit=%d: %s\",\n index,\n classId,\n entry.name,\n bs.getCurPos(),\n error,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: bs.getCurPos(),\n failed: true,\n error,\n });\n break;\n }\n\n this.ghostTracker.createGhost(index, classId, entry.name);\n debugInitial(\n \" ghost idx=%d classId=%d parser=%s bits=%d\",\n index,\n classId,\n entry.name,\n bs.getCurPos() - updateBitsStart,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: bs.getCurPos(),\n parsedData,\n });\n }\n\n debugInitial(\n \"ghost loop ended at bit=%d remaining=%d count=%d\",\n bs.getCurPos(),\n totalBits - bs.getCurPos(),\n ghosts.length,\n );\n return { ghostingSequence, ghosts };\n }\n\n /**\n * Parse a raw 64-byte Move struct from a type 2 block.\n *\n * Layout (all little-endian):\n * S32 px, py, pz (12 bytes, offsets 0-11)\n * U32 pyaw, ppitch, proll (12 bytes, offsets 12-23)\n * F32 x, y, z (12 bytes, offsets 24-35)\n * F32 yaw, pitch, roll (12 bytes, offsets 36-47)\n * U32 id (4 bytes, offset 48)\n * U32 sendCount (4 bytes, offset 52)\n * bool freeLook (1 byte, offset 56)\n * bool trigger[6] (6 bytes, offsets 57-62)\n * padding (1 byte, offset 63)\n */\n private readRawMove(data: Uint8Array): Move {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const px = dv.getInt32(0, true);\n const py = dv.getInt32(4, true);\n const pz = dv.getInt32(8, true);\n const pyaw = dv.getUint32(12, true);\n const ppitch = dv.getUint32(16, true);\n const proll = dv.getUint32(20, true);\n const x = dv.getFloat32(24, true);\n const y = dv.getFloat32(28, true);\n const z = dv.getFloat32(32, true);\n const yaw = dv.getFloat32(36, true);\n const pitch = dv.getFloat32(40, true);\n const roll = dv.getFloat32(44, true);\n const id = dv.getUint32(48, true);\n const sendCount = dv.getUint32(52, true);\n const freeLook = data[56] !== 0;\n const trigger: boolean[] = [];\n for (let i = 0; i < MaxTriggerKeys; i++) {\n trigger.push(data[57 + i] !== 0);\n }\n\n return {\n px,\n py,\n pz,\n pyaw,\n ppitch,\n proll,\n x,\n y,\n z,\n yaw,\n pitch,\n roll,\n id,\n sendCount,\n freeLook,\n trigger,\n };\n }\n\n /**\n * Parse an 8-byte info block (type 3).\n * Contains U32 + F32 (observed: always 1 + 120.0).\n */\n private readInfoBlock(data: Uint8Array): InfoBlock {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return {\n // GameConnection::handleRecordedBlock (FUN_005fb170) case 3 reads\n // only byte 0 as firstPerson and the F32 at +4 as the camera FOV.\n firstPerson: data[0] !== 0,\n cameraFov: dv.getFloat32(4, true),\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DemoParser.js","sourceRoot":"","sources":["../src/DemoParser.ts"],"names":[],"mappings":"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","sourcesContent":["import { inflate, Inflate } from \"fflate\";\nimport createDebug from \"debug\";\nimport type { MoveData } from \"./ghostDataTypes.js\";\nimport { BitStream } from \"./BitStream.js\";\nimport { PacketParser } from \"./PacketParser.js\";\nimport type { ClassRegistry, GhostParserEntry } from \"./ClassRegistry.js\";\nimport { createDefaultRegistry } from \"./defaultRegistry.js\";\nimport { GhostTracker, readMove } from \"./GhostManager.js\";\nimport {\n BlockTypePacket,\n BlockTypeSendPacket,\n BlockTypeMove,\n BlockTypeInfo,\n DemoIdentString,\n DemoProtocolVersion,\n MaxTriggerKeys,\n NetEventClassBitSize,\n NetEventClassFirst,\n NetObjectClassBitSize,\n NetObjectClassFirst,\n GhostIdBitSize,\n DataBlockClassFirst,\n DataBlockClassNames,\n SimDBEventObjectIdBits,\n SimDBEventClassIdBits,\n SimDBEventIndexBits,\n SimDBEventTotalBits,\n} from \"./types.js\";\nimport type {\n DemoHeader,\n DemoFile,\n DemoBlock,\n InitialBlockData,\n ConnectionProtocolState,\n DataBlockHeader,\n ParsedDataBlock,\n PathManagerEntry,\n TargetEntry,\n Move,\n InfoBlock,\n GhostUpdate,\n NetEventInfo,\n LoadResult,\n} from \"./types.js\";\n\nconst debug = createDebug(\"t2-demo-parser\");\n/**\n * Sequence numbers assigned to ordered events carried in the demo start\n * block: past every 32-bit sequence, so they stay queued without ever\n * matching `nextRecvEventSeq` (see setupPacketParser).\n */\nconst START_BLOCK_EVENT_SEQ_BASE = 0x1_0000_0000;\n\nconst debugInitial = createDebug(\"t2-demo-parser:initial\");\nconst debugBlocks = createDebug(\"t2-demo-parser:blocks\");\n\n/**\n * Read a U32 count and reject it unless `minBitsPerEntry × count` bits\n * remain: exhausted reads return 0 without throwing, so a corrupt count\n * would otherwise spin allocating until memory ran out.\n */\nfunction readCheckedCount(\n bs: BitStream,\n minBitsPerEntry: number,\n what: string,\n): number {\n const count = bs.readU32();\n if (count > bs.getRemainingBits() / minBitsPerEntry) {\n throw new Error(`Invalid ${what}: ${count}`);\n }\n return count;\n}\n\nexport class DemoParser {\n private buffer: Uint8Array;\n private view: DataView;\n private offset: number;\n private registry: ClassRegistry;\n private ghostTracker: GhostTracker;\n private packetParser: PacketParser;\n // Stepping API state\n private _loaded = false;\n private _header?: DemoHeader;\n private _initialBlock?: InitialBlockData;\n private _decompressedData?: Uint8Array;\n private _decompressedView?: DataView;\n private _blockStreamOffset = 0;\n private _blockCount?: number;\n private _blockCursor = 0;\n private readonly checkpointOwner = {};\n // Incremental mode: the compressed block stream arrives in chunks via\n // push() and is inflated as it goes; nextBlock() treats the end of the\n // decompressed data as a frontier (more may arrive) until finish().\n private readonly _incremental: boolean;\n private _complete = true;\n private _inflator?: Inflate;\n /** The zlib stream announced its own end (final deflate block seen) —\n * later bytes are trailing garbage and further pushes would throw. */\n private _streamEnded = false;\n /** Backing store for the growing decompressed stream (incremental\n * mode). `_decompressedData` is always a length-exact subarray of\n * this, so every existing `.length`-based read stays correct. */\n private _backing?: Uint8Array;\n private _decompressedLength = 0;\n // Buffered-time scan state (see bufferedMoveTicks).\n private _scanOffset = 0;\n private _bufferedMoveTicks = 0;\n\n private readonly _ignoreProtocolVersion: boolean;\n private readonly _haltOnFault: boolean | undefined;\n\n constructor(\n buffer: Uint8Array,\n options?: {\n /** Feed the compressed block stream in chunks via push()/finish(). */\n incremental?: boolean;\n /**\n * Parse demos whose protocol version differs from build 25034's\n * (0x330004). The game itself refuses to play them, and the block\n * formats are not guaranteed to match, so expect faults.\n */\n ignoreProtocolVersion?: boolean;\n /** Passed to PacketParser; see its `haltOnFault` option. */\n haltOnFault?: boolean;\n },\n ) {\n this.buffer = buffer;\n this.view = new DataView(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength,\n );\n this.offset = 0;\n this._incremental = options?.incremental === true;\n this._ignoreProtocolVersion = options?.ignoreProtocolVersion === true;\n this._haltOnFault = options?.haltOnFault;\n // Parser catalogs bound to their deterministic classIds (derived from\n // binary analysis of the Tribes 2 executable).\n this.registry = createDefaultRegistry();\n this.ghostTracker = new GhostTracker();\n this.packetParser = new PacketParser(this.registry, this.ghostTracker);\n }\n\n getRegistry(): ClassRegistry {\n return this.registry;\n }\n\n getGhostTracker(): GhostTracker {\n return this.ghostTracker;\n }\n\n getPacketParser(): PacketParser {\n return this.packetParser;\n }\n\n // --- Stepping API getters ---\n\n get loaded(): boolean {\n return this._loaded;\n }\n\n get header(): DemoHeader {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._header!;\n }\n\n get initialBlock(): InitialBlockData {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._initialBlock!;\n }\n\n get blockCount(): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._blockCount === undefined) {\n // Lazy scan: walk decompressed buffer counting U16 headers\n let count = 0;\n this._walkBlockHeaders(0, () => {\n count++;\n });\n this._blockCount = count;\n }\n return this._blockCount;\n }\n\n /**\n * Walk complete block headers from byte offset `from`, calling `visit`\n * for each; returns the offset of the first incomplete block (or the\n * end of the data).\n */\n private _walkBlockHeaders(\n from: number,\n visit: (type: number, size: number) => void,\n ): number {\n const data = this._decompressedData;\n const view = this._decompressedView;\n if (!data || !view) return from;\n let off = from;\n while (off + 2 <= data.length) {\n const typeSize = view.getUint16(off, true);\n const size = typeSize & 0xfff;\n if (off + 2 + size > data.length) break;\n visit(typeSize >> 12, size);\n off += 2 + size;\n }\n return off;\n }\n\n get blockCursor(): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return this._blockCursor;\n }\n\n // --- Stepping API methods ---\n\n /**\n * Async load: parses header, initial block (DataBlocks, events,\n * ghosts, control object, mission name), and asynchronously decompresses\n * the block stream. No block indexing — blocks are read lazily via nextBlock().\n *\n * Idempotent — second call returns cached result.\n */\n async load(): Promise<LoadResult> {\n if (this._loaded) {\n return {\n header: this._header!,\n initialBlock: this._initialBlock!,\n };\n }\n\n // Phase 1: header + initial block\n const header = this.readHeader();\n debug(\n 'header: \"%s\" version=0x%s length=%dms (%smin) initialBlockSize=%d',\n header.identString,\n header.protocolVersion.toString(16),\n header.demoLengthMs,\n (header.demoLengthMs / 1000 / 60).toFixed(1),\n header.initialBlockSize,\n );\n\n if (this.buffer.length < this.offset + header.initialBlockSize) {\n if (this._incremental) {\n throw new RangeError(\n `incremental parser needs the full initial block up front: have ${\n this.buffer.length - this.offset\n } bytes, need ${header.initialBlockSize}`,\n );\n }\n throw new RangeError(\n `truncated demo: initial block needs ${header.initialBlockSize} bytes, have ${\n this.buffer.length - this.offset\n }`,\n );\n }\n const initialBlockData = this.buffer.subarray(\n this.offset,\n this.offset + header.initialBlockSize,\n );\n const initialBlock = this.readInitialBlock(initialBlockData);\n this.offset += header.initialBlockSize;\n\n if (this._incremental) {\n // Phase 2 (incremental): streaming inflate. Compressed bytes\n // arrive via push(); whatever tail the constructor buffer already\n // holds past the initial block is the first chunk. fflate's\n // Inflate emits decompressed output synchronously during push.\n this._complete = false;\n this._decompressedLength = 0;\n this._backing = new Uint8Array(1 << 20);\n this._decompressedData = this._backing.subarray(0, 0);\n this._decompressedView = new DataView(this._backing.buffer, 0, 0);\n this._inflator = new Inflate((chunk, final) => {\n this._appendDecompressed(chunk);\n if (final) this._streamEnded = true;\n });\n const tail = this.buffer.subarray(this.offset);\n // The prefix buffer has served its purpose (header + initial block\n // are parsed); don't retain arbitrary compressed tail bytes twice.\n if (tail.length > 0) this._inflator.push(tail);\n } else {\n // Phase 2: async decompress block stream\n const compressedData = this.buffer.subarray(this.offset);\n debug(\"compressed block stream: %d bytes\", compressedData.length);\n\n const decompressedData = await new Promise<Uint8Array>(\n (resolve, reject) => {\n inflate(compressedData, (err, data) => {\n if (err) reject(err);\n else resolve(data);\n });\n },\n );\n debug(\"decompressed block stream: %d bytes\", decompressedData.length);\n\n this._decompressedData = decompressedData;\n this._decompressedView = new DataView(\n decompressedData.buffer,\n decompressedData.byteOffset,\n decompressedData.byteLength,\n );\n }\n\n // Phase 3: set up PacketParser with seeded ghost tracker\n this.setupPacketParser(initialBlock);\n\n // Cache results\n this._header = header;\n this._initialBlock = initialBlock;\n this._blockStreamOffset = 0;\n this._blockCursor = 0;\n this._loaded = true;\n\n return { header, initialBlock };\n }\n\n /**\n * Parse just the fixed-size demo header from a byte prefix, without\n * constructing a parser. Throws RangeError when `bytes` is too short —\n * callers streaming a download retry as more data arrives. The\n * returned `byteLength` is where the initial block begins; the block\n * stream begins at `byteLength + header.initialBlockSize`.\n */\n static peekHeader(bytes: Uint8Array): {\n header: DemoHeader;\n byteLength: number;\n } {\n if (bytes.length < 1) throw new RangeError(\"incomplete header\");\n const strLen = bytes[0];\n const byteLength = 1 + strLen + 12;\n if (bytes.length < byteLength) throw new RangeError(\"incomplete header\");\n const identString = new TextDecoder(\"ascii\").decode(\n bytes.subarray(1, 1 + strLen),\n );\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const protocolVersion = view.getUint32(1 + strLen, true);\n const demoLengthMs = view.getUint32(1 + strLen + 4, true);\n const initialBlockSize = view.getUint32(1 + strLen + 8, true);\n return {\n header: { identString, protocolVersion, demoLengthMs, initialBlockSize },\n byteLength,\n };\n }\n\n /**\n * Incremental mode only: feed the next chunk of raw (compressed) block\n * stream bytes as they arrive. Inflation happens synchronously; any\n * blocks completed by this chunk become readable via nextBlock().\n * The chunk is not retained.\n */\n push(chunk: Uint8Array): void {\n if (!this._incremental) throw new Error(\"not an incremental parser\");\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._complete) throw new Error(\"already finished\");\n if (chunk.length === 0 || this._streamEnded) return;\n this._inflator!.push(chunk);\n }\n\n /**\n * Incremental mode only: signal that the download is complete. Flushes\n * the inflator; after this, running out of blocks means the true end\n * of the demo rather than the frontier.\n */\n finish(): void {\n if (!this._incremental) throw new Error(\"not an incremental parser\");\n if (!this._loaded) throw new Error(\"must call load() first\");\n if (this._complete) return;\n if (!this._streamEnded) {\n try {\n this._inflator!.push(new Uint8Array(0), true);\n } catch (err) {\n // A truncated zlib stream: the blocks inflated so far remain\n // valid (nextBlock bounds-checks the tail) — degrade to a\n // shorter demo rather than failing the whole load.\n debug(\"finish(): inflate flush failed: %o\", err);\n }\n }\n this._inflator = undefined;\n this._complete = true;\n // Trim: the doubling backing store can overshoot by up to 2× —\n // release the slack now that the final length is known.\n if (this._backing && this._backing.length > this._decompressedLength) {\n const exact = this._backing.slice(0, this._decompressedLength);\n this._backing = exact;\n this._decompressedData = exact;\n this._decompressedView = new DataView(\n exact.buffer,\n exact.byteOffset,\n exact.byteLength,\n );\n }\n }\n\n /**\n * False only in incremental mode before finish(): nextBlock()\n * returning undefined then means \"frontier — more data may arrive\",\n * not the end of the demo.\n */\n get isComplete(): boolean {\n return this._complete;\n }\n\n /**\n * Bytes of decompressed block stream available so far. Grows during\n * an incremental feed; consumers that latched an \"out of blocks\"\n * state can compare against it to know new data has arrived.\n */\n get decompressedByteLength(): number {\n return this._incremental\n ? this._decompressedLength\n : (this._decompressedData?.length ?? 0);\n }\n\n /**\n * Move-tick blocks in the decompressed stream so far — each is one\n * fixed 32ms simulation tick, so this measures buffered DEMO TIME\n * exactly (compressed bytes don't: quiet stretches pack far denser).\n * Independent of the read cursor; unaffected by reset(). Maintained\n * incrementally as data arrives; a full lazy scan on first access\n * covers the one-shot mode.\n */\n get bufferedMoveTicks(): number {\n this._scanBufferedTicks();\n return this._bufferedMoveTicks;\n }\n\n private _scanBufferedTicks(): void {\n let ticks = this._bufferedMoveTicks;\n this._scanOffset = this._walkBlockHeaders(this._scanOffset, (type) => {\n if (type === BlockTypeMove) ticks++;\n });\n this._bufferedMoveTicks = ticks;\n }\n\n private _appendDecompressed(chunk: Uint8Array): void {\n if (chunk.length === 0) return;\n const needed = this._decompressedLength + chunk.length;\n let backing = this._backing!;\n if (needed > backing.length) {\n let capacity = backing.length;\n while (capacity < needed) capacity *= 2;\n const grown = new Uint8Array(capacity);\n grown.set(backing.subarray(0, this._decompressedLength));\n backing = grown;\n this._backing = grown;\n }\n backing.set(chunk, this._decompressedLength);\n this._decompressedLength = needed;\n // Refresh the exact-length views; subarray shares memory, so this is\n // cheap and keeps every `.length`-based reader (nextBlock,\n // blockCount) correct without touching them.\n this._decompressedData = backing.subarray(0, needed);\n this._decompressedView = new DataView(backing.buffer, 0, needed);\n // The lazily-cached block count no longer covers the new bytes.\n this._blockCount = undefined;\n }\n\n /**\n * Read and parse the next block from the decompressed buffer.\n * Returns the parsed block, or undefined when all blocks are exhausted.\n * Each block is transient — only one in memory at a time.\n * Throws if load() has not been called.\n */\n nextBlock(): DemoBlock | undefined {\n if (!this._loaded) throw new Error(\"must call load() first\");\n const data = this._decompressedData!;\n const view = this._decompressedView!;\n const off = this._blockStreamOffset;\n\n if (off + 2 > data.length) return undefined;\n\n const typeSize = view.getUint16(off, true);\n const type = typeSize >> 12;\n const size = typeSize & 0xfff;\n\n if (off + 2 + size > data.length) {\n debugBlocks(\n \"block %d: size %d would exceed decompressed data (offset=%d remaining=%d), stopping\",\n this._blockCursor,\n size,\n off + 2,\n data.length - off - 2,\n );\n return undefined;\n }\n\n const blockData = data.subarray(off + 2, off + 2 + size);\n this._blockStreamOffset = off + 2 + size;\n\n const block: DemoBlock = {\n index: this._blockCursor,\n type,\n size,\n data: blockData,\n };\n this._blockCursor++;\n\n // PacketParser reports problems through parseFault rather than\n // throwing; anything that does escape is a parser bug, and the raw\n // block plus the error text is kept for diagnosis.\n try {\n if (type === BlockTypePacket) {\n block.parsed = this.packetParser.parsePacket(blockData);\n } else if (type === BlockTypeSendPacket) {\n this.packetParser.onSendPacketTrigger();\n } else if (type === BlockTypeMove && size === 64) {\n block.parsed = this.readRawMove(blockData);\n } else if (type === BlockTypeInfo && size === 8) {\n block.parsed = this.readInfoBlock(blockData);\n }\n } catch (e) {\n block.parseError = e instanceof Error ? e.message : String(e);\n debugBlocks(\n \"block %d (type %d, %d bytes) threw: %s\",\n block.index,\n type,\n size,\n block.parseError,\n );\n }\n\n return block;\n }\n\n /** Capture a block boundary without copying the recording or inflater. */\n createCheckpoint() {\n if (!this._loaded) throw new Error(\"must call load() first\");\n return {\n owner: this.checkpointOwner,\n blockStreamOffset: this._blockStreamOffset,\n blockCursor: this._blockCursor,\n ghosts: structuredClone(this.ghostTracker.getAllGhosts()),\n packetState: this.packetParser.saveState(),\n };\n }\n\n /** Checkpoints belong to this parser, including after its download grows. */\n restoreCheckpoint(\n checkpoint: ReturnType<DemoParser[\"createCheckpoint\"]>,\n ): void {\n if (checkpoint.owner !== this.checkpointOwner)\n throw new Error(\"Checkpoint belongs to a different demo parser\");\n this._blockStreamOffset = checkpoint.blockStreamOffset;\n this._blockCursor = checkpoint.blockCursor;\n this.ghostTracker.clear();\n for (const [index, ghost] of checkpoint.ghosts)\n this.ghostTracker.createGhost(index, ghost.classId, ghost.className);\n this.packetParser.restoreState(checkpoint.packetState);\n }\n\n /**\n * Reset stepping state: resets stream offset and cursor to 0,\n * clears cached block count, and re-initializes the PacketParser\n * with a fresh ghost tracker seeded from the initial block.\n * Throws if load() has not been called.\n */\n reset(): void {\n if (!this._loaded) throw new Error(\"must call load() first\");\n\n this._blockStreamOffset = 0;\n this._blockCursor = 0;\n this._blockCount = undefined;\n\n // Fresh ghost tracker + packet parser\n this.setupPacketParser(this._initialBlock!);\n }\n\n /**\n * Fast-forward through N blocks, processing each but not returning them.\n * Returns the number of blocks actually processed (may be less than count\n * if the stream is exhausted).\n * Throws if load() has not been called.\n */\n processBlocks(count: number): number {\n if (!this._loaded) throw new Error(\"must call load() first\");\n let processed = 0;\n for (let i = 0; i < count; i++) {\n if (!this.nextBlock()) break;\n processed++;\n }\n return processed;\n }\n\n /**\n * Set up a fresh PacketParser seeded from the initial block's ghosts\n * and with the DataBlock data map for ghost parsers. Replaces\n * this.ghostTracker and this.packetParser.\n */\n private setupPacketParser(initialBlock: InitialBlockData): void {\n // Build DataBlock data map (objectId → parsed data)\n const dataBlockDataMap = new Map<number, Record<string, unknown>>();\n for (const [objectId, db] of initialBlock.dataBlocks) {\n dataBlockDataMap.set(objectId, db.data);\n }\n\n // Seed ghost tracker from initial block ghosts\n const gt = new GhostTracker();\n for (const ghost of initialBlock.initialGhosts) {\n if (ghost.type !== \"create\" || ghost.classId === undefined) continue;\n const parserEntry = this.registry.getGhostParser(ghost.classId);\n gt.createGhost(\n ghost.index,\n ghost.classId,\n parserEntry?.name ?? `unknown_${ghost.classId}`,\n );\n }\n\n const pp = new PacketParser(this.registry, gt, {\n dataBlockDataMap,\n connectionProtocolState: initialBlock.connectionState,\n nextRecvEventSeq: initialBlock.nextRecvEventSeq,\n compressionPoint: initialBlock.initialCompressionPoint,\n // NetConnection::eventReadStartBlock (FUN_00583ac0) appends the\n // start block's in-flight ordered events to the wait queue without\n // a sequence number (the field is never written; NetEvent's\n // constructor leaves it uninitialized), so in the engine they can\n // only ever dispatch by accident of heap contents. The deterministic\n // stand-in keeps them queued behind every possible real sequence\n // number, where they neither dispatch nor block dispatch.\n pendingGuaranteedEvents: initialBlock.initialEvents\n .filter((event) => !event.failed)\n .map((event, i) => ({\n absoluteSequenceNumber: START_BLOCK_EVENT_SEQ_BASE + i,\n event,\n })),\n haltOnFault: this._haltOnFault,\n });\n\n this.ghostTracker = gt;\n this.packetParser = pp;\n }\n\n /**\n * Full parse: async load + drain all blocks.\n */\n async parseFullDemo(): Promise<DemoFile> {\n const { header, initialBlock } = await this.load();\n const blocks: DemoBlock[] = [];\n let block: DemoBlock | undefined;\n while ((block = this.nextBlock())) blocks.push(block);\n return { header, initialBlock, blocks };\n }\n\n /**\n * Read and validate the header the way GameConnection's demo playback\n * does: the ident string must match and the protocol version must be\n * the one this build speaks (unless `ignoreProtocolVersion` is set).\n */\n private readHeader(): DemoHeader {\n const { header, byteLength } = DemoParser.peekHeader(\n this.buffer.subarray(this.offset),\n );\n this.offset += byteLength;\n if (header.identString !== DemoIdentString) {\n throw new Error(\n `not a Tribes 2 recording: ident string ${JSON.stringify(header.identString)}`,\n );\n }\n if (header.protocolVersion !== DemoProtocolVersion) {\n const detail = `protocol version 0x${header.protocolVersion.toString(16)} (expected 0x${DemoProtocolVersion.toString(16)})`;\n if (!this._ignoreProtocolVersion) {\n throw new Error(\n `unsupported demo ${detail}; the game rejects it too. Pass { ignoreProtocolVersion: true } to try anyway.`,\n );\n }\n debug(\"parsing demo with unexpected %s\", detail);\n }\n return header;\n }\n\n /** Parse the initial block: DataBlocks, scores, targets, connection state,\n * events, ghosts, control object, and mission name. */\n private readInitialBlock(data: Uint8Array): InitialBlockData {\n const bs = new BitStream(data);\n\n // --- A. Tagged string table (1024 entries) ---\n const taggedStrings = new Map<number, string>();\n for (let i = 0; i < 1024; i++) {\n if (bs.readFlag()) {\n taggedStrings.set(i, bs.readString());\n }\n }\n debugInitial(\n \"after tagged strings bit=%d count=%d\",\n bs.getCurPos(),\n taggedStrings.size,\n );\n\n // --- B.1 U32 datablockCount ---\n const expectedDataBlockCount = bs.readU32();\n\n // --- B.2 DataBlock loop ---\n const dataBlockHeaders: DataBlockHeader[] = [];\n const dataBlocks = new Map<number, ParsedDataBlock>();\n let dataBlockCount = 0;\n\n while (bs.readFlag()) {\n dataBlockCount++;\n const modified = bs.readFlag();\n if (!modified) {\n continue;\n }\n\n const objectId = bs.readInt(SimDBEventObjectIdBits);\n const classId = bs.readInt(SimDBEventClassIdBits) + DataBlockClassFirst;\n const index = bs.readInt(SimDBEventIndexBits);\n const total = bs.readInt(SimDBEventTotalBits);\n const dataBitsStart = bs.getCurPos();\n\n dataBlockHeaders.push({ objectId, classId, index, total, dataBitsStart });\n\n const parserEntry = this.registry.getDataBlockParser(classId);\n if (parserEntry) {\n const parsedData = parserEntry.unpackData(bs);\n dataBlocks.set(objectId, {\n classId,\n className: parserEntry.name,\n objectId,\n data: parsedData,\n });\n } else {\n const className =\n classId >= DataBlockClassFirst &&\n classId < DataBlockClassFirst + DataBlockClassNames.length\n ? DataBlockClassNames[classId - DataBlockClassFirst]\n : `unknown(${classId})`;\n throw new Error(\n `No parser for DataBlock classId ${classId} (${className}) at bit ${dataBitsStart}`,\n );\n }\n }\n\n debug(\n \"all %d/%d DataBlocks parsed (%d payloads), bit position after DataBlocks: %d\",\n dataBlockCount,\n expectedDataBlockCount,\n dataBlocks.size,\n bs.getCurPos(),\n );\n\n // --- B.3 $firstPerson (U8 boolean from GameConnection::writeDemoStartBlock) ---\n const firstPerson = bs.readU8() !== 0;\n // --- B.4 6× U32 connection fields ---\n // @0x8384, @0x8388, @0x83f8, @0x83fc, @0x8400, @0x8434\n const connectionFields: number[] = [];\n for (let i = 0; i < 6; i++) connectionFields.push(bs.readU32());\n\n // --- B.5 16× U32 state array ---\n // @0x83b8 + i*4, i=0..15\n const stateArray: number[] = [];\n for (let i = 0; i < 16; i++) stateArray.push(bs.readU32());\n\n // --- B.6 U32 move count ---\n // A packed move is at least 3 + 18 + 1 + 6 = 28 bits (FUN_00601800).\n const moveCount = readCheckedCount(bs, 28, \"move count\");\n\n // --- B.7 Queued moves × count (FUN_00601800) ---\n const moves: MoveData[] = [];\n for (let i = 0; i < moveCount; i++) {\n moves.push(readMove(bs));\n }\n debugInitial(\n \"after queued moves bit=%d moveCount=%d\",\n bs.getCurPos(),\n moveCount,\n );\n\n // B.8: FUN_005fb130 — clears internal state, no bitstream I/O\n\n // --- B.8 DemoValues ---\n const demoValues = this.readDemoValues(bs);\n debugInitial(\n \"after demo values bit=%d demoValues=%d\",\n bs.getCurPos(),\n demoValues.length,\n );\n\n // --- B.9 Complex TargetManager (FUN_00670660) ---\n const { sensorGroupColors, targets: targetEntries } =\n this.readComplexTargetManager(bs);\n debugInitial(\n \"after complex target manager bit=%d targets=%d sensorGroupColors=%d\",\n bs.getCurPos(),\n targetEntries.length,\n sensorGroupColors.length,\n );\n\n // --- B.10 Parent: NetConnection::readDemoStartBlock (FUN_00588260) ---\n\n // B.10a ConnectionProtocol (FUN_0043d820)\n const connectionState = this.readConnectionProtocol(bs);\n debugInitial(\n \"after connection protocol bit=%d lastRecv=%d highestAck=%d lastSend=%d connected=%s\",\n bs.getCurPos(),\n connectionState.lastSeqRecvd,\n connectionState.highestAckedSeq,\n connectionState.lastSendSeq,\n connectionState.connectionEstablished,\n );\n\n // B.10b RTT, B.10c packet loss\n const roundTripTime = bs.readF32();\n const packetLoss = bs.readF32();\n debugInitial(\n \"after RTT/loss bit=%d rtt=%d loss=%d\",\n bs.getCurPos(),\n roundTripTime,\n packetLoss,\n );\n\n // B.10d PathManager (FUN_00591ce0)\n const pathManager = this.readPathManager(bs);\n debugInitial(\n \"after path manager bit=%d entries=%d\",\n bs.getCurPos(),\n pathManager.length,\n );\n\n // B.10e Notify count only (FUN_00588260).\n // The reader allocates notify nodes in memory but does not consume\n // per-notify records from the bitstream in this phase.\n const notifyCount = bs.readU32();\n // Engine invariant (verified in build 25034): the start block carries\n // one PacketNotify per in-flight packet, i.e. exactly\n // lastSendSeq - highestAckedSeq of them. checkPacketSend\n // (FUN_005877e0) refuses to queue a notify while windowFull\n // (FUN_0043d720: lastSendSeq - highestAckedSeq > 0x1d), and\n // handleNotify (FUN_005874d0) pops the queue head with no null check on\n // every newly acked sequence, so a mismatched seed crashes playback on\n // the first ack. Every Tribes2.exe recording satisfies this exactly.\n const warnings: string[] = [];\n const inFlight =\n (connectionState.lastSendSeq - connectionState.highestAckedSeq) >>> 0;\n if (notifyCount !== inFlight) {\n warnings.push(\n `notify count ${notifyCount} does not match in-flight packets ` +\n `(lastSendSeq ${connectionState.lastSendSeq} - highestAckedSeq ` +\n `${connectionState.highestAckedSeq} = ${inFlight}); Tribes2.exe ` +\n `dereferences an empty notify queue on the first ack`,\n );\n }\n debugInitial(\n \"after notify count bit=%d notifyCount=%d\",\n bs.getCurPos(),\n notifyCount,\n );\n\n // --- B.10f through B.15: events, ghosts, control object, mission ---\n // Uses a temporary ghost tracker for initial-block ghost parsing only.\n const totalBits = bs.getBuffer().length * 8;\n const ibGhostTracker = new GhostTracker();\n const savedGhostTracker = this.ghostTracker;\n this.ghostTracker = ibGhostTracker;\n\n let initialEvents: NetEventInfo[] = [];\n let nextRecvEventSeq = 0;\n let ghostingSequence = 0;\n let initialGhosts: GhostUpdate[] = [];\n let controlObjectGhostIndex = -1;\n let controlObjectData: Record<string, unknown> | undefined;\n let initialCompressionPoint:\n { x: number; y: number; z: number } | undefined;\n let missionName = \"\";\n let missionCRC = 0;\n let phase2Error: string | undefined;\n try {\n debugInitial(\n \"phase2 start bit=%d remaining=%d\",\n bs.getCurPos(),\n totalBits - bs.getCurPos(),\n );\n\n // B.10f Events\n ({ nextRecvEventSeq, events: initialEvents } =\n this.readEventStartBlock(bs));\n debugInitial(\n \"after initial events bit=%d count=%d\",\n bs.getCurPos(),\n initialEvents.length,\n );\n\n // B.10g Ghosts\n const ghostResult = this.readGhostStartBlock(bs, dataBlocks);\n ghostingSequence = ghostResult.ghostingSequence;\n initialGhosts = ghostResult.ghosts;\n const lastInitialGhost = initialGhosts[initialGhosts.length - 1];\n if (lastInitialGhost?.failed) {\n // The engine sets \"Invalid packet.\" here and drops the connection\n // once the start block is done; the fields below are still read,\n // misaligned, exactly as it reads them.\n phase2Error ??= `initial ghost ${lastInitialGhost.index} (classId ${lastInitialGhost.classId}) failed: ${lastInitialGhost.error}`;\n }\n debugInitial(\n \"after initial ghosts bit=%d count=%d seq=%d\",\n bs.getCurPos(),\n initialGhosts.length,\n ghostingSequence,\n );\n\n // B.11 controlObjectGhostIndex\n controlObjectGhostIndex = bs.readS32();\n debugInitial(\n \"after control ghost index bit=%d control=%d\",\n bs.getCurPos(),\n controlObjectGhostIndex,\n );\n\n // B.12 If != -1: controlObject readPacketData\n if (controlObjectGhostIndex !== -1) {\n // The engine resolves the ghost and calls its readPacketData with\n // no fallback; if we cannot, every later read in the initial\n // block (mission name, CRC) would be misaligned, so fail phase 2.\n const ghost = ibGhostTracker.getGhost(controlObjectGhostIndex);\n if (!ghost) {\n throw new Error(\n `control object ghost ${controlObjectGhostIndex} not found among initial ghosts`,\n );\n }\n const parser = this.registry.getGhostParser(ghost.classId);\n if (!parser?.readPacketData) {\n throw new Error(\n `control object ghost ${controlObjectGhostIndex} (${ghost.className}) has no readPacketData parser`,\n );\n }\n // getGhostParser enables the nested vehicle readPacketData when\n // the recorder was piloting at recording start.\n const conn = {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: ibGhostTracker,\n getGhostParser: (classId: number) =>\n this.registry.getGhostParser(classId),\n };\n controlObjectData = parser.readPacketData(bs, conn);\n // The control object's readPacketData establishes the\n // connection's compression point (its position) — carry it\n // into the packet parser seed.\n initialCompressionPoint = conn.compressionPoint;\n debugInitial(\n \"after control readPacketData bit=%d parser=%s\",\n bs.getCurPos(),\n parser.name,\n );\n }\n\n // B.13 $MissionName\n missionName = bs.readString();\n // B.14 mMissionCRC\n missionCRC = bs.readU32();\n // B.15 Simple TargetManager ×2. FUN_006021b0 reads U8 + 4×U32 at the\n // current bit position; the binary does not byte-align here.\n this.readSimpleTargetManager(bs);\n this.readSimpleTargetManager(bs);\n debugInitial(\n 'after sequential tail bit=%d mission=\"%s\" CRC=0x%s',\n bs.getCurPos(),\n missionName,\n missionCRC.toString(16),\n );\n } catch (e) {\n phase2Error = e instanceof Error ? e.message : String(e);\n } finally {\n this.ghostTracker = savedGhostTracker;\n }\n\n const remaining = totalBits - bs.getCurPos();\n const missionPrintableRatio =\n missionName.length > 0\n ? missionName.split(\"\").filter((c) => {\n const code = c.charCodeAt(0);\n return code >= 0x20 && code <= 0x7e;\n }).length / missionName.length\n : 1;\n const phase2Valid =\n missionName.length > 0 &&\n missionPrintableRatio >= 0.8 &&\n phase2Error === undefined;\n\n debug(\n 'initial block: events=%d ghosts=%d ghostingSeq=%d controlObj=%d mission=\"%s\" CRC=0x%s valid=%s%s',\n initialEvents.length,\n initialGhosts.length,\n ghostingSequence,\n controlObjectGhostIndex,\n missionName,\n missionCRC.toString(16),\n phase2Valid,\n phase2Error ? ` error=${phase2Error}` : \"\",\n );\n for (const warning of warnings) {\n debug(\"initial block warning: %s\", warning);\n }\n\n return {\n taggedStrings,\n dataBlockHeaders,\n dataBlockCount,\n dataBlocks,\n firstPerson,\n connectionFields,\n stateArray,\n moves,\n demoValues,\n sensorGroupColors,\n targetEntries,\n connectionState,\n roundTripTime,\n packetLoss,\n pathManager,\n notifyCount,\n nextRecvEventSeq,\n ghostingSequence,\n initialGhosts,\n initialEvents,\n controlObjectGhostIndex,\n controlObjectData,\n initialCompressionPoint,\n missionName,\n missionCRC,\n phase2TrailingBits: remaining,\n phase2Valid,\n phase2Error,\n warnings,\n };\n }\n\n /**\n * Read DemoValues from FUN_005fb5c0 lines 388966-388980.\n * Format: while(readFlag()) { readString(value) }\n * Variable names are derived from index ($DemoValue_0, $DemoValue_1, etc.).\n */\n private readDemoValues(bs: BitStream): string[] {\n const values: string[] = [];\n while (bs.readFlag()) {\n values.push(bs.readString());\n }\n return values;\n }\n\n /**\n * Read Complex TargetManager from FUN_00670660.\n *\n * Phase 1: 4×U8 initial data\n * Phase 2: 32×32 grid — each cell: readFlag + if true: 4×U8\n * Phase 3: 512 target entries with conditional fields\n */\n private readComplexTargetManager(bs: BitStream): {\n sensorGroupColors: import(\"./types.js\").SensorGroupColor[];\n targets: TargetEntry[];\n } {\n // Phase 1: FUN_0043efe0 — read 4 bytes (4×U8)\n bs.readU8();\n bs.readU8();\n bs.readU8();\n bs.readU8();\n\n // Phase 2: 32×32 sensor group color grid (IFF colors).\n // sensorGroupColors[group][targetGroup] = RGBA determines how targetGroup\n // appears to group (e.g., red for enemy, green for friendly).\n const sensorGroupColors: import(\"./types.js\").SensorGroupColor[] = [];\n for (let group = 0; group < 32; group++) {\n for (let targetGroup = 0; targetGroup < 32; targetGroup++) {\n if (bs.readFlag()) {\n sensorGroupColors.push({\n group,\n targetGroup,\n r: bs.readU8(),\n g: bs.readU8(),\n b: bs.readU8(),\n a: bs.readU8(),\n });\n }\n }\n }\n\n // Phase 3: 512 target entries\n const targets: TargetEntry[] = [];\n for (let i = 0; i < 512; i++) {\n if (!bs.readFlag()) continue; // Target not active\n\n const entry: TargetEntry = {\n targetId: i,\n sensorGroup: 0,\n targetData: 0,\n damageLevel: 0,\n };\n\n // Conditional sensor data\n if (bs.readFlag()) {\n entry.sensorData = bs.readU32(); // F32 sensorData\n }\n // Conditional voice map data\n if (bs.readFlag()) {\n entry.voiceMapData = bs.readU32(); // F32 voiceMapData\n }\n // 5 conditional strings: name, skin, skinPref, voice, typeDescription\n if (bs.readFlag()) entry.name = bs.readString();\n if (bs.readFlag()) entry.skin = bs.readString();\n if (bs.readFlag()) entry.skinPref = bs.readString();\n if (bs.readFlag()) entry.voice = bs.readString();\n if (bs.readFlag()) entry.typeDescription = bs.readString();\n\n // Always-read fields\n entry.sensorGroup = bs.readInt(5); // team/type\n entry.targetData = bs.readInt(9); // target data\n\n // Targets >= 32 have additional DataBlock reference\n if (i >= 32) {\n if (bs.readFlag()) {\n entry.dataBlockRef = bs.readInt(11); // DataBlock reference (FUN_00436d10: readClassId)\n }\n // Virtual call notification — no bitstream I/O\n }\n\n // Damage level: readFloat(7) — always read for all active targets\n entry.damageLevel = bs.readFloat(7);\n\n targets.push(entry);\n }\n\n return { sensorGroupColors, targets };\n }\n\n /**\n * Read PathManager from FUN_00591ce0.\n * Decompiled format:\n * - U32 entryCount\n * - repeat entryCount:\n * - U32 entryId\n * - U32 recordCount\n * - repeat recordCount:\n * - U32 field0\n * - U32 field1\n * - U32 field2\n * - U32 auxField\n */\n private readPathManager(bs: BitStream): PathManagerEntry[] {\n const entries: PathManagerEntry[] = [];\n const entryCount = readCheckedCount(bs, 64, \"PathManager entry count\");\n for (let i = 0; i < entryCount; i++) {\n const entryId = bs.readU32();\n const recordCount = readCheckedCount(bs, 128, \"PathManager record count\");\n const records: {\n field0: number;\n field1: number;\n field2: number;\n auxField: number;\n }[] = [];\n for (let j = 0; j < recordCount; j++) {\n records.push({\n field0: bs.readU32(),\n field1: bs.readU32(),\n field2: bs.readU32(),\n auxField: bs.readU32(),\n });\n }\n entries.push({ entryId, records });\n }\n return entries;\n }\n\n /**\n * Read Simple TargetManager from FUN_006021b0.\n * Format: U8 flag + 4×U32 = 136 bits total.\n */\n private readSimpleTargetManager(bs: BitStream): void {\n bs.readU8(); // _read(1) = 8 bits\n bs.readU32(); // 4× _read(4)\n bs.readU32();\n bs.readU32();\n bs.readU32();\n }\n\n private readConnectionProtocol(bs: BitStream): ConnectionProtocolState {\n const lastSeqRecvdAtSend: number[] = [];\n for (let i = 0; i < 32; i++) {\n lastSeqRecvdAtSend.push(bs.readU32());\n }\n const lastSeqRecvd = bs.readU32();\n const highestAckedSeq = bs.readU32();\n const lastSendSeq = bs.readU32();\n const ackMask = bs.readU32();\n const connectSequence = bs.readU32();\n const lastRecvAckAck = bs.readU32();\n const connectionEstablished = bs.readBool();\n\n return {\n lastSeqRecvdAtSend,\n lastSeqRecvd,\n highestAckedSeq,\n lastSendSeq,\n ackMask,\n connectSequence,\n lastRecvAckAck,\n connectionEstablished,\n };\n }\n\n private readEventStartBlock(bs: BitStream): {\n nextRecvEventSeq: number;\n events: NetEventInfo[];\n } {\n const nextRecvEventSeq = bs.readU32();\n const events: NetEventInfo[] = [];\n debugInitial(\n \"event block: nextRecvEventSeq=%d bit=%d\",\n nextRecvEventSeq,\n bs.getCurPos(),\n );\n while (bs.readFlag()) {\n const classId = bs.readInt(NetEventClassBitSize) + NetEventClassFirst;\n const dataBitsStart = bs.getCurPos();\n\n // Try to parse the event payload using the registry\n const parserEntry = this.registry.getEventParser(classId);\n let parsedData: Record<string, unknown> | undefined;\n\n if (parserEntry) {\n try {\n const conn = {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: this.ghostTracker,\n getDataBlockParser: (cid: number) =>\n this.registry.getDataBlockParser(cid),\n };\n parsedData = parserEntry.unpack(bs, conn);\n } catch {\n // Can't parse — stop here\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n break;\n }\n } else {\n // No parser — can't advance past this event\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: dataBitsStart,\n failed: true,\n });\n break;\n }\n\n events.push({\n classId,\n guaranteed: true,\n dataBitsStart,\n dataBitsEnd: bs.getCurPos(),\n parsedData,\n });\n debugInitial(\n \" event classId=%d bits=%d\",\n classId,\n bs.getCurPos() - dataBitsStart,\n );\n }\n return { nextRecvEventSeq, events };\n }\n\n private readGhostStartBlock(\n bs: BitStream,\n dataBlocks: Map<number, ParsedDataBlock>,\n ): { ghostingSequence: number; ghosts: GhostUpdate[] } {\n const ghostingSequence = bs.readU32();\n const ghosts: GhostUpdate[] = [];\n debugInitial(\n \"ghost block: seq=%d bit=%d\",\n ghostingSequence,\n bs.getCurPos(),\n );\n const totalBits = bs.getBuffer().length * 8;\n\n // DataBlock data lookup for ghost parsers that resolve datablock\n // fields during unpack.\n const dataBlockDataMap = new Map<number, Record<string, unknown>>();\n for (const [objectId, db] of dataBlocks) {\n dataBlockDataMap.set(objectId, db.data);\n }\n\n while (bs.readFlag()) {\n if (bs.isError()) break;\n\n const index = bs.readInt(GhostIdBitSize);\n const classId = bs.readInt(NetObjectClassBitSize) + NetObjectClassFirst;\n const updateBitsStart = bs.getCurPos();\n\n // NetConnection::ghostReadStartBlock (FUN_00585220): create the\n // object from the class id, call its unpackUpdate, register it.\n // An unknown class id or a failed registration is \"Invalid packet.\"\n // — the engine stops reading ghosts and the connection is dead.\n // There is no second candidate and no plausibility check.\n const entry = this.registry.getGhostParser(classId);\n if (!entry) {\n debugInitial(\n \" ghost idx=%d classId=%d NO CLASS (stopping at bit=%d)\",\n index,\n classId,\n updateBitsStart,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: updateBitsStart,\n failed: true,\n error: `no ghost class bound to classId ${classId}`,\n });\n break;\n }\n\n let parsedData: Record<string, unknown>;\n try {\n parsedData =\n entry.unpackUpdate(bs, true, {\n compressionPoint: { x: 0, y: 0, z: 0 },\n ghostTracker: this.ghostTracker,\n getDataBlockData: (objectId: number) =>\n dataBlockDataMap.get(objectId),\n getDataBlockParser: (cid: number) =>\n this.registry.getDataBlockParser(cid),\n }) ?? {};\n if (bs.isError()) {\n throw new Error(\"ran past the end of the initial block\");\n }\n } catch (e) {\n const error = `${entry.name}: ${e instanceof Error ? e.message : String(e)}`;\n debugInitial(\n \" ghost idx=%d classId=%d parser=%s FAILED at bit=%d: %s\",\n index,\n classId,\n entry.name,\n bs.getCurPos(),\n error,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: bs.getCurPos(),\n failed: true,\n error,\n });\n break;\n }\n\n this.ghostTracker.createGhost(index, classId, entry.name);\n debugInitial(\n \" ghost idx=%d classId=%d parser=%s bits=%d\",\n index,\n classId,\n entry.name,\n bs.getCurPos() - updateBitsStart,\n );\n ghosts.push({\n index,\n type: \"create\",\n classId,\n updateBitsStart,\n updateBitsEnd: bs.getCurPos(),\n parsedData,\n });\n }\n\n debugInitial(\n \"ghost loop ended at bit=%d remaining=%d count=%d\",\n bs.getCurPos(),\n totalBits - bs.getCurPos(),\n ghosts.length,\n );\n return { ghostingSequence, ghosts };\n }\n\n /**\n * Parse a raw 64-byte Move struct from a type 2 block.\n *\n * Layout (all little-endian):\n * S32 px, py, pz (12 bytes, offsets 0-11)\n * U32 pyaw, ppitch, proll (12 bytes, offsets 12-23)\n * F32 x, y, z (12 bytes, offsets 24-35)\n * F32 yaw, pitch, roll (12 bytes, offsets 36-47)\n * U32 id (4 bytes, offset 48)\n * U32 sendCount (4 bytes, offset 52)\n * bool freeLook (1 byte, offset 56)\n * bool trigger[6] (6 bytes, offsets 57-62)\n * padding (1 byte, offset 63)\n */\n private readRawMove(data: Uint8Array): Move {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const px = dv.getInt32(0, true);\n const py = dv.getInt32(4, true);\n const pz = dv.getInt32(8, true);\n const pyaw = dv.getUint32(12, true);\n const ppitch = dv.getUint32(16, true);\n const proll = dv.getUint32(20, true);\n const x = dv.getFloat32(24, true);\n const y = dv.getFloat32(28, true);\n const z = dv.getFloat32(32, true);\n const yaw = dv.getFloat32(36, true);\n const pitch = dv.getFloat32(40, true);\n const roll = dv.getFloat32(44, true);\n const id = dv.getUint32(48, true);\n const sendCount = dv.getUint32(52, true);\n const freeLook = data[56] !== 0;\n const trigger: boolean[] = [];\n for (let i = 0; i < MaxTriggerKeys; i++) {\n trigger.push(data[57 + i] !== 0);\n }\n\n return {\n px,\n py,\n pz,\n pyaw,\n ppitch,\n proll,\n x,\n y,\n z,\n yaw,\n pitch,\n roll,\n id,\n sendCount,\n freeLook,\n trigger,\n };\n }\n\n /**\n * Parse an 8-byte info block (type 3).\n * Contains U32 + F32 (observed: always 1 + 120.0).\n */\n private readInfoBlock(data: Uint8Array): InfoBlock {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return {\n // GameConnection::handleRecordedBlock (FUN_005fb170) case 3 reads\n // only byte 0 as firstPerson and the F32 at +4 as the camera FOV.\n firstPerson: data[0] !== 0,\n cameraFov: dv.getFloat32(4, true),\n };\n }\n}\n"]}
|
package/dist/PacketParser.d.ts
CHANGED
|
@@ -66,6 +66,43 @@ export declare class PacketParser {
|
|
|
66
66
|
*/
|
|
67
67
|
haltOnFault?: boolean;
|
|
68
68
|
});
|
|
69
|
+
/** Mutable decoding state only; immutable datablock values remain shared. */
|
|
70
|
+
saveState(): {
|
|
71
|
+
dataBlockDataMap: Map<number, ParsedData> | undefined;
|
|
72
|
+
compressionPoint: {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
z: number;
|
|
76
|
+
};
|
|
77
|
+
lastSeqRecvdAtSend: number[];
|
|
78
|
+
lastSeqRecvd: number;
|
|
79
|
+
highestAckedSeq: number;
|
|
80
|
+
lastSendSeq: number;
|
|
81
|
+
recvAckMask: number;
|
|
82
|
+
connectSequence: number;
|
|
83
|
+
lastRecvAckAck: number;
|
|
84
|
+
_connectionEstablished: boolean;
|
|
85
|
+
nextRecvEventSeq: number;
|
|
86
|
+
pendingGuaranteedEvents: {
|
|
87
|
+
absoluteSequenceNumber: number;
|
|
88
|
+
event: NetEventInfo;
|
|
89
|
+
}[];
|
|
90
|
+
_fault: ParseFault | undefined;
|
|
91
|
+
controlObjectParsed: number;
|
|
92
|
+
controlObjectFailed: number;
|
|
93
|
+
eventsParsed: number;
|
|
94
|
+
eventsFailed: number;
|
|
95
|
+
ghostCreatesParsed: number;
|
|
96
|
+
ghostUpdatesParsed: number;
|
|
97
|
+
ghostDeletes: number;
|
|
98
|
+
ghostsFailed: number;
|
|
99
|
+
ghostsTrackerDiverged: number;
|
|
100
|
+
packetsParsed: number;
|
|
101
|
+
protocolRejected: number;
|
|
102
|
+
protocolNoDispatch: number;
|
|
103
|
+
packetsDroppedAfterFault: number;
|
|
104
|
+
};
|
|
105
|
+
restoreState(state: ReturnType<PacketParser["saveState"]>): void;
|
|
69
106
|
getCompressionPoint(): {
|
|
70
107
|
x: number;
|
|
71
108
|
y: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PacketParser.d.ts","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,uBAAuB,EAIvB,UAAU,EACV,UAAU,EACV,YAAY,EAEb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,aAAa,EAEb,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAStD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,gBAAgB,CAAC,CAA0B;IACnD,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,uBAAuB,CAGvB;IACR,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,MAAM,CAAC,CAAa;IAG5B,mBAAmB,SAAK;IACxB,mBAAmB,SAAK;IACxB,YAAY,SAAK;IACjB,YAAY,SAAK;IACjB,kBAAkB,SAAK;IACvB,kBAAkB,SAAK;IACvB,YAAY,SAAK;IACjB,YAAY,SAAK;IACjB;;;oDAGgD;IAChD,qBAAqB,SAAK;IAC1B,aAAa,SAAK;IAClB,gBAAgB,SAAK;IACrB,kBAAkB,SAAK;IACvB,4DAA4D;IAC5D,wBAAwB,SAAK;gBAG3B,QAAQ,EAAE,aAAa,EACvB,YAAY,EAAE,YAAY,EAC1B,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC3C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;QAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,gBAAgB,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACvD,uBAAuB,CAAC,EAAE,KAAK,CAAC;YAC9B,sBAAsB,EAAE,MAAM,CAAC;YAC/B,KAAK,EAAE,YAAY,CAAC;SACrB,CAAC,CAAC;QACH;;;;;WAKG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB;IAsBH,mBAAmB,IAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;IAI1D,+DAA+D;IAC/D,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS;IAIlE;;;;;OAKG;IACH,IAAI,KAAK,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,oBAAoB;IAI5B,0BAA0B,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI;IAchE;;;;;;OAMG;IACH,0BAA0B,IAAI,uBAAuB;IAarD,mBAAmB,IAAI,MAAM;IAI7B,0BAA0B,IAAI,KAAK,CAAC;QAClC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,KAAK,EAAE,YAAY,CAAC;KACrB,CAAC;IAIF;;;OAGG;IACH,mBAAmB,IAAI,IAAI;IAK3B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA6D3B,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU;
|
|
1
|
+
{"version":3,"file":"PacketParser.d.ts","sourceRoot":"","sources":["../src/PacketParser.ts"],"names":[],"mappings":"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"}
|
package/dist/PacketParser.js
CHANGED
|
@@ -71,6 +71,48 @@ export class PacketParser {
|
|
|
71
71
|
.sort((a, b) => a.absoluteSequenceNumber - b.absoluteSequenceNumber);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
/** Mutable decoding state only; immutable datablock values remain shared. */
|
|
75
|
+
saveState() {
|
|
76
|
+
return {
|
|
77
|
+
...structuredClone({
|
|
78
|
+
compressionPoint: this.compressionPoint,
|
|
79
|
+
lastSeqRecvdAtSend: this.lastSeqRecvdAtSend,
|
|
80
|
+
lastSeqRecvd: this.lastSeqRecvd,
|
|
81
|
+
highestAckedSeq: this.highestAckedSeq,
|
|
82
|
+
lastSendSeq: this.lastSendSeq,
|
|
83
|
+
recvAckMask: this.recvAckMask,
|
|
84
|
+
connectSequence: this.connectSequence,
|
|
85
|
+
lastRecvAckAck: this.lastRecvAckAck,
|
|
86
|
+
_connectionEstablished: this._connectionEstablished,
|
|
87
|
+
nextRecvEventSeq: this.nextRecvEventSeq,
|
|
88
|
+
pendingGuaranteedEvents: this.pendingGuaranteedEvents,
|
|
89
|
+
_fault: this._fault,
|
|
90
|
+
controlObjectParsed: this.controlObjectParsed,
|
|
91
|
+
controlObjectFailed: this.controlObjectFailed,
|
|
92
|
+
eventsParsed: this.eventsParsed,
|
|
93
|
+
eventsFailed: this.eventsFailed,
|
|
94
|
+
ghostCreatesParsed: this.ghostCreatesParsed,
|
|
95
|
+
ghostUpdatesParsed: this.ghostUpdatesParsed,
|
|
96
|
+
ghostDeletes: this.ghostDeletes,
|
|
97
|
+
ghostsFailed: this.ghostsFailed,
|
|
98
|
+
ghostsTrackerDiverged: this.ghostsTrackerDiverged,
|
|
99
|
+
packetsParsed: this.packetsParsed,
|
|
100
|
+
protocolRejected: this.protocolRejected,
|
|
101
|
+
protocolNoDispatch: this.protocolNoDispatch,
|
|
102
|
+
packetsDroppedAfterFault: this.packetsDroppedAfterFault,
|
|
103
|
+
}),
|
|
104
|
+
dataBlockDataMap: this.dataBlockDataMap
|
|
105
|
+
? new Map(this.dataBlockDataMap)
|
|
106
|
+
: undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
restoreState(state) {
|
|
110
|
+
const { dataBlockDataMap, ...mutable } = state;
|
|
111
|
+
Object.assign(this, structuredClone(mutable));
|
|
112
|
+
this.dataBlockDataMap = dataBlockDataMap
|
|
113
|
+
? new Map(dataBlockDataMap)
|
|
114
|
+
: undefined;
|
|
115
|
+
}
|
|
74
116
|
getCompressionPoint() {
|
|
75
117
|
return { ...this.compressionPoint };
|
|
76
118
|
}
|
|
@@ -269,7 +311,9 @@ export class PacketParser {
|
|
|
269
311
|
if (!gameStateComplete) {
|
|
270
312
|
parseFault = {
|
|
271
313
|
stage: "gameState",
|
|
272
|
-
message: `control object ghost ${gameState.controlObjectGhostIndex} could not be read${gameState.controlObjectError
|
|
314
|
+
message: `control object ghost ${gameState.controlObjectGhostIndex} could not be read${gameState.controlObjectError
|
|
315
|
+
? `: ${gameState.controlObjectError}`
|
|
316
|
+
: ""}`,
|
|
273
317
|
};
|
|
274
318
|
}
|
|
275
319
|
else if (!eventsComplete) {
|
|
@@ -282,7 +326,8 @@ export class PacketParser {
|
|
|
282
326
|
parseFault = {
|
|
283
327
|
stage: "ghost",
|
|
284
328
|
message: `ghost ${lastGhost.index} (class ${lastGhost.classId}, ${lastGhost.classId !== undefined
|
|
285
|
-
? (this.registry.getGhostParser(lastGhost.classId)?.name ??
|
|
329
|
+
? (this.registry.getGhostParser(lastGhost.classId)?.name ??
|
|
330
|
+
"unbound")
|
|
286
331
|
: "unknown"}) ${lastGhost.type} failed to parse: ${lastGhost.error ?? "unknown error"}`,
|
|
287
332
|
};
|
|
288
333
|
}
|
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\";\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"]}
|
|
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 /** Mutable decoding state only; immutable datablock values remain shared. */\n saveState() {\n return {\n ...structuredClone({\n compressionPoint: this.compressionPoint,\n lastSeqRecvdAtSend: this.lastSeqRecvdAtSend,\n lastSeqRecvd: this.lastSeqRecvd,\n highestAckedSeq: this.highestAckedSeq,\n lastSendSeq: this.lastSendSeq,\n recvAckMask: this.recvAckMask,\n connectSequence: this.connectSequence,\n lastRecvAckAck: this.lastRecvAckAck,\n _connectionEstablished: this._connectionEstablished,\n nextRecvEventSeq: this.nextRecvEventSeq,\n pendingGuaranteedEvents: this.pendingGuaranteedEvents,\n _fault: this._fault,\n controlObjectParsed: this.controlObjectParsed,\n controlObjectFailed: this.controlObjectFailed,\n eventsParsed: this.eventsParsed,\n eventsFailed: this.eventsFailed,\n ghostCreatesParsed: this.ghostCreatesParsed,\n ghostUpdatesParsed: this.ghostUpdatesParsed,\n ghostDeletes: this.ghostDeletes,\n ghostsFailed: this.ghostsFailed,\n ghostsTrackerDiverged: this.ghostsTrackerDiverged,\n packetsParsed: this.packetsParsed,\n protocolRejected: this.protocolRejected,\n protocolNoDispatch: this.protocolNoDispatch,\n packetsDroppedAfterFault: this.packetsDroppedAfterFault,\n }),\n dataBlockDataMap: this.dataBlockDataMap\n ? new Map(this.dataBlockDataMap)\n : undefined,\n };\n }\n\n restoreState(state: ReturnType<PacketParser[\"saveState\"]>): void {\n const { dataBlockDataMap, ...mutable } = state;\n Object.assign(this, structuredClone(mutable));\n this.dataBlockDataMap = dataBlockDataMap\n ? new Map(dataBlockDataMap)\n : undefined;\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\n ? `: ${gameState.controlObjectError}`\n : \"\"\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 ??\n \"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"]}
|