t2-demo-parser 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -7
- package/dist/BitStream.d.ts +14 -3
- package/dist/BitStream.d.ts.map +1 -1
- package/dist/BitStream.js +28 -6
- package/dist/BitStream.js.map +1 -1
- package/dist/BitWriter.d.ts +29 -0
- package/dist/BitWriter.d.ts.map +1 -0
- package/dist/BitWriter.js +76 -0
- package/dist/BitWriter.js.map +1 -0
- package/dist/ClassRegistry.d.ts +23 -28
- package/dist/ClassRegistry.d.ts.map +1 -1
- package/dist/ClassRegistry.js +75 -84
- package/dist/ClassRegistry.js.map +1 -1
- package/dist/DataBlockParsers.d.ts.map +1 -1
- package/dist/DataBlockParsers.js +51 -76
- package/dist/DataBlockParsers.js.map +1 -1
- package/dist/DemoParser.d.ts +23 -22
- package/dist/DemoParser.d.ts.map +1 -1
- package/dist/DemoParser.js +218 -266
- package/dist/DemoParser.js.map +1 -1
- package/dist/EventParsers.d.ts.map +1 -1
- package/dist/EventParsers.js +87 -58
- package/dist/EventParsers.js.map +1 -1
- package/dist/GhostManager.d.ts +7 -1
- package/dist/GhostManager.d.ts.map +1 -1
- package/dist/GhostManager.js +231 -146
- package/dist/GhostManager.js.map +1 -1
- package/dist/HuffmanProcessor.d.ts +15 -0
- package/dist/HuffmanProcessor.d.ts.map +1 -1
- package/dist/HuffmanProcessor.js +45 -0
- package/dist/HuffmanProcessor.js.map +1 -1
- package/dist/LiveParser.d.ts +20 -1
- package/dist/LiveParser.d.ts.map +1 -1
- package/dist/LiveParser.js +31 -12
- package/dist/LiveParser.js.map +1 -1
- package/dist/PacketParser.d.ts +22 -2
- package/dist/PacketParser.d.ts.map +1 -1
- package/dist/PacketParser.js +111 -48
- package/dist/PacketParser.js.map +1 -1
- package/dist/Timeline.d.ts +5 -2
- package/dist/Timeline.d.ts.map +1 -1
- package/dist/Timeline.js +25 -12
- package/dist/Timeline.js.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/dataBlockDataTypes.d.ts +111 -112
- package/dist/dataBlockDataTypes.d.ts.map +1 -1
- package/dist/dataBlockDataTypes.js.map +1 -1
- package/dist/defaultRegistry.d.ts +9 -0
- package/dist/defaultRegistry.d.ts.map +1 -0
- package/dist/defaultRegistry.js +43 -0
- package/dist/defaultRegistry.js.map +1 -0
- package/dist/eventDataTypes.d.ts +74 -72
- package/dist/eventDataTypes.d.ts.map +1 -1
- package/dist/eventDataTypes.js.map +1 -1
- package/dist/ghostDataTypes.d.ts +125 -131
- package/dist/ghostDataTypes.d.ts.map +1 -1
- package/dist/ghostDataTypes.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +51 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -1
- package/dist/BitStream.test.d.ts +0 -2
- package/dist/BitStream.test.d.ts.map +0 -1
- package/dist/BitStream.test.js +0 -419
- package/dist/BitStream.test.js.map +0 -1
- package/dist/ClassRegistry.test.d.ts +0 -2
- package/dist/ClassRegistry.test.d.ts.map +0 -1
- package/dist/ClassRegistry.test.js +0 -83
- package/dist/ClassRegistry.test.js.map +0 -1
- package/dist/DataBlockParsers.test.d.ts +0 -2
- package/dist/DataBlockParsers.test.d.ts.map +0 -1
- package/dist/DataBlockParsers.test.js +0 -294
- package/dist/DataBlockParsers.test.js.map +0 -1
- package/dist/DemoParser.test.d.ts +0 -2
- package/dist/DemoParser.test.d.ts.map +0 -1
- package/dist/DemoParser.test.js +0 -472
- package/dist/DemoParser.test.js.map +0 -1
- package/dist/GhostStateAccumulator.test.d.ts +0 -2
- package/dist/GhostStateAccumulator.test.d.ts.map +0 -1
- package/dist/GhostStateAccumulator.test.js +0 -201
- package/dist/GhostStateAccumulator.test.js.map +0 -1
- package/dist/GhostTracker.test.d.ts +0 -2
- package/dist/GhostTracker.test.d.ts.map +0 -1
- package/dist/GhostTracker.test.js +0 -64
- package/dist/GhostTracker.test.js.map +0 -1
- package/dist/IncrementalParser.test.d.ts +0 -2
- package/dist/IncrementalParser.test.d.ts.map +0 -1
- package/dist/IncrementalParser.test.js +0 -226
- package/dist/IncrementalParser.test.js.map +0 -1
package/dist/DataBlockParsers.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* getBitCount(getNextPow2(0x800)) = 11 bits.
|
|
8
8
|
* If flag is false, sets objectId to -1 (0xFFFFFFFF).
|
|
9
9
|
*/
|
|
10
|
+
/** particleEngine.cc: PDC_MAX_TEX. */
|
|
11
|
+
const ParticleDataMaxTextures = 50;
|
|
10
12
|
function readDataBlockRef(bs) {
|
|
11
13
|
return bs.readFlag() ? bs.readInt(11) : null;
|
|
12
14
|
}
|
|
@@ -22,6 +24,11 @@ function readRangedS32(bs, min, max) {
|
|
|
22
24
|
* From decompiled binary: FUN_0043f040 calls FUN_0043efe0 which reads 4 × stream->read(1, &byte).
|
|
23
25
|
* Each byte is multiplied by 1/255.0 to produce the float value.
|
|
24
26
|
* NOTE: This is NOT 4×F32 (128 bits) — it's 4×U8 (32 bits).
|
|
27
|
+
*
|
|
28
|
+
* Colour representation follows the engine's own field type: fields the
|
|
29
|
+
* engine stores as ColorF (this reader) are normalised to [0, 1]; fields
|
|
30
|
+
* it stores as ColorI (sensorColor, sensor group colours) keep the raw
|
|
31
|
+
* 0–255 bytes.
|
|
25
32
|
*/
|
|
26
33
|
function readColorF(bs) {
|
|
27
34
|
return {
|
|
@@ -37,13 +44,23 @@ function readColorF(bs) {
|
|
|
37
44
|
* Many DataBlock fields use write(sizeof(bool)) instead of writeFlag().
|
|
38
45
|
*/
|
|
39
46
|
function readBool(bs) {
|
|
40
|
-
return bs.
|
|
47
|
+
return bs.readBool();
|
|
48
|
+
}
|
|
49
|
+
/** Read a ranged float: min + readFloat(bits) * (max - min). */
|
|
50
|
+
function readRangedF32(bs, min, max, bits) {
|
|
51
|
+
return min + bs.readFloat(bits) * (max - min);
|
|
41
52
|
}
|
|
42
53
|
/**
|
|
43
|
-
* Read a
|
|
54
|
+
* Read a U32 count and reject it unless `minBitsPerEntry × count` bits
|
|
55
|
+
* remain: exhausted reads return 0 without throwing, so a corrupt count
|
|
56
|
+
* would otherwise spin allocating until memory ran out.
|
|
44
57
|
*/
|
|
45
|
-
function
|
|
46
|
-
|
|
58
|
+
function readCheckedCount(bs, minBitsPerEntry, what) {
|
|
59
|
+
const count = bs.readU32();
|
|
60
|
+
if (count > bs.getRemainingBits() / minBitsPerEntry) {
|
|
61
|
+
throw new Error(`Invalid ${what}: ${count}`);
|
|
62
|
+
}
|
|
63
|
+
return count;
|
|
47
64
|
}
|
|
48
65
|
// ============================================================
|
|
49
66
|
// Base class parsers (inheritance chain)
|
|
@@ -90,6 +107,7 @@ function shapeBaseDataUnpack(bs) {
|
|
|
90
107
|
result.debrisShapeName = bs.readString();
|
|
91
108
|
// sensorRadius — flag; if true: readInt(10) + 4×U8 (RGBA bytes)
|
|
92
109
|
// Binary: readInt(10) → this+0x15c (cast to float), then 4 × read(1) → 0x160-0x163
|
|
110
|
+
// sensorColor is a ColorI in the engine, so the bytes are kept as-is.
|
|
93
111
|
if (bs.readFlag()) {
|
|
94
112
|
result.sensorRadius = bs.readInt(10);
|
|
95
113
|
result.sensorColor = {
|
|
@@ -134,11 +152,7 @@ function shapeBaseDataUnpack(bs) {
|
|
|
134
152
|
// Binary: readFlag, if true: read(4) × 3 → this+0x98, 0x9c, 0xa0
|
|
135
153
|
// NOTE: This field is NOT in the V12 reference source — Tribes 2 addition.
|
|
136
154
|
if (bs.readFlag()) {
|
|
137
|
-
result.shieldEffectScale =
|
|
138
|
-
x: bs.readF32(),
|
|
139
|
-
y: bs.readF32(),
|
|
140
|
-
z: bs.readF32(),
|
|
141
|
-
};
|
|
155
|
+
result.shieldEffectScale = bs.readPoint3F();
|
|
142
156
|
}
|
|
143
157
|
// HUD images loop (8 iterations, NumHudRenderImages=8)
|
|
144
158
|
// Binary: do-while uVar4 < 8 at offset this + uVar4*4 + 0x174
|
|
@@ -222,11 +236,7 @@ function shapeBaseImageDataUnpack(bs) {
|
|
|
222
236
|
};
|
|
223
237
|
}
|
|
224
238
|
// shellExitDir — 3×F32 (mathWrite Point3F)
|
|
225
|
-
result.shellExitDir =
|
|
226
|
-
x: bs.readF32(),
|
|
227
|
-
y: bs.readF32(),
|
|
228
|
-
z: bs.readF32(),
|
|
229
|
-
};
|
|
239
|
+
result.shellExitDir = bs.readPoint3F();
|
|
230
240
|
// shellExitVariance — F32
|
|
231
241
|
result.shellExitVariance = bs.readF32();
|
|
232
242
|
// shellVelocity — F32
|
|
@@ -366,9 +376,7 @@ function playerDataUnpack(bs) {
|
|
|
366
376
|
// [0x364 hardcoded to 0, not from stream]
|
|
367
377
|
// 3. 2 optional DataBlock refs (readClassId pattern)
|
|
368
378
|
result.jetEmitter = readDataBlockRef(bs); // 0x368 (jetEmitter @0x364)
|
|
369
|
-
|
|
370
|
-
result.jetEffect = bs.readInt(11); // 0x370 (jetEffect @0x36c; no else/-1)
|
|
371
|
-
}
|
|
379
|
+
result.jetEffect = readDataBlockRef(bs); // 0x370 (jetEffect @0x36c)
|
|
372
380
|
// 4. 9× F32 (offsets 0x374-0x394)
|
|
373
381
|
result.runForce = bs.readF32(); // 0x374
|
|
374
382
|
result.runEnergyDrain = bs.readF32(); // 0x378
|
|
@@ -415,20 +423,11 @@ function playerDataUnpack(bs) {
|
|
|
415
423
|
// Binary: zeros 0x428+i*4, then flag + readClassId → 0x4a8+i*4
|
|
416
424
|
const sounds = [];
|
|
417
425
|
for (let i = 0; i < 32; i++) {
|
|
418
|
-
|
|
419
|
-
sounds.push(bs.readInt(11));
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
sounds.push(null);
|
|
423
|
-
}
|
|
426
|
+
sounds.push(readDataBlockRef(bs));
|
|
424
427
|
}
|
|
425
428
|
result.sounds = sounds;
|
|
426
429
|
// 12. boxSize 3×F32 (offsets 0x528, 0x52c, 0x530)
|
|
427
|
-
result.boxSize =
|
|
428
|
-
x: bs.readF32(),
|
|
429
|
-
y: bs.readF32(),
|
|
430
|
-
z: bs.readF32(),
|
|
431
|
-
};
|
|
430
|
+
result.boxSize = bs.readPoint3F();
|
|
432
431
|
// 13. footPuffEmitter + 2 F32s (offset 0xcf0, 0xcf4, 0xcf8)
|
|
433
432
|
result.footPuffEmitter = readDataBlockRef(bs);
|
|
434
433
|
result.footPuffNumParts = bs.readF32();
|
|
@@ -524,16 +523,8 @@ function vehicleDataUnpack(bs) {
|
|
|
524
523
|
}
|
|
525
524
|
result.splashEmitters = splashEmitters;
|
|
526
525
|
// 8. 2×3 F32 damage emitter offsets (2 sets of x,y,z) → offsets 0x3e8-0x3f4
|
|
527
|
-
result.damageEmitterOffset0 =
|
|
528
|
-
|
|
529
|
-
y: bs.readF32(),
|
|
530
|
-
z: bs.readF32(),
|
|
531
|
-
};
|
|
532
|
-
result.damageEmitterOffset1 = {
|
|
533
|
-
x: bs.readF32(),
|
|
534
|
-
y: bs.readF32(),
|
|
535
|
-
z: bs.readF32(),
|
|
536
|
-
};
|
|
526
|
+
result.damageEmitterOffset0 = bs.readPoint3F();
|
|
527
|
+
result.damageEmitterOffset1 = bs.readPoint3F();
|
|
537
528
|
// 9. 2 F32 damage level tolerance → offsets 0x400, 0x404
|
|
538
529
|
result.damageLevelTolerance0 = bs.readF32();
|
|
539
530
|
result.damageLevelTolerance1 = bs.readF32();
|
|
@@ -602,11 +593,7 @@ function hoverVehicleDataUnpack(bs) {
|
|
|
602
593
|
result.floatingThrustFactor = bs.readF32();
|
|
603
594
|
result.brakingForce = bs.readF32();
|
|
604
595
|
// 3×F32 (dustTrailOffset)
|
|
605
|
-
result.dustTrailOffset =
|
|
606
|
-
x: bs.readF32(),
|
|
607
|
-
y: bs.readF32(),
|
|
608
|
-
z: bs.readF32(),
|
|
609
|
-
};
|
|
596
|
+
result.dustTrailOffset = bs.readPoint3F();
|
|
610
597
|
// 2 F32s
|
|
611
598
|
result.dustTrailFreqMod = bs.readF32();
|
|
612
599
|
result.triggerTrailHeight = bs.readF32();
|
|
@@ -748,11 +735,7 @@ function projectileDataUnpack(bs) {
|
|
|
748
735
|
result.faceViewer = bs.readFlag();
|
|
749
736
|
// flag(nonDefaultScale); if true: 3×F32
|
|
750
737
|
if (bs.readFlag()) {
|
|
751
|
-
result.scale =
|
|
752
|
-
x: bs.readF32(),
|
|
753
|
-
y: bs.readF32(),
|
|
754
|
-
z: bs.readF32(),
|
|
755
|
-
};
|
|
738
|
+
result.scale = bs.readPoint3F();
|
|
756
739
|
}
|
|
757
740
|
// 9 readDataBlockRef fields in pack order (verified against decompiled
|
|
758
741
|
// Tribes2.exe FUN_00631010 / FUN_006303f0 struct offsets).
|
|
@@ -1175,16 +1158,8 @@ function explosionDataUnpack(bs) {
|
|
|
1175
1158
|
result.shakeCamera = bs.readFlag();
|
|
1176
1159
|
result.hasLight = bs.readFlag();
|
|
1177
1160
|
// 9×F32
|
|
1178
|
-
result.camShakeFreq =
|
|
1179
|
-
|
|
1180
|
-
y: bs.readF32(),
|
|
1181
|
-
z: bs.readF32(),
|
|
1182
|
-
};
|
|
1183
|
-
result.camShakeAmp = {
|
|
1184
|
-
x: bs.readF32(),
|
|
1185
|
-
y: bs.readF32(),
|
|
1186
|
-
z: bs.readF32(),
|
|
1187
|
-
};
|
|
1161
|
+
result.camShakeFreq = bs.readPoint3F();
|
|
1162
|
+
result.camShakeAmp = bs.readPoint3F();
|
|
1188
1163
|
result.camShakeDuration = bs.readF32();
|
|
1189
1164
|
result.camShakeRadius = bs.readF32();
|
|
1190
1165
|
result.camShakeFalloff = bs.readF32();
|
|
@@ -1238,9 +1213,11 @@ function debrisDataUnpack(bs) {
|
|
|
1238
1213
|
result.snapOnMaxBounce = readBool(bs);
|
|
1239
1214
|
result.lifetime = bs.readF32(); // 0x54
|
|
1240
1215
|
result.lifetimeVariance = bs.readF32(); // 0x58
|
|
1241
|
-
//
|
|
1242
|
-
|
|
1243
|
-
|
|
1216
|
+
// The binary writes minSpinSpeed/maxSpinSpeed (0x64/0x68) a second
|
|
1217
|
+
// time here; the client's second read overwrites the first, so do the
|
|
1218
|
+
// same.
|
|
1219
|
+
result.minSpinSpeed = bs.readF32();
|
|
1220
|
+
result.maxSpinSpeed = bs.readF32();
|
|
1244
1221
|
result.velocity = bs.readF32(); // 0x44
|
|
1245
1222
|
result.velocityVariance = bs.readF32(); // 0x48
|
|
1246
1223
|
// 2 bools via stream->write(sizeof(bool)) = 8 bits each (0x70, 0x71)
|
|
@@ -1266,11 +1243,7 @@ function debrisDataUnpack(bs) {
|
|
|
1266
1243
|
function splashDataUnpack(bs) {
|
|
1267
1244
|
const result = {};
|
|
1268
1245
|
// 3×F32 (scale)
|
|
1269
|
-
result.scale =
|
|
1270
|
-
x: bs.readF32(),
|
|
1271
|
-
y: bs.readF32(),
|
|
1272
|
-
z: bs.readF32(),
|
|
1273
|
-
};
|
|
1246
|
+
result.scale = bs.readPoint3F();
|
|
1274
1247
|
// ~15 F32/S32 values
|
|
1275
1248
|
result.delayMS = bs.readS32();
|
|
1276
1249
|
result.delayVariance = bs.readS32();
|
|
@@ -1317,11 +1290,7 @@ function splashDataUnpack(bs) {
|
|
|
1317
1290
|
function shockwaveDataUnpack(bs) {
|
|
1318
1291
|
const result = {};
|
|
1319
1292
|
// 3×F32 (scale)
|
|
1320
|
-
result.scale =
|
|
1321
|
-
x: bs.readF32(),
|
|
1322
|
-
y: bs.readF32(),
|
|
1323
|
-
z: bs.readF32(),
|
|
1324
|
-
};
|
|
1293
|
+
result.scale = bs.readPoint3F();
|
|
1325
1294
|
// ~17 F32/S32/bool values
|
|
1326
1295
|
result.delayMS = bs.readS32();
|
|
1327
1296
|
result.delayVariance = bs.readS32();
|
|
@@ -1401,9 +1370,11 @@ function particleEmitterDataUnpack(bs) {
|
|
|
1401
1370
|
// Verified against decompiled binary FUN_006222a0:
|
|
1402
1371
|
// read(4, &count) → U32 count
|
|
1403
1372
|
// for each: readFlag → if true: FUN_00436d10 (readClassId, 11 bits); else: 0xFFFFFFFF
|
|
1404
|
-
|
|
1373
|
+
// particleEngine.cc sizes the vector straight from the count (no cap);
|
|
1374
|
+
// each entry is at least the 1-bit presence flag.
|
|
1375
|
+
const particleCount = readCheckedCount(bs, 1, "ParticleEmitterData particle count");
|
|
1405
1376
|
const particles = [];
|
|
1406
|
-
for (let i = 0; i < particleCount
|
|
1377
|
+
for (let i = 0; i < particleCount; i++) {
|
|
1407
1378
|
particles.push(readDataBlockRef(bs));
|
|
1408
1379
|
}
|
|
1409
1380
|
result.particles = particles;
|
|
@@ -1454,10 +1425,14 @@ function particleDataUnpack(bs) {
|
|
|
1454
1425
|
});
|
|
1455
1426
|
}
|
|
1456
1427
|
result.keys = keys;
|
|
1457
|
-
// readInt(6) texCount; per tex: readString
|
|
1428
|
+
// readInt(6) texCount; per tex: readString. The writer only emits up
|
|
1429
|
+
// to PDC_MAX_TEX names, so a larger count means the stream is corrupt.
|
|
1458
1430
|
const texCount = bs.readInt(6);
|
|
1431
|
+
if (texCount > ParticleDataMaxTextures) {
|
|
1432
|
+
throw new Error(`Invalid ParticleData texture count: ${texCount}`);
|
|
1433
|
+
}
|
|
1459
1434
|
const textures = [];
|
|
1460
|
-
for (let i = 0; i < texCount
|
|
1435
|
+
for (let i = 0; i < texCount; i++) {
|
|
1461
1436
|
textures.push(bs.readString());
|
|
1462
1437
|
}
|
|
1463
1438
|
result.textures = textures;
|
|
@@ -1805,7 +1780,7 @@ function tsShapeConstructorUnpack(bs) {
|
|
|
1805
1780
|
result.shape = bs.readString();
|
|
1806
1781
|
const count = bs.readInt(7);
|
|
1807
1782
|
const sequences = [];
|
|
1808
|
-
for (let i = 0; i < count
|
|
1783
|
+
for (let i = 0; i < count; i++) {
|
|
1809
1784
|
sequences.push(bs.readString());
|
|
1810
1785
|
}
|
|
1811
1786
|
result.sequences = sequences;
|