t2-demo-parser 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -7
- package/dist/BitStream.d.ts +14 -3
- package/dist/BitStream.d.ts.map +1 -1
- package/dist/BitStream.js +28 -6
- package/dist/BitStream.js.map +1 -1
- package/dist/BitWriter.d.ts +29 -0
- package/dist/BitWriter.d.ts.map +1 -0
- package/dist/BitWriter.js +76 -0
- package/dist/BitWriter.js.map +1 -0
- package/dist/ClassRegistry.d.ts +23 -28
- package/dist/ClassRegistry.d.ts.map +1 -1
- package/dist/ClassRegistry.js +75 -84
- package/dist/ClassRegistry.js.map +1 -1
- package/dist/DataBlockParsers.d.ts.map +1 -1
- package/dist/DataBlockParsers.js +51 -76
- package/dist/DataBlockParsers.js.map +1 -1
- package/dist/DemoParser.d.ts +86 -23
- package/dist/DemoParser.d.ts.map +1 -1
- package/dist/DemoParser.js +409 -264
- package/dist/DemoParser.js.map +1 -1
- package/dist/EventParsers.d.ts.map +1 -1
- package/dist/EventParsers.js +87 -58
- package/dist/EventParsers.js.map +1 -1
- package/dist/GhostManager.d.ts +7 -1
- package/dist/GhostManager.d.ts.map +1 -1
- package/dist/GhostManager.js +231 -146
- package/dist/GhostManager.js.map +1 -1
- package/dist/HuffmanProcessor.d.ts +15 -0
- package/dist/HuffmanProcessor.d.ts.map +1 -1
- package/dist/HuffmanProcessor.js +45 -0
- package/dist/HuffmanProcessor.js.map +1 -1
- package/dist/LiveParser.d.ts +20 -1
- package/dist/LiveParser.d.ts.map +1 -1
- package/dist/LiveParser.js +31 -12
- package/dist/LiveParser.js.map +1 -1
- package/dist/PacketParser.d.ts +22 -2
- package/dist/PacketParser.d.ts.map +1 -1
- package/dist/PacketParser.js +111 -48
- package/dist/PacketParser.js.map +1 -1
- package/dist/Timeline.d.ts +5 -2
- package/dist/Timeline.d.ts.map +1 -1
- package/dist/Timeline.js +25 -12
- package/dist/Timeline.js.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/dataBlockDataTypes.d.ts +111 -112
- package/dist/dataBlockDataTypes.d.ts.map +1 -1
- package/dist/dataBlockDataTypes.js.map +1 -1
- package/dist/defaultRegistry.d.ts +9 -0
- package/dist/defaultRegistry.d.ts.map +1 -0
- package/dist/defaultRegistry.js +43 -0
- package/dist/defaultRegistry.js.map +1 -0
- package/dist/eventDataTypes.d.ts +74 -72
- package/dist/eventDataTypes.d.ts.map +1 -1
- package/dist/eventDataTypes.js.map +1 -1
- package/dist/ghostDataTypes.d.ts +125 -131
- package/dist/ghostDataTypes.d.ts.map +1 -1
- package/dist/ghostDataTypes.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +51 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -1
- package/dist/BitStream.test.d.ts +0 -2
- package/dist/BitStream.test.d.ts.map +0 -1
- package/dist/BitStream.test.js +0 -419
- package/dist/BitStream.test.js.map +0 -1
- package/dist/ClassRegistry.test.d.ts +0 -2
- package/dist/ClassRegistry.test.d.ts.map +0 -1
- package/dist/ClassRegistry.test.js +0 -83
- package/dist/ClassRegistry.test.js.map +0 -1
- package/dist/DataBlockParsers.test.d.ts +0 -2
- package/dist/DataBlockParsers.test.d.ts.map +0 -1
- package/dist/DataBlockParsers.test.js +0 -294
- package/dist/DataBlockParsers.test.js.map +0 -1
- package/dist/DemoParser.test.d.ts +0 -2
- package/dist/DemoParser.test.d.ts.map +0 -1
- package/dist/DemoParser.test.js +0 -472
- package/dist/DemoParser.test.js.map +0 -1
- package/dist/GhostStateAccumulator.test.d.ts +0 -2
- package/dist/GhostStateAccumulator.test.d.ts.map +0 -1
- package/dist/GhostStateAccumulator.test.js +0 -201
- package/dist/GhostStateAccumulator.test.js.map +0 -1
- package/dist/GhostTracker.test.d.ts +0 -2
- package/dist/GhostTracker.test.d.ts.map +0 -1
- package/dist/GhostTracker.test.js +0 -64
- package/dist/GhostTracker.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -11,6 +11,8 @@ thread responsive: in browsers, decompression runs in a Web Worker via
|
|
|
11
11
|
[fflate](https://github.com/101arrowz/fflate), and blocks are parsed lazily
|
|
12
12
|
one at a time.
|
|
13
13
|
|
|
14
|
+
Requires Node.js 18 or newer (or any modern browser).
|
|
15
|
+
|
|
14
16
|
## Quick start
|
|
15
17
|
|
|
16
18
|
```typescript
|
|
@@ -75,7 +77,11 @@ All parser bindings (53 ghost classes, 54 DataBlock classes, 26 event classes)
|
|
|
75
77
|
are set up deterministically in the constructor.
|
|
76
78
|
|
|
77
79
|
```typescript
|
|
78
|
-
const parser = new DemoParser(buffer: Uint8Array
|
|
80
|
+
const parser = new DemoParser(buffer: Uint8Array, options?: {
|
|
81
|
+
incremental?: boolean; // feed the block stream via push()/finish()
|
|
82
|
+
ignoreProtocolVersion?: boolean; // see below
|
|
83
|
+
haltOnFault?: boolean; // passed to PacketParser (default true)
|
|
84
|
+
});
|
|
79
85
|
```
|
|
80
86
|
|
|
81
87
|
#### `async load(): Promise<LoadResult>`
|
|
@@ -83,6 +89,13 @@ const parser = new DemoParser(buffer: Uint8Array);
|
|
|
83
89
|
Parse the header and initial block, then asynchronously decompress the block
|
|
84
90
|
stream. Does **not** parse any blocks — use `nextBlock()` to consume them.
|
|
85
91
|
|
|
92
|
+
The header is validated the way the game's demo playback validates it: the
|
|
93
|
+
ident string must be `"Tribes2 Recording"` and the protocol version must be
|
|
94
|
+
`0x330004` (build 25034), otherwise `load()` throws. The game refuses to play
|
|
95
|
+
other versions too, and their block formats are not guaranteed to match; pass
|
|
96
|
+
`{ ignoreProtocolVersion: true }` to try anyway. A buffer too short to hold
|
|
97
|
+
the initial block throws a `RangeError`.
|
|
98
|
+
|
|
86
99
|
Idempotent: calling `load()` again returns the cached result.
|
|
87
100
|
|
|
88
101
|
```typescript
|
|
@@ -96,6 +109,9 @@ interface LoadResult {
|
|
|
96
109
|
|
|
97
110
|
Read and parse the next block from the decompressed stream. Returns `undefined`
|
|
98
111
|
when the stream is exhausted. Each call advances `blockCursor` by one.
|
|
112
|
+
Packets that the parser cannot fully consume are reported through
|
|
113
|
+
`PacketData.parseFault` (see `PacketParser` below); a block whose decoder
|
|
114
|
+
threw carries the message in `DemoBlock.parseError`.
|
|
99
115
|
|
|
100
116
|
Blocks are transient — only one exists in memory at a time (previous blocks are
|
|
101
117
|
eligible for GC unless you retain a reference).
|
|
@@ -208,6 +224,9 @@ interface InitialBlockData {
|
|
|
208
224
|
phase2Valid?: boolean;
|
|
209
225
|
phase2Error?: string;
|
|
210
226
|
phase2TrailingBits?: number;
|
|
227
|
+
// Seeded state Tribes2.exe would crash on during playback (always empty
|
|
228
|
+
// for recordings made by the game; see freshConnectionProtocolState).
|
|
229
|
+
warnings: string[];
|
|
211
230
|
}
|
|
212
231
|
```
|
|
213
232
|
|
|
@@ -225,6 +244,14 @@ interface DemoBlock {
|
|
|
225
244
|
size: number; // Payload size in bytes
|
|
226
245
|
data: Uint8Array; // Raw payload
|
|
227
246
|
parsed?: PacketData | Move | InfoBlock;
|
|
247
|
+
parseError?: string; // Set if decoding threw (a parser bug)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Type 3 block: written after every received packet, replayed through
|
|
251
|
+
// setControlCameraFov on playback.
|
|
252
|
+
interface InfoBlock {
|
|
253
|
+
firstPerson: boolean; // $firstPerson (byte 0; the other 3 bytes are garbage)
|
|
254
|
+
cameraFov: number; // control camera FOV in degrees
|
|
228
255
|
}
|
|
229
256
|
```
|
|
230
257
|
|
|
@@ -241,6 +268,11 @@ interface PacketData {
|
|
|
241
268
|
gameState: GameState;
|
|
242
269
|
events: NetEventInfo[];
|
|
243
270
|
ghosts: GhostUpdate[];
|
|
271
|
+
/** Set when any section failed to parse; the ghost tracker and
|
|
272
|
+
* event sequence no longer mirror the server, so a live consumer
|
|
273
|
+
* must re-sync from a fresh connection (the engine disconnects).
|
|
274
|
+
* The message names the parser and the underlying error. */
|
|
275
|
+
parseFault?: { stage: "gameState" | "event" | "ghost"; message: string };
|
|
244
276
|
}
|
|
245
277
|
```
|
|
246
278
|
|
|
@@ -259,6 +291,7 @@ interface GameState {
|
|
|
259
291
|
controlObjectDataStart?: number; // Bit offsets of the control object
|
|
260
292
|
controlObjectDataEnd?: number; // update within the packet
|
|
261
293
|
controlObjectData?: Record<string, unknown>;
|
|
294
|
+
controlObjectError?: string; // Why readPacketData could not be applied
|
|
262
295
|
compressionPoint?: { x: number; y: number; z: number };
|
|
263
296
|
cameraFov?: number;
|
|
264
297
|
targetVisibility?: { index: number; mask: number }[];
|
|
@@ -286,6 +319,8 @@ interface GhostUpdate {
|
|
|
286
319
|
updateBitsStart: number;
|
|
287
320
|
updateBitsEnd: number;
|
|
288
321
|
parsedData?: Record<string, unknown>; // Class-specific parsed fields
|
|
322
|
+
failed?: boolean; // Could not be parsed; the ghost section stops here
|
|
323
|
+
error?: string; // Parser name and error text when failed
|
|
289
324
|
}
|
|
290
325
|
```
|
|
291
326
|
|
|
@@ -304,6 +339,7 @@ interface NetEventInfo {
|
|
|
304
339
|
parsedData?: Record<string, unknown>;
|
|
305
340
|
failed?: boolean; // Event could not be parsed; stream
|
|
306
341
|
// position after it is unreliable
|
|
342
|
+
error?: string; // Parser name and error text when failed
|
|
307
343
|
}
|
|
308
344
|
```
|
|
309
345
|
|
|
@@ -357,8 +393,11 @@ interface ParsedDataBlock {
|
|
|
357
393
|
|
|
358
394
|
#### `buildTimeline(demo, registry): DemoTimeline`
|
|
359
395
|
|
|
360
|
-
Extract a time-indexed timeline from a fully parsed `DemoFile`.
|
|
361
|
-
|
|
396
|
+
Extract a time-indexed timeline from a fully parsed `DemoFile`. Every Move
|
|
397
|
+
block is one 32ms simulation tick (`MoveTickMs`), so a packet's timestamp is
|
|
398
|
+
the number of Move blocks before it × 32ms — exact demo time, the same clock
|
|
399
|
+
as `DemoParser.bufferedMoveTicks` and the seek guide below. `tickIntervalMs`
|
|
400
|
+
is always `MoveTickMs`.
|
|
362
401
|
|
|
363
402
|
```typescript
|
|
364
403
|
import { buildTimeline } from "t2-demo-parser";
|
|
@@ -477,6 +516,27 @@ Available via `parser.getPacketParser()`. Exposes parse statistics.
|
|
|
477
516
|
| `controlObjectFailed` | `number` | Control object updates that failed. |
|
|
478
517
|
| `protocolRejected` | `number` | Packets rejected by the dnet protocol window. |
|
|
479
518
|
| `protocolNoDispatch` | `number` | Packets accepted but not dispatched (duplicates/out-of-window). |
|
|
519
|
+
| `packetsDroppedAfterFault` | `number` | Packets returned empty because the parser had halted. |
|
|
520
|
+
|
|
521
|
+
#### Faults and halting
|
|
522
|
+
|
|
523
|
+
The engine drops the connection on any packet it cannot read ("Invalid
|
|
524
|
+
packet"). `PacketParser` mirrors that: the first packet whose game state,
|
|
525
|
+
events, or ghosts fail to parse gets a `parseFault`, and by default the
|
|
526
|
+
parser **halts** — every later `parsePacket()` returns an empty `PacketData`
|
|
527
|
+
carrying the same fault and touches no state, because it would otherwise be
|
|
528
|
+
parsing against ghost and event state that no longer mirrors the server.
|
|
529
|
+
|
|
530
|
+
| Member | Description |
|
|
531
|
+
| ----------- | ------------------------------------------------------------------- |
|
|
532
|
+
| `fault` | The first `ParseFault`, or `undefined`. |
|
|
533
|
+
| `faulted` | `true` once a fault has been recorded. |
|
|
534
|
+
|
|
535
|
+
Pass `haltOnFault: false` (to `new PacketParser`, `new DemoParser`, or
|
|
536
|
+
`createLiveParser`) to keep parsing regardless; each later packet still
|
|
537
|
+
reports its own `parseFault` when it has one. To continue after a fault,
|
|
538
|
+
build a fresh parser: `DemoParser.reset()`, or a new `createLiveParser`
|
|
539
|
+
seeded from a known-good exported state.
|
|
480
540
|
|
|
481
541
|
#### State export (for seeding another parser)
|
|
482
542
|
|
|
@@ -490,8 +550,8 @@ late-joiner catch-up in live streaming.
|
|
|
490
550
|
| `getConnectionProtocolState()` | `ConnectionProtocolState` (dnet sequence window) |
|
|
491
551
|
| `getNextRecvEventSeq()` | `number` |
|
|
492
552
|
| `getPendingGuaranteedEvents()` | Out-of-order guaranteed events awaiting dispatch |
|
|
493
|
-
| `getCompressionPoint()` | `{ x, y, z }`
|
|
494
|
-
| `getDataBlockDataMap()` | `
|
|
553
|
+
| `getCompressionPoint()` | `{ x, y, z }` (a copy) |
|
|
554
|
+
| `getDataBlockDataMap()` | `ReadonlyMap<number, ParsedData> \| undefined` |
|
|
495
555
|
| `setConnectionProtocolState(state)` | — (also a constructor option) |
|
|
496
556
|
|
|
497
557
|
---
|
|
@@ -533,6 +593,7 @@ interface LiveParserSeed {
|
|
|
533
593
|
absoluteSequenceNumber: number;
|
|
534
594
|
event: NetEventInfo;
|
|
535
595
|
}>;
|
|
596
|
+
haltOnFault?: boolean; // default true, see PacketParser
|
|
536
597
|
}
|
|
537
598
|
```
|
|
538
599
|
|
|
@@ -545,6 +606,13 @@ sequences the observer didn't send. Intended for the first packets of a
|
|
|
545
606
|
connection; to attach mid-stream, seed `connectionProtocolState` from the
|
|
546
607
|
exporting parser instead.
|
|
547
608
|
|
|
609
|
+
Parser-only: never write this state into a `.rec` initial block. The game
|
|
610
|
+
requires the start block's notify count to equal
|
|
611
|
+
`lastSendSeq - highestAckedSeq` and treats a difference above 0x1d as a
|
|
612
|
+
full send window, so a demo seeded this way crashes Tribes2.exe on the
|
|
613
|
+
first acknowledged packet. `DemoParser` reports such files in
|
|
614
|
+
`initialBlock.warnings`.
|
|
615
|
+
|
|
548
616
|
```typescript
|
|
549
617
|
import { createLiveParser, passiveObserverProtocolState } from "t2-demo-parser";
|
|
550
618
|
|
|
@@ -553,6 +621,14 @@ const { packetParser } = createLiveParser();
|
|
|
553
621
|
packetParser.setConnectionProtocolState(passiveObserverProtocolState(data[0]));
|
|
554
622
|
```
|
|
555
623
|
|
|
624
|
+
### `freshConnectionProtocolState(connectSequence): ConnectionProtocolState`
|
|
625
|
+
|
|
626
|
+
The state of a connection that has not yet exchanged a sequenced packet:
|
|
627
|
+
everything zero except the connect sequence, with `connectionEstablished`
|
|
628
|
+
set. This is what a recording that starts at connect time must seed
|
|
629
|
+
(with a notify count of 0), writing one SendPacket marker per packet the
|
|
630
|
+
recorder actually sends, before the received packet that acks it.
|
|
631
|
+
|
|
556
632
|
---
|
|
557
633
|
|
|
558
634
|
### `GhostStateAccumulator`
|
|
@@ -596,6 +672,42 @@ const value = bs.readInt(10);
|
|
|
596
672
|
const str = bs.readString();
|
|
597
673
|
```
|
|
598
674
|
|
|
675
|
+
Reads never throw on short data: a read that would pass the end of the
|
|
676
|
+
buffer returns zero (or an empty buffer), leaves the cursor in place, and
|
|
677
|
+
sets the error flag, which `isError()` reports — the same contract as the
|
|
678
|
+
engine's BitStream. `readInt` throws a `RangeError` for bit counts above 32.
|
|
679
|
+
Strings are decoded byte-per-character (Latin-1); Tribes 2 tagged strings
|
|
680
|
+
begin with `"\x01"`.
|
|
681
|
+
|
|
682
|
+
### `BitWriter`
|
|
683
|
+
|
|
684
|
+
The matching LSB-first bit packer, for building test vectors and synthetic
|
|
685
|
+
packets: `writeFlag`, `writeInt`, `writeSignedInt`, `writeU8/U32/S32`,
|
|
686
|
+
`writeF32`, `writeFloat`, `writeBytes`, and `writeString` (Huffman, exactly
|
|
687
|
+
as the engine's `writeString`). `finish()` returns the packed `Uint8Array`.
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
import { BitWriter, BitStream } from "t2-demo-parser";
|
|
691
|
+
|
|
692
|
+
const bytes = new BitWriter().writeFlag(true).writeInt(5, 4).writeString("hi").finish();
|
|
693
|
+
const bs = new BitStream(bytes); // readFlag() → true, readInt(4) → 5, readString() → "hi"
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### `ClassRegistry` / `createDefaultRegistry()`
|
|
697
|
+
|
|
698
|
+
`createDefaultRegistry()` returns a registry with every built-in parser bound
|
|
699
|
+
to its deterministic classId — the same setup `DemoParser` and
|
|
700
|
+
`createLiveParser` use. Lookups go both ways:
|
|
701
|
+
|
|
702
|
+
| Method | Returns |
|
|
703
|
+
| --------------------------------------- | -------------------------------- |
|
|
704
|
+
| `getGhostParser(classId)` etc. | Parser entry for a bound classId |
|
|
705
|
+
| `getGhostClassId(name)` etc. | Bound classId for a class name |
|
|
706
|
+
| `getGhostCatalog()` etc. | `ReadonlyMap<name, entry>` |
|
|
707
|
+
| `getGhostBindings()` etc. | `Map<classId, name>` (debug) |
|
|
708
|
+
|
|
709
|
+
The `Event` and `DataBlock` variants of each method exist too.
|
|
710
|
+
|
|
599
711
|
---
|
|
600
712
|
|
|
601
713
|
### `GhostTracker`
|
|
@@ -606,7 +718,7 @@ Tracks the live state of all ghost objects. Available via
|
|
|
606
718
|
```typescript
|
|
607
719
|
const tracker = parser.getGhostTracker();
|
|
608
720
|
const ghost = tracker.getGhost(index); // GhostEntry | undefined
|
|
609
|
-
const all = tracker.getAllGhosts(); //
|
|
721
|
+
const all = tracker.getAllGhosts(); // ReadonlyMap<number, GhostEntry>
|
|
610
722
|
tracker.size(); // Number of active ghosts
|
|
611
723
|
```
|
|
612
724
|
|
|
@@ -614,10 +726,12 @@ tracker.size(); // Number of active ghosts
|
|
|
614
726
|
interface GhostEntry {
|
|
615
727
|
classId: number;
|
|
616
728
|
className: string;
|
|
617
|
-
state: Record<string, unknown>;
|
|
618
729
|
}
|
|
619
730
|
```
|
|
620
731
|
|
|
732
|
+
Accumulated per-ghost state lives in `GhostStateAccumulator`, not in the
|
|
733
|
+
tracker.
|
|
734
|
+
|
|
621
735
|
---
|
|
622
736
|
|
|
623
737
|
### Constants
|
|
@@ -630,6 +744,9 @@ import {
|
|
|
630
744
|
BlockTypeSendPacket, // 1 — send-packet trigger (no data)
|
|
631
745
|
BlockTypeMove, // 2 — 64-byte player input
|
|
632
746
|
BlockTypeInfo, // 3 — 8-byte timing/FOV
|
|
747
|
+
MoveTickMs, // 32 — one Move block per simulation tick
|
|
748
|
+
DemoIdentString, // "Tribes2 Recording"
|
|
749
|
+
DemoProtocolVersion, // 0x330004 (build 25034)
|
|
633
750
|
} from "t2-demo-parser";
|
|
634
751
|
```
|
|
635
752
|
|
|
@@ -886,10 +1003,56 @@ DEBUG=t2-demo-parser:initial npx t2-demo-parser demo.rec
|
|
|
886
1003
|
|
|
887
1004
|
# Just block stream parsing
|
|
888
1005
|
DEBUG=t2-demo-parser:blocks npx t2-demo-parser demo.rec
|
|
1006
|
+
|
|
1007
|
+
# Per-event / per-ghost parse failures and tracker re-creates
|
|
1008
|
+
DEBUG=t2-demo-parser:events,t2-demo-parser:ghosts,t2-demo-parser:ghost-tracker npx t2-demo-parser demo.rec
|
|
889
1009
|
```
|
|
890
1010
|
|
|
1011
|
+
### Known limitations
|
|
1012
|
+
|
|
1013
|
+
- One archived demo (a 2000s-era recording) carries a TerrainBlock
|
|
1014
|
+
`GhostAlwaysObjectEvent` after a mission change whose payload holds 377 more
|
|
1015
|
+
bits than build 25034's `TerrainBlock::unpackUpdate` reads (a shared-prefix
|
|
1016
|
+
string with the terrain's material list, then 91 unidentified bits). Seven
|
|
1017
|
+
other mission-change TerrainBlock events in other demos match the binary
|
|
1018
|
+
exactly, so this is a conditional extension of an unidentified client
|
|
1019
|
+
build. The parser faults cleanly at that packet instead of guessing.
|
|
1020
|
+
- `SimVoiceStreamEvent` follows the binary's layout (which differs from the
|
|
1021
|
+
V12 source), but no available demo contains voice traffic, so it is
|
|
1022
|
+
verified against the disassembly only.
|
|
1023
|
+
|
|
891
1024
|
---
|
|
892
1025
|
|
|
1026
|
+
## Upgrading from 2.x
|
|
1027
|
+
|
|
1028
|
+
Breaking changes in this version:
|
|
1029
|
+
|
|
1030
|
+
- **Halt on fault.** `PacketParser` stops after the first `parseFault`
|
|
1031
|
+
(`haltOnFault: false` restores the old behaviour).
|
|
1032
|
+
- **Header validation.** `DemoParser.load()` throws on a wrong ident string or
|
|
1033
|
+
protocol version (`ignoreProtocolVersion: true` to override).
|
|
1034
|
+
- **Timeline timestamps** come from Move ticks (32ms) instead of an even
|
|
1035
|
+
spread of packets over the demo length; `tickIntervalMs` is now 32.
|
|
1036
|
+
- Removed fields: `GhostEntry.state`, `ConnectionContext.currentGhostIndex`,
|
|
1037
|
+
`SimDataBlockEventData._payloadBitPos` / `_needsClassParser`,
|
|
1038
|
+
`VehicleGhostData._controlledEarlyReturn`, `DebrisDataBlock.minSpinSpeed_dup`
|
|
1039
|
+
/ `maxSpinSpeed_dup` (the second wire copy now lands in `minSpinSpeed` /
|
|
1040
|
+
`maxSpinSpeed`, as on the client). `GhostAlwaysObjectEventData._hasObjectData`
|
|
1041
|
+
is now `hasObjectData`; `DebrisGhostData.objectRef2` is folded into
|
|
1042
|
+
`objectRefs` (three entries); `ShapeBaseDataBlock.jetEffect` is `null`
|
|
1043
|
+
rather than `undefined` when absent.
|
|
1044
|
+
- `SimVoiceStreamEventData` now reflects the binary's wire format
|
|
1045
|
+
(`sequence`, `codecId`, `streamId`, `clientId`, `partial`, `frameCount`,
|
|
1046
|
+
`audioData` or `frames`).
|
|
1047
|
+
- A `SimDataBlockEvent` with no parser (or whose payload fails) now fails the
|
|
1048
|
+
event (and the packet) instead of returning silently misaligned.
|
|
1049
|
+
- Parsed-data types are now type aliases without index signatures; property
|
|
1050
|
+
access on them is checked.
|
|
1051
|
+
- `getAllGhosts()`, `getGhostCatalog()`, and `getDataBlockDataMap()` return
|
|
1052
|
+
read-only maps; `getCompressionPoint()` returns a copy.
|
|
1053
|
+
- `ShapeBase` ghosts' `readPacketData` reads energy + recharge only (it was
|
|
1054
|
+
bound to the Vehicle reader).
|
|
1055
|
+
|
|
893
1056
|
## Supported classes
|
|
894
1057
|
|
|
895
1058
|
### Ghost classes (53)
|
package/dist/BitStream.d.ts
CHANGED
|
@@ -33,9 +33,17 @@ export declare class BitStream {
|
|
|
33
33
|
readFloat(bitCount: number): number;
|
|
34
34
|
/** Read a float normalized to [-1, 1]. */
|
|
35
35
|
readSignedFloat(bitCount: number): number;
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Read a ranged unsigned 32-bit integer. Bit width is
|
|
38
|
+
* getBinLog2(getNextPow2(rangeSize)) as in the engine (FUN_0043f120 /
|
|
39
|
+
* FUN_0043f150): a range of one value reads zero bits.
|
|
40
|
+
*/
|
|
37
41
|
readRangedU32(rangeStart: number, rangeEnd: number): number;
|
|
38
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Read raw bits into a new Uint8Array. Like every other read, an
|
|
44
|
+
* over-length request sets the error flag, leaves the cursor in place,
|
|
45
|
+
* and returns zeroed bytes (the engine's BitStream::readBits).
|
|
46
|
+
*/
|
|
39
47
|
readBitsBuffer(bitCount: number): Uint8Array;
|
|
40
48
|
/** Read N raw bytes. Returns an array of byte values. */
|
|
41
49
|
readBytes(count: number): number[];
|
|
@@ -85,11 +93,14 @@ export declare class BitStream {
|
|
|
85
93
|
/**
|
|
86
94
|
* Read a Huffman-encoded string.
|
|
87
95
|
* Handles the stringBuffer optimization (shared prefix with previous string).
|
|
96
|
+
* Each wire byte becomes one UTF-16 code unit (Latin-1 decoding); Tribes 2
|
|
97
|
+
* strings are not UTF-8, and tagged strings begin with "\x01".
|
|
88
98
|
*/
|
|
89
99
|
readString(): string;
|
|
90
100
|
/** Enable/disable the string buffer for shared-prefix optimization. */
|
|
91
101
|
setStringBuffer(enable: boolean): void;
|
|
92
|
-
/** Skip N bits.
|
|
102
|
+
/** Skip N bits. Sets the error flag (without moving) if that would
|
|
103
|
+
* pass the end of the buffer. */
|
|
93
104
|
skipBits(count: number): void;
|
|
94
105
|
/** Read 3x F32 as a Point3F. */
|
|
95
106
|
readPoint3F(): {
|
package/dist/BitStream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitStream.d.ts","sourceRoot":"","sources":["../src/BitStream.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,YAAY,CAAuB;gBAE/B,IAAI,EAAE,UAAU,EAAE,SAAS,SAAI;IAO3C,SAAS,IAAI,MAAM;IAInB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B,6DAA6D;IAC7D,eAAe,IAAI,MAAM;IAIzB,OAAO,IAAI,OAAO;IAIlB,iDAAiD;IACjD,MAAM,IAAI,OAAO;IAIjB,gBAAgB,IAAI,MAAM;IAI1B,SAAS,IAAI,MAAM;IAInB,sCAAsC;IACtC,QAAQ,IAAI,OAAO;IAWnB;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"BitStream.d.ts","sourceRoot":"","sources":["../src/BitStream.ts"],"names":[],"mappings":"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"}
|
package/dist/BitStream.js
CHANGED
|
@@ -58,6 +58,9 @@ export class BitStream {
|
|
|
58
58
|
readInt(bitCount) {
|
|
59
59
|
if (bitCount === 0)
|
|
60
60
|
return 0;
|
|
61
|
+
if (!(bitCount > 0 && bitCount <= 32)) {
|
|
62
|
+
throw new RangeError(`readInt bitCount out of range: ${bitCount}`);
|
|
63
|
+
}
|
|
61
64
|
if (this.bitNum + bitCount > this.maxReadBitNum) {
|
|
62
65
|
this.error = true;
|
|
63
66
|
return 0;
|
|
@@ -100,24 +103,36 @@ export class BitStream {
|
|
|
100
103
|
}
|
|
101
104
|
/** Read a float normalized to [0, 1]. */
|
|
102
105
|
readFloat(bitCount) {
|
|
103
|
-
return this.readInt(bitCount) / (
|
|
106
|
+
return this.readInt(bitCount) / (2 ** bitCount - 1);
|
|
104
107
|
}
|
|
105
108
|
/** Read a float normalized to [-1, 1]. */
|
|
106
109
|
readSignedFloat(bitCount) {
|
|
107
|
-
return (this.readInt(bitCount) * 2) / (
|
|
110
|
+
return (this.readInt(bitCount) * 2) / (2 ** bitCount - 1) - 1.0;
|
|
108
111
|
}
|
|
109
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Read a ranged unsigned 32-bit integer. Bit width is
|
|
114
|
+
* getBinLog2(getNextPow2(rangeSize)) as in the engine (FUN_0043f120 /
|
|
115
|
+
* FUN_0043f150): a range of one value reads zero bits.
|
|
116
|
+
*/
|
|
110
117
|
readRangedU32(rangeStart, rangeEnd) {
|
|
111
118
|
const rangeSize = rangeEnd - rangeStart + 1;
|
|
112
|
-
const rangeBits = Math.ceil(Math.log2(rangeSize))
|
|
119
|
+
const rangeBits = Math.ceil(Math.log2(rangeSize));
|
|
113
120
|
return this.readInt(rangeBits) + rangeStart;
|
|
114
121
|
}
|
|
115
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* Read raw bits into a new Uint8Array. Like every other read, an
|
|
124
|
+
* over-length request sets the error flag, leaves the cursor in place,
|
|
125
|
+
* and returns zeroed bytes (the engine's BitStream::readBits).
|
|
126
|
+
*/
|
|
116
127
|
readBitsBuffer(bitCount) {
|
|
117
128
|
if (bitCount === 0)
|
|
118
129
|
return new Uint8Array(0);
|
|
119
130
|
const byteCount = (bitCount + 7) >> 3;
|
|
120
131
|
const result = new Uint8Array(byteCount);
|
|
132
|
+
if (bitCount < 0 || this.bitNum + bitCount > this.maxReadBitNum) {
|
|
133
|
+
this.error = true;
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
121
136
|
const startByte = this.bitNum >> 3;
|
|
122
137
|
const downShift = this.bitNum & 0x7;
|
|
123
138
|
const upShift = 8 - downShift;
|
|
@@ -240,6 +255,8 @@ export class BitStream {
|
|
|
240
255
|
/**
|
|
241
256
|
* Read a Huffman-encoded string.
|
|
242
257
|
* Handles the stringBuffer optimization (shared prefix with previous string).
|
|
258
|
+
* Each wire byte becomes one UTF-16 code unit (Latin-1 decoding); Tribes 2
|
|
259
|
+
* strings are not UTF-8, and tagged strings begin with "\x01".
|
|
243
260
|
*/
|
|
244
261
|
readString() {
|
|
245
262
|
if (this.stringBuffer !== null) {
|
|
@@ -262,8 +279,13 @@ export class BitStream {
|
|
|
262
279
|
setStringBuffer(enable) {
|
|
263
280
|
this.stringBuffer = enable ? "" : null;
|
|
264
281
|
}
|
|
265
|
-
/** Skip N bits.
|
|
282
|
+
/** Skip N bits. Sets the error flag (without moving) if that would
|
|
283
|
+
* pass the end of the buffer. */
|
|
266
284
|
skipBits(count) {
|
|
285
|
+
if (count < 0 || this.bitNum + count > this.maxReadBitNum) {
|
|
286
|
+
this.error = true;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
267
289
|
this.bitNum += count;
|
|
268
290
|
}
|
|
269
291
|
/** Read 3x F32 as a Point3F. */
|
package/dist/BitStream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitStream.js","sourceRoot":"","sources":["../src/BitStream.ts"],"names":[],"mappings":"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","sourcesContent":["import { huffProcessor } from \"./HuffmanProcessor.js\";\n\n/**\n * Bit-level stream reader, ported from the V12 engine's BitStream class.\n *\n * Bits are read LSB-first within each byte:\n * byte[bitNum >> 3] & (1 << (bitNum & 7))\n */\nexport class BitStream {\n private data: Uint8Array;\n private bitNum: number;\n private maxReadBitNum: number;\n private error: boolean;\n private stringBuffer: string | null = null;\n\n constructor(data: Uint8Array, bitOffset = 0) {\n this.data = data;\n this.bitNum = bitOffset;\n this.maxReadBitNum = data.length << 3;\n this.error = false;\n }\n\n getCurPos(): number {\n return this.bitNum;\n }\n\n setCurPos(pos: number): void {\n this.bitNum = pos;\n }\n\n /** Byte position (rounded up), matching C++ getPosition() */\n getBytePosition(): number {\n return (this.bitNum + 7) >> 3;\n }\n\n isError(): boolean {\n return this.error;\n }\n\n /** Returns true if we've read past the buffer */\n isFull(): boolean {\n return this.bitNum > this.maxReadBitNum;\n }\n\n getRemainingBits(): number {\n return this.maxReadBitNum - this.bitNum;\n }\n\n getMaxPos(): number {\n return this.maxReadBitNum;\n }\n\n /** Read a single bit as a boolean. */\n readFlag(): boolean {\n if (this.bitNum >= this.maxReadBitNum) {\n this.error = true;\n return false;\n }\n const mask = 1 << (this.bitNum & 0x7);\n const ret = (this.data[this.bitNum >> 3] & mask) !== 0;\n this.bitNum++;\n return ret;\n }\n\n /**\n * Read N bits as an unsigned integer (up to 32 bits).\n * Bits are read LSB-first, matching the C++ implementation.\n */\n readInt(bitCount: number): number {\n if (bitCount === 0) return 0;\n if (this.bitNum + bitCount > this.maxReadBitNum) {\n this.error = true;\n return 0;\n }\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n this.bitNum += bitCount;\n\n // When bitCount + downShift <= 32, everything fits in 32-bit operations\n if (bitCount + downShift <= 32) {\n let ret = 0;\n const bytesNeeded = (bitCount + downShift + 7) >> 3;\n for (\n let i = 0;\n i < bytesNeeded && startByte + i < this.data.length;\n i++\n ) {\n ret |= this.data[startByte + i] << (i * 8);\n }\n ret = ret >>> downShift;\n if (bitCount === 32) return ret >>> 0;\n return ret & ((1 << bitCount) - 1);\n }\n\n // Slow path: bitCount + downShift > 32 (e.g., reading 32 bits at a\n // non-byte-aligned position). Use float64 arithmetic to avoid the\n // 32-bit limit of JavaScript bitwise operators.\n let ret = 0;\n const bytesNeeded = (bitCount + downShift + 7) >> 3;\n for (let i = 0; i < bytesNeeded && startByte + i < this.data.length; i++) {\n ret += this.data[startByte + i] * 2 ** (i * 8);\n }\n ret = Math.floor(ret / 2 ** downShift);\n // Mask to bitCount bits using float64-safe operations\n if (bitCount === 32) return ret >>> 0;\n return ret & ((1 << bitCount) - 1);\n }\n\n /** Read a signed integer: 1-bit sign flag + (bitCount-1) magnitude bits. */\n readSignedInt(bitCount: number): number {\n if (this.readFlag()) {\n return -this.readInt(bitCount - 1);\n }\n return this.readInt(bitCount - 1);\n }\n\n /** Read a float normalized to [0, 1]. */\n readFloat(bitCount: number): number {\n return this.readInt(bitCount) / ((1 << bitCount) - 1);\n }\n\n /** Read a float normalized to [-1, 1]. */\n readSignedFloat(bitCount: number): number {\n return (this.readInt(bitCount) * 2) / ((1 << bitCount) - 1) - 1.0;\n }\n\n /** Read a ranged unsigned 32-bit integer. */\n readRangedU32(rangeStart: number, rangeEnd: number): number {\n const rangeSize = rangeEnd - rangeStart + 1;\n const rangeBits = Math.ceil(Math.log2(rangeSize)) || 1;\n return this.readInt(rangeBits) + rangeStart;\n }\n\n /** Read raw bits into a new Uint8Array. */\n readBitsBuffer(bitCount: number): Uint8Array {\n if (bitCount === 0) return new Uint8Array(0);\n const byteCount = (bitCount + 7) >> 3;\n const result = new Uint8Array(byteCount);\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n const upShift = 8 - downShift;\n\n if (downShift === 0) {\n // Byte-aligned, fast path\n result.set(this.data.subarray(startByte, startByte + byteCount));\n } else {\n let curB = this.data[startByte];\n for (let i = 0; i < byteCount; i++) {\n const nextB =\n startByte + i + 1 < this.data.length\n ? this.data[startByte + i + 1]\n : 0;\n result[i] = ((curB >> downShift) | (nextB << upShift)) & 0xff;\n curB = nextB;\n }\n }\n\n // Mask off extra bits in the last byte\n const extraBits = bitCount & 0x7;\n if (extraBits !== 0) {\n result[byteCount - 1] &= (1 << extraBits) - 1;\n }\n\n this.bitNum += bitCount;\n return result;\n }\n\n /** Read N raw bytes. Returns an array of byte values. */\n readBytes(count: number): number[] {\n const buf = this.readBitsBuffer(count * 8);\n return Array.from(buf);\n }\n\n /** Read a U8 (8 bits). */\n readU8(): number {\n return this.readInt(8);\n }\n\n /** Read a U16 (16 bits, little-endian). */\n readU16(): number {\n return this.readInt(16);\n }\n\n /** Read a U32 (32 bits, little-endian). */\n readU32(): number {\n return this.readInt(32);\n }\n\n /** Read a signed 32-bit integer (via stream.read in C++). */\n readS32(): number {\n const val = this.readU32();\n return val | 0; // convert to signed\n }\n\n /** Shared buffer for allocation-free F32 reads. */\n private static readonly f32Buf = new ArrayBuffer(4);\n private static readonly f32View = new DataView(BitStream.f32Buf);\n private static readonly f32U8 = new Uint8Array(BitStream.f32Buf);\n\n /** Read a 32-bit float (IEEE 754), allocation-free. */\n readF32(): number {\n if (this.bitNum + 32 > this.maxReadBitNum) {\n this.error = true;\n return 0;\n }\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n const u8 = BitStream.f32U8;\n\n if (downShift === 0) {\n u8[0] = this.data[startByte];\n u8[1] = this.data[startByte + 1];\n u8[2] = this.data[startByte + 2];\n u8[3] = this.data[startByte + 3];\n } else {\n const upShift = 8 - downShift;\n for (let i = 0; i < 4; i++) {\n const curB = this.data[startByte + i];\n const nextB =\n startByte + i + 1 < this.data.length\n ? this.data[startByte + i + 1]\n : 0;\n u8[i] = ((curB >> downShift) | (nextB << upShift)) & 0xff;\n }\n }\n\n this.bitNum += 32;\n return BitStream.f32View.getFloat32(0, true);\n }\n\n /** Read a boolean value stored as a U8 (matches C++ Stream::read(bool*)). */\n readBool(): boolean {\n return this.readU8() !== 0;\n }\n\n /**\n * Read a compressed 3D normal vector.\n * Uses phi (azimuth) and theta (elevation) angles.\n */\n readNormalVector(bitCount: number): { x: number; y: number; z: number } {\n const phi = this.readSignedFloat(bitCount + 1) * Math.PI;\n const theta = this.readSignedFloat(bitCount) * (Math.PI / 2.0);\n\n return {\n x: Math.sin(phi) * Math.cos(theta),\n y: Math.cos(phi) * Math.cos(theta),\n z: Math.sin(theta),\n };\n }\n\n /**\n * Read an affine transform (position + quaternion rotation).\n * Position: 3x F32\n * Quaternion: 3x F32 (x,y,z) + 1-bit sign for w\n */\n readAffineTransform(): {\n position: { x: number; y: number; z: number };\n rotation: { x: number; y: number; z: number; w: number };\n } {\n const position = {\n x: this.readF32(),\n y: this.readF32(),\n z: this.readF32(),\n };\n\n const qx = this.readF32();\n const qy = this.readF32();\n const qz = this.readF32();\n let qw = Math.sqrt(\n Math.max(0, 1.0 - (qx * qx + qy * qy + qz * qz))\n );\n if (this.readFlag()) {\n qw = -qw;\n }\n\n return {\n position,\n rotation: { x: qx, y: qy, z: qz, w: qw },\n };\n }\n\n /**\n * Read a Huffman-encoded string.\n * Handles the stringBuffer optimization (shared prefix with previous string).\n */\n readString(): string {\n if (this.stringBuffer !== null) {\n if (this.readFlag()) {\n // Shared prefix optimization: offset into previous string\n const offset = this.readInt(8);\n const suffix = huffProcessor.readHuffBuffer(this);\n const result = this.stringBuffer.substring(0, offset) + suffix;\n this.stringBuffer = result;\n return result;\n }\n }\n const result = huffProcessor.readHuffBuffer(this);\n if (this.stringBuffer !== null) {\n this.stringBuffer = result;\n }\n return result;\n }\n\n /** Enable/disable the string buffer for shared-prefix optimization. */\n setStringBuffer(enable: boolean): void {\n this.stringBuffer = enable ? \"\" : null;\n }\n\n /** Skip N bits. */\n skipBits(count: number): void {\n this.bitNum += count;\n }\n\n /** Read 3x F32 as a Point3F. */\n readPoint3F(): { x: number; y: number; z: number } {\n return { x: this.readF32(), y: this.readF32(), z: this.readF32() };\n }\n\n /**\n * Read a compressed 3D point relative to a compression point.\n * Format: 2-bit type, then either absolute (3x F32) or relative delta.\n * Used by Player MoveMask and Vehicle PositionMask.\n */\n readCompressedPoint(\n compressionPoint: { x: number; y: number; z: number },\n scale: number = 0.01\n ): { x: number; y: number; z: number } {\n const type = this.readInt(2);\n if (type === 3) {\n // Absolute position\n return { x: this.readF32(), y: this.readF32(), z: this.readF32() };\n }\n // Relative to compression point\n const bitCounts = [16, 18, 20];\n const bits = bitCounts[type];\n const dx = this.readSignedInt(bits);\n const dy = this.readSignedInt(bits);\n const dz = this.readSignedInt(bits);\n return {\n x: compressionPoint.x + dx * scale,\n y: compressionPoint.y + dy * scale,\n z: compressionPoint.z + dz * scale,\n };\n }\n\n /**\n * Read a MatrixF written via mathWrite(MatrixF).\n * Format: 16x F32 (row-major in Torque's MatrixF storage) = 512 bits.\n */\n readMatrixF(): {\n elements: number[];\n position: { x: number; y: number; z: number };\n } {\n const elements = new Array<number>(16);\n for (let i = 0; i < 16; i++) {\n elements[i] = this.readF32();\n }\n\n // MatrixF is written row-major: each row is [r0, r1, r2, translation].\n // Position (column 3) is at indices 3, 7, 11 (last element of each row).\n return {\n elements,\n position: { x: elements[3], y: elements[7], z: elements[11] },\n };\n }\n\n /**\n * Read a Torque \"packed string\" with 2-bit type code.\n * Used by RemoteCommandEvent for script arguments.\n * Tribes 2 binary (FUN_00588690) format:\n * 0 = null/empty\n * 1 = normal packed string\n * 2 = tagged string id (10-bit), decoded to \"\\x01<decimalId>\"\n * 3 = integer string (sign + 7/15/31-bit magnitude)\n */\n unpackNetString(): string {\n const code = this.readInt(2);\n switch (code) {\n case 0:\n return \"\"; // null string\n case 1:\n return this.readString(); // Huffman-encoded string\n case 2: {\n // Decompiled binary uses 10 bits here, not 12.\n const tag = this.readInt(10);\n // Keep Tribes 2 tagged-string wire representation.\n return `\\x01${tag}`;\n }\n case 3: {\n // Integer encoding: sign + variable-size magnitude\n const neg = this.readFlag();\n let num: number;\n if (this.readFlag()) {\n num = this.readInt(7); // small\n } else if (this.readFlag()) {\n num = this.readInt(15); // medium\n } else {\n num = this.readInt(31); // large\n }\n if (neg) num = -num;\n return String(num);\n }\n default:\n return \"\";\n }\n }\n\n /** Create a snapshot of the current position that can be restored. */\n savePos(): number {\n return this.bitNum;\n }\n\n /** Restore a previously saved position. */\n restorePos(pos: number): void {\n this.bitNum = pos;\n this.error = false;\n }\n\n /** Get the underlying data buffer. */\n getBuffer(): Uint8Array {\n return this.data;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BitStream.js","sourceRoot":"","sources":["../src/BitStream.ts"],"names":[],"mappings":"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","sourcesContent":["import { huffProcessor } from \"./HuffmanProcessor.js\";\n\n/**\n * Bit-level stream reader, ported from the V12 engine's BitStream class.\n *\n * Bits are read LSB-first within each byte:\n * byte[bitNum >> 3] & (1 << (bitNum & 7))\n */\nexport class BitStream {\n private data: Uint8Array;\n private bitNum: number;\n private maxReadBitNum: number;\n private error: boolean;\n private stringBuffer: string | null = null;\n\n constructor(data: Uint8Array, bitOffset = 0) {\n this.data = data;\n this.bitNum = bitOffset;\n this.maxReadBitNum = data.length << 3;\n this.error = false;\n }\n\n getCurPos(): number {\n return this.bitNum;\n }\n\n setCurPos(pos: number): void {\n this.bitNum = pos;\n }\n\n /** Byte position (rounded up), matching C++ getPosition() */\n getBytePosition(): number {\n return (this.bitNum + 7) >> 3;\n }\n\n isError(): boolean {\n return this.error;\n }\n\n /** Returns true if we've read past the buffer */\n isFull(): boolean {\n return this.bitNum > this.maxReadBitNum;\n }\n\n getRemainingBits(): number {\n return this.maxReadBitNum - this.bitNum;\n }\n\n getMaxPos(): number {\n return this.maxReadBitNum;\n }\n\n /** Read a single bit as a boolean. */\n readFlag(): boolean {\n if (this.bitNum >= this.maxReadBitNum) {\n this.error = true;\n return false;\n }\n const mask = 1 << (this.bitNum & 0x7);\n const ret = (this.data[this.bitNum >> 3] & mask) !== 0;\n this.bitNum++;\n return ret;\n }\n\n /**\n * Read N bits as an unsigned integer (up to 32 bits).\n * Bits are read LSB-first, matching the C++ implementation.\n */\n readInt(bitCount: number): number {\n if (bitCount === 0) return 0;\n if (!(bitCount > 0 && bitCount <= 32)) {\n throw new RangeError(`readInt bitCount out of range: ${bitCount}`);\n }\n if (this.bitNum + bitCount > this.maxReadBitNum) {\n this.error = true;\n return 0;\n }\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n this.bitNum += bitCount;\n\n // When bitCount + downShift <= 32, everything fits in 32-bit operations\n if (bitCount + downShift <= 32) {\n let ret = 0;\n const bytesNeeded = (bitCount + downShift + 7) >> 3;\n for (\n let i = 0;\n i < bytesNeeded && startByte + i < this.data.length;\n i++\n ) {\n ret |= this.data[startByte + i] << (i * 8);\n }\n ret = ret >>> downShift;\n if (bitCount === 32) return ret >>> 0;\n return ret & ((1 << bitCount) - 1);\n }\n\n // Slow path: bitCount + downShift > 32 (e.g., reading 32 bits at a\n // non-byte-aligned position). Use float64 arithmetic to avoid the\n // 32-bit limit of JavaScript bitwise operators.\n let ret = 0;\n const bytesNeeded = (bitCount + downShift + 7) >> 3;\n for (let i = 0; i < bytesNeeded && startByte + i < this.data.length; i++) {\n ret += this.data[startByte + i] * 2 ** (i * 8);\n }\n ret = Math.floor(ret / 2 ** downShift);\n // Mask to bitCount bits using float64-safe operations\n if (bitCount === 32) return ret >>> 0;\n return ret & ((1 << bitCount) - 1);\n }\n\n /** Read a signed integer: 1-bit sign flag + (bitCount-1) magnitude bits. */\n readSignedInt(bitCount: number): number {\n if (this.readFlag()) {\n return -this.readInt(bitCount - 1);\n }\n return this.readInt(bitCount - 1);\n }\n\n /** Read a float normalized to [0, 1]. */\n readFloat(bitCount: number): number {\n return this.readInt(bitCount) / (2 ** bitCount - 1);\n }\n\n /** Read a float normalized to [-1, 1]. */\n readSignedFloat(bitCount: number): number {\n return (this.readInt(bitCount) * 2) / (2 ** bitCount - 1) - 1.0;\n }\n\n /**\n * Read a ranged unsigned 32-bit integer. Bit width is\n * getBinLog2(getNextPow2(rangeSize)) as in the engine (FUN_0043f120 /\n * FUN_0043f150): a range of one value reads zero bits.\n */\n readRangedU32(rangeStart: number, rangeEnd: number): number {\n const rangeSize = rangeEnd - rangeStart + 1;\n const rangeBits = Math.ceil(Math.log2(rangeSize));\n return this.readInt(rangeBits) + rangeStart;\n }\n\n /**\n * Read raw bits into a new Uint8Array. Like every other read, an\n * over-length request sets the error flag, leaves the cursor in place,\n * and returns zeroed bytes (the engine's BitStream::readBits).\n */\n readBitsBuffer(bitCount: number): Uint8Array {\n if (bitCount === 0) return new Uint8Array(0);\n const byteCount = (bitCount + 7) >> 3;\n const result = new Uint8Array(byteCount);\n if (bitCount < 0 || this.bitNum + bitCount > this.maxReadBitNum) {\n this.error = true;\n return result;\n }\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n const upShift = 8 - downShift;\n\n if (downShift === 0) {\n // Byte-aligned, fast path\n result.set(this.data.subarray(startByte, startByte + byteCount));\n } else {\n let curB = this.data[startByte];\n for (let i = 0; i < byteCount; i++) {\n const nextB =\n startByte + i + 1 < this.data.length\n ? this.data[startByte + i + 1]\n : 0;\n result[i] = ((curB >> downShift) | (nextB << upShift)) & 0xff;\n curB = nextB;\n }\n }\n\n // Mask off extra bits in the last byte\n const extraBits = bitCount & 0x7;\n if (extraBits !== 0) {\n result[byteCount - 1] &= (1 << extraBits) - 1;\n }\n\n this.bitNum += bitCount;\n return result;\n }\n\n /** Read N raw bytes. Returns an array of byte values. */\n readBytes(count: number): number[] {\n const buf = this.readBitsBuffer(count * 8);\n return Array.from(buf);\n }\n\n /** Read a U8 (8 bits). */\n readU8(): number {\n return this.readInt(8);\n }\n\n /** Read a U16 (16 bits, little-endian). */\n readU16(): number {\n return this.readInt(16);\n }\n\n /** Read a U32 (32 bits, little-endian). */\n readU32(): number {\n return this.readInt(32);\n }\n\n /** Read a signed 32-bit integer (via stream.read in C++). */\n readS32(): number {\n const val = this.readU32();\n return val | 0; // convert to signed\n }\n\n /** Shared buffer for allocation-free F32 reads. */\n private static readonly f32Buf = new ArrayBuffer(4);\n private static readonly f32View = new DataView(BitStream.f32Buf);\n private static readonly f32U8 = new Uint8Array(BitStream.f32Buf);\n\n /** Read a 32-bit float (IEEE 754), allocation-free. */\n readF32(): number {\n if (this.bitNum + 32 > this.maxReadBitNum) {\n this.error = true;\n return 0;\n }\n\n const startByte = this.bitNum >> 3;\n const downShift = this.bitNum & 0x7;\n const u8 = BitStream.f32U8;\n\n if (downShift === 0) {\n u8[0] = this.data[startByte];\n u8[1] = this.data[startByte + 1];\n u8[2] = this.data[startByte + 2];\n u8[3] = this.data[startByte + 3];\n } else {\n const upShift = 8 - downShift;\n for (let i = 0; i < 4; i++) {\n const curB = this.data[startByte + i];\n const nextB =\n startByte + i + 1 < this.data.length\n ? this.data[startByte + i + 1]\n : 0;\n u8[i] = ((curB >> downShift) | (nextB << upShift)) & 0xff;\n }\n }\n\n this.bitNum += 32;\n return BitStream.f32View.getFloat32(0, true);\n }\n\n /** Read a boolean value stored as a U8 (matches C++ Stream::read(bool*)). */\n readBool(): boolean {\n return this.readU8() !== 0;\n }\n\n /**\n * Read a compressed 3D normal vector.\n * Uses phi (azimuth) and theta (elevation) angles.\n */\n readNormalVector(bitCount: number): { x: number; y: number; z: number } {\n const phi = this.readSignedFloat(bitCount + 1) * Math.PI;\n const theta = this.readSignedFloat(bitCount) * (Math.PI / 2.0);\n\n return {\n x: Math.sin(phi) * Math.cos(theta),\n y: Math.cos(phi) * Math.cos(theta),\n z: Math.sin(theta),\n };\n }\n\n /**\n * Read an affine transform (position + quaternion rotation).\n * Position: 3x F32\n * Quaternion: 3x F32 (x,y,z) + 1-bit sign for w\n */\n readAffineTransform(): {\n position: { x: number; y: number; z: number };\n rotation: { x: number; y: number; z: number; w: number };\n } {\n const position = {\n x: this.readF32(),\n y: this.readF32(),\n z: this.readF32(),\n };\n\n const qx = this.readF32();\n const qy = this.readF32();\n const qz = this.readF32();\n let qw = Math.sqrt(Math.max(0, 1.0 - (qx * qx + qy * qy + qz * qz)));\n if (this.readFlag()) {\n qw = -qw;\n }\n\n return {\n position,\n rotation: { x: qx, y: qy, z: qz, w: qw },\n };\n }\n\n /**\n * Read a Huffman-encoded string.\n * Handles the stringBuffer optimization (shared prefix with previous string).\n * Each wire byte becomes one UTF-16 code unit (Latin-1 decoding); Tribes 2\n * strings are not UTF-8, and tagged strings begin with \"\\x01\".\n */\n readString(): string {\n if (this.stringBuffer !== null) {\n if (this.readFlag()) {\n // Shared prefix optimization: offset into previous string\n const offset = this.readInt(8);\n const suffix = huffProcessor.readHuffBuffer(this);\n const result = this.stringBuffer.substring(0, offset) + suffix;\n this.stringBuffer = result;\n return result;\n }\n }\n const result = huffProcessor.readHuffBuffer(this);\n if (this.stringBuffer !== null) {\n this.stringBuffer = result;\n }\n return result;\n }\n\n /** Enable/disable the string buffer for shared-prefix optimization. */\n setStringBuffer(enable: boolean): void {\n this.stringBuffer = enable ? \"\" : null;\n }\n\n /** Skip N bits. Sets the error flag (without moving) if that would\n * pass the end of the buffer. */\n skipBits(count: number): void {\n if (count < 0 || this.bitNum + count > this.maxReadBitNum) {\n this.error = true;\n return;\n }\n this.bitNum += count;\n }\n\n /** Read 3x F32 as a Point3F. */\n readPoint3F(): { x: number; y: number; z: number } {\n return { x: this.readF32(), y: this.readF32(), z: this.readF32() };\n }\n\n /**\n * Read a compressed 3D point relative to a compression point.\n * Format: 2-bit type, then either absolute (3x F32) or relative delta.\n * Used by Player MoveMask and Vehicle PositionMask.\n */\n readCompressedPoint(\n compressionPoint: { x: number; y: number; z: number },\n scale: number = 0.01,\n ): { x: number; y: number; z: number } {\n const type = this.readInt(2);\n if (type === 3) {\n // Absolute position\n return { x: this.readF32(), y: this.readF32(), z: this.readF32() };\n }\n // Relative to compression point\n const bitCounts = [16, 18, 20];\n const bits = bitCounts[type];\n const dx = this.readSignedInt(bits);\n const dy = this.readSignedInt(bits);\n const dz = this.readSignedInt(bits);\n return {\n x: compressionPoint.x + dx * scale,\n y: compressionPoint.y + dy * scale,\n z: compressionPoint.z + dz * scale,\n };\n }\n\n /**\n * Read a MatrixF written via mathWrite(MatrixF).\n * Format: 16x F32 (row-major in Torque's MatrixF storage) = 512 bits.\n */\n readMatrixF(): {\n elements: number[];\n position: { x: number; y: number; z: number };\n } {\n const elements = new Array<number>(16);\n for (let i = 0; i < 16; i++) {\n elements[i] = this.readF32();\n }\n\n // MatrixF is written row-major: each row is [r0, r1, r2, translation].\n // Position (column 3) is at indices 3, 7, 11 (last element of each row).\n return {\n elements,\n position: { x: elements[3], y: elements[7], z: elements[11] },\n };\n }\n\n /**\n * Read a Torque \"packed string\" with 2-bit type code.\n * Used by RemoteCommandEvent for script arguments.\n * Tribes 2 binary (FUN_00588690) format:\n * 0 = null/empty\n * 1 = normal packed string\n * 2 = tagged string id (10-bit), decoded to \"\\x01<decimalId>\"\n * 3 = integer string (sign + 7/15/31-bit magnitude)\n */\n unpackNetString(): string {\n const code = this.readInt(2);\n switch (code) {\n case 0:\n return \"\"; // null string\n case 1:\n return this.readString(); // Huffman-encoded string\n case 2: {\n // Decompiled binary uses 10 bits here, not 12.\n const tag = this.readInt(10);\n // Keep Tribes 2 tagged-string wire representation.\n return `\\x01${tag}`;\n }\n case 3: {\n // Integer encoding: sign + variable-size magnitude\n const neg = this.readFlag();\n let num: number;\n if (this.readFlag()) {\n num = this.readInt(7); // small\n } else if (this.readFlag()) {\n num = this.readInt(15); // medium\n } else {\n num = this.readInt(31); // large\n }\n if (neg) num = -num;\n return String(num);\n }\n default:\n return \"\";\n }\n }\n\n /** Create a snapshot of the current position that can be restored. */\n savePos(): number {\n return this.bitNum;\n }\n\n /** Restore a previously saved position. */\n restorePos(pos: number): void {\n this.bitNum = pos;\n this.error = false;\n }\n\n /** Get the underlying data buffer. */\n getBuffer(): Uint8Array {\n return this.data;\n }\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSB-first bit packer producing buffers that BitStream reads back
|
|
3
|
+
* bit-for-bit. Mirrors the write side of the engine's BitStream for the
|
|
4
|
+
* primitives the parser consumes; intended for building test vectors and
|
|
5
|
+
* synthetic packets.
|
|
6
|
+
*/
|
|
7
|
+
export declare class BitWriter {
|
|
8
|
+
private bytes;
|
|
9
|
+
private bitNum;
|
|
10
|
+
getCurPos(): number;
|
|
11
|
+
writeFlag(value: boolean): this;
|
|
12
|
+
/** Write the low `bitCount` bits of `value` (up to 32), LSB first. */
|
|
13
|
+
writeInt(value: number, bitCount: number): this;
|
|
14
|
+
writeSignedInt(value: number, bitCount: number): this;
|
|
15
|
+
writeU8(value: number): this;
|
|
16
|
+
writeU32(value: number): this;
|
|
17
|
+
writeS32(value: number): this;
|
|
18
|
+
writeF32(value: number): this;
|
|
19
|
+
/** Write a float in [0, 1] quantized to `bitCount` bits. */
|
|
20
|
+
writeFloat(value: number, bitCount: number): this;
|
|
21
|
+
writeBytes(bytes: ArrayLike<number>): this;
|
|
22
|
+
/** Write a Huffman string exactly as the engine's writeString does
|
|
23
|
+
* (no string-buffer prefix optimization). */
|
|
24
|
+
writeString(value: string): this;
|
|
25
|
+
/** Pad to a byte boundary (plus optional extra zero bytes) and return
|
|
26
|
+
* the packed buffer. */
|
|
27
|
+
finish(padBytes?: number): Uint8Array;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=BitWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitWriter.d.ts","sourceRoot":"","sources":["../src/BitWriter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAK;IAEnB,SAAS,IAAI,MAAM;IAInB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI/B,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgB/C,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKrD,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,4DAA4D;IAC5D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIjD,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAK1C;kDAC8C;IAC9C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKhC;6BACyB;IACzB,MAAM,CAAC,QAAQ,SAAI,GAAG,UAAU;CAMjC"}
|