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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { huffProcessor } from "./HuffmanProcessor.js";
|
|
2
|
+
/**
|
|
3
|
+
* LSB-first bit packer producing buffers that BitStream reads back
|
|
4
|
+
* bit-for-bit. Mirrors the write side of the engine's BitStream for the
|
|
5
|
+
* primitives the parser consumes; intended for building test vectors and
|
|
6
|
+
* synthetic packets.
|
|
7
|
+
*/
|
|
8
|
+
export class BitWriter {
|
|
9
|
+
bytes = [];
|
|
10
|
+
bitNum = 0;
|
|
11
|
+
getCurPos() {
|
|
12
|
+
return this.bitNum;
|
|
13
|
+
}
|
|
14
|
+
writeFlag(value) {
|
|
15
|
+
return this.writeInt(value ? 1 : 0, 1);
|
|
16
|
+
}
|
|
17
|
+
/** Write the low `bitCount` bits of `value` (up to 32), LSB first. */
|
|
18
|
+
writeInt(value, bitCount) {
|
|
19
|
+
if (!(bitCount >= 0 && bitCount <= 32)) {
|
|
20
|
+
throw new RangeError(`writeInt bitCount out of range: ${bitCount}`);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < bitCount; i++) {
|
|
23
|
+
const byteIndex = this.bitNum >> 3;
|
|
24
|
+
this.bytes[byteIndex] ??= 0;
|
|
25
|
+
// Use arithmetic on the float64 value so bit 31 works for values
|
|
26
|
+
// above 2^31 - 1.
|
|
27
|
+
const bit = Math.floor(value / 2 ** i) % 2 !== 0 ? 1 : 0;
|
|
28
|
+
this.bytes[byteIndex] |= bit << (this.bitNum & 7);
|
|
29
|
+
this.bitNum++;
|
|
30
|
+
}
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
writeSignedInt(value, bitCount) {
|
|
34
|
+
this.writeFlag(value < 0);
|
|
35
|
+
return this.writeInt(Math.abs(value), bitCount - 1);
|
|
36
|
+
}
|
|
37
|
+
writeU8(value) {
|
|
38
|
+
return this.writeInt(value & 0xff, 8);
|
|
39
|
+
}
|
|
40
|
+
writeU32(value) {
|
|
41
|
+
return this.writeInt(value >>> 0, 32);
|
|
42
|
+
}
|
|
43
|
+
writeS32(value) {
|
|
44
|
+
return this.writeInt(value >>> 0, 32);
|
|
45
|
+
}
|
|
46
|
+
writeF32(value) {
|
|
47
|
+
const view = new DataView(new ArrayBuffer(4));
|
|
48
|
+
view.setFloat32(0, value, true);
|
|
49
|
+
return this.writeInt(view.getUint32(0, true), 32);
|
|
50
|
+
}
|
|
51
|
+
/** Write a float in [0, 1] quantized to `bitCount` bits. */
|
|
52
|
+
writeFloat(value, bitCount) {
|
|
53
|
+
return this.writeInt(Math.round(value * (2 ** bitCount - 1)), bitCount);
|
|
54
|
+
}
|
|
55
|
+
writeBytes(bytes) {
|
|
56
|
+
for (let i = 0; i < bytes.length; i++)
|
|
57
|
+
this.writeU8(bytes[i]);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/** Write a Huffman string exactly as the engine's writeString does
|
|
61
|
+
* (no string-buffer prefix optimization). */
|
|
62
|
+
writeString(value) {
|
|
63
|
+
huffProcessor.writeHuffBuffer(this, value);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/** Pad to a byte boundary (plus optional extra zero bytes) and return
|
|
67
|
+
* the packed buffer. */
|
|
68
|
+
finish(padBytes = 0) {
|
|
69
|
+
const total = ((this.bitNum + 7) >> 3) + padBytes;
|
|
70
|
+
const out = new Uint8Array(total);
|
|
71
|
+
for (let i = 0; i < this.bytes.length; i++)
|
|
72
|
+
out[i] = this.bytes[i];
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=BitWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitWriter.js","sourceRoot":"","sources":["../src/BitWriter.ts"],"names":[],"mappings":"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","sourcesContent":["import { huffProcessor } from \"./HuffmanProcessor.js\";\n\n/**\n * LSB-first bit packer producing buffers that BitStream reads back\n * bit-for-bit. Mirrors the write side of the engine's BitStream for the\n * primitives the parser consumes; intended for building test vectors and\n * synthetic packets.\n */\nexport class BitWriter {\n private bytes: number[] = [];\n private bitNum = 0;\n\n getCurPos(): number {\n return this.bitNum;\n }\n\n writeFlag(value: boolean): this {\n return this.writeInt(value ? 1 : 0, 1);\n }\n\n /** Write the low `bitCount` bits of `value` (up to 32), LSB first. */\n writeInt(value: number, bitCount: number): this {\n if (!(bitCount >= 0 && bitCount <= 32)) {\n throw new RangeError(`writeInt bitCount out of range: ${bitCount}`);\n }\n for (let i = 0; i < bitCount; i++) {\n const byteIndex = this.bitNum >> 3;\n this.bytes[byteIndex] ??= 0;\n // Use arithmetic on the float64 value so bit 31 works for values\n // above 2^31 - 1.\n const bit = Math.floor(value / 2 ** i) % 2 !== 0 ? 1 : 0;\n this.bytes[byteIndex] |= bit << (this.bitNum & 7);\n this.bitNum++;\n }\n return this;\n }\n\n writeSignedInt(value: number, bitCount: number): this {\n this.writeFlag(value < 0);\n return this.writeInt(Math.abs(value), bitCount - 1);\n }\n\n writeU8(value: number): this {\n return this.writeInt(value & 0xff, 8);\n }\n\n writeU32(value: number): this {\n return this.writeInt(value >>> 0, 32);\n }\n\n writeS32(value: number): this {\n return this.writeInt(value >>> 0, 32);\n }\n\n writeF32(value: number): this {\n const view = new DataView(new ArrayBuffer(4));\n view.setFloat32(0, value, true);\n return this.writeInt(view.getUint32(0, true), 32);\n }\n\n /** Write a float in [0, 1] quantized to `bitCount` bits. */\n writeFloat(value: number, bitCount: number): this {\n return this.writeInt(Math.round(value * (2 ** bitCount - 1)), bitCount);\n }\n\n writeBytes(bytes: ArrayLike<number>): this {\n for (let i = 0; i < bytes.length; i++) this.writeU8(bytes[i]);\n return this;\n }\n\n /** Write a Huffman string exactly as the engine's writeString does\n * (no string-buffer prefix optimization). */\n writeString(value: string): this {\n huffProcessor.writeHuffBuffer(this, value);\n return this;\n }\n\n /** Pad to a byte boundary (plus optional extra zero bytes) and return\n * the packed buffer. */\n finish(padBytes = 0): Uint8Array {\n const total = ((this.bitNum + 7) >> 3) + padBytes;\n const out = new Uint8Array(total);\n for (let i = 0; i < this.bytes.length; i++) out[i] = this.bytes[i];\n return out;\n }\n}\n"]}
|
package/dist/ClassRegistry.d.ts
CHANGED
|
@@ -22,8 +22,6 @@ export interface ConnectionContext {
|
|
|
22
22
|
getDataBlockParser?: (classId: number) => DataBlockParserEntry | undefined;
|
|
23
23
|
getDataBlockData?: (objectId: number) => ParsedData | undefined;
|
|
24
24
|
getGhostParser?: (classId: number) => GhostParserEntry | undefined;
|
|
25
|
-
/** Ghost index of the ghost currently being parsed (set per-ghost in readGhosts). */
|
|
26
|
-
currentGhostIndex?: number;
|
|
27
25
|
}
|
|
28
26
|
/** Minimal interface for ghost tracker used by parsers. */
|
|
29
27
|
export interface GhostTrackerInterface {
|
|
@@ -32,7 +30,6 @@ export interface GhostTrackerInterface {
|
|
|
32
30
|
export interface GhostEntry {
|
|
33
31
|
classId: number;
|
|
34
32
|
className: string;
|
|
35
|
-
state: ParsedData;
|
|
36
33
|
}
|
|
37
34
|
export interface GhostParserEntry {
|
|
38
35
|
name: string;
|
|
@@ -54,38 +51,30 @@ export interface DataBlockParserEntry {
|
|
|
54
51
|
* via bindDeterministicGhosts/Events/DataBlocks.
|
|
55
52
|
*/
|
|
56
53
|
export declare class ClassRegistry {
|
|
57
|
-
private
|
|
58
|
-
private
|
|
59
|
-
private
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
catalogGhost(entry:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
private events;
|
|
55
|
+
private ghosts;
|
|
56
|
+
private dataBlocks;
|
|
57
|
+
catalogEvent<T extends EventData>(entry: {
|
|
58
|
+
name: string;
|
|
59
|
+
unpack: (bs: BitStream, conn: ConnectionContext) => T;
|
|
60
|
+
}): void;
|
|
61
|
+
catalogGhost<T extends object, P extends object = ParsedData>(entry: {
|
|
62
|
+
name: string;
|
|
63
|
+
unpackUpdate: (bs: BitStream, isInitial: boolean, conn: ConnectionContext) => T;
|
|
64
|
+
readPacketData?: (bs: BitStream, conn: ConnectionContext) => P;
|
|
65
|
+
}): void;
|
|
66
|
+
catalogDataBlock<T extends object>(entry: {
|
|
67
|
+
name: string;
|
|
68
|
+
unpackData: (bs: BitStream) => T;
|
|
69
|
+
}): void;
|
|
71
70
|
bindDeterministicDataBlocks(classNames: readonly string[], classFirst: number): {
|
|
72
71
|
bound: number;
|
|
73
72
|
missing: string[];
|
|
74
73
|
};
|
|
75
|
-
/**
|
|
76
|
-
* Bind all event (NetEvent) parsers deterministically using the known
|
|
77
|
-
* class name mapping. For each class name in the sorted list, if we have
|
|
78
|
-
* a parser in the catalog, bind it to classId = classFirst + index.
|
|
79
|
-
*/
|
|
80
74
|
bindDeterministicEvents(classNames: readonly string[], classFirst: number): {
|
|
81
75
|
bound: number;
|
|
82
76
|
missing: string[];
|
|
83
77
|
};
|
|
84
|
-
/**
|
|
85
|
-
* Bind all ghost (NetObject) parsers deterministically using the known
|
|
86
|
-
* class name mapping. For each class name in the sorted list, if we have
|
|
87
|
-
* a parser in the catalog, bind it to classId = classFirst + index.
|
|
88
|
-
*/
|
|
89
78
|
bindDeterministicGhosts(classNames: readonly string[], classFirst: number): {
|
|
90
79
|
bound: number;
|
|
91
80
|
missing: string[];
|
|
@@ -93,8 +82,14 @@ export declare class ClassRegistry {
|
|
|
93
82
|
getEventParser(classId: number): EventParserEntry | undefined;
|
|
94
83
|
getGhostParser(classId: number): GhostParserEntry | undefined;
|
|
95
84
|
getDataBlockParser(classId: number): DataBlockParserEntry | undefined;
|
|
96
|
-
|
|
85
|
+
getEventClassId(name: string): number | undefined;
|
|
86
|
+
getGhostClassId(name: string): number | undefined;
|
|
87
|
+
getDataBlockClassId(name: string): number | undefined;
|
|
88
|
+
getEventCatalog(): ReadonlyMap<string, EventParserEntry>;
|
|
89
|
+
getGhostCatalog(): ReadonlyMap<string, GhostParserEntry>;
|
|
90
|
+
getDataBlockCatalog(): ReadonlyMap<string, DataBlockParserEntry>;
|
|
97
91
|
getEventBindings(): Map<number, string>;
|
|
98
92
|
getGhostBindings(): Map<number, string>;
|
|
93
|
+
getDataBlockBindings(): Map<number, string>;
|
|
99
94
|
}
|
|
100
95
|
//# sourceMappingURL=ClassRegistry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassRegistry.d.ts","sourceRoot":"","sources":["../src/ClassRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAIpD,MAAM,MAAM,WAAW,GAAG,CACxB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,iBAAiB,KACpB,SAAS,CAAC;AAEf,MAAM,MAAM,iBAAiB,GAAG,CAC9B,EAAE,EAAE,SAAS,EACb,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,iBAAiB,KACpB,UAAU,CAAC;AAEhB,MAAM,MAAM,qBAAqB,GAAG,CAClC,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,iBAAiB,KACpB,UAAU,CAAC;AAEhB,MAAM,MAAM,eAAe,GAAG,CAC5B,EAAE,EAAE,SAAS,KACV,UAAU,CAAC;AAEhB,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,YAAY,EAAE,qBAAqB,CAAC;IACpC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,oBAAoB,GAAG,SAAS,CAAC;IAC3E,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IAChE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ClassRegistry.d.ts","sourceRoot":"","sources":["../src/ClassRegistry.ts"],"names":[],"mappings":"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"}
|
package/dist/ClassRegistry.js
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
function newCatalog() {
|
|
2
|
+
return { byName: new Map(), byClassId: new Map(), classIdByName: new Map() };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Bind every cataloged parser whose name appears in `classNames` to
|
|
6
|
+
* classId = classFirst + index. Names without a parser are reported.
|
|
7
|
+
*/
|
|
8
|
+
function bindCatalog(catalog, classNames, classFirst) {
|
|
9
|
+
let bound = 0;
|
|
10
|
+
const missing = [];
|
|
11
|
+
for (let i = 0; i < classNames.length; i++) {
|
|
12
|
+
const name = classNames[i];
|
|
13
|
+
const entry = catalog.byName.get(name);
|
|
14
|
+
if (entry) {
|
|
15
|
+
catalog.byClassId.set(classFirst + i, entry);
|
|
16
|
+
catalog.classIdByName.set(name, classFirst + i);
|
|
17
|
+
bound++;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
missing.push(name);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { bound, missing };
|
|
24
|
+
}
|
|
25
|
+
function bindingsOf(catalog) {
|
|
26
|
+
const bindings = new Map();
|
|
27
|
+
for (const [id, entry] of catalog.byClassId) {
|
|
28
|
+
bindings.set(id, entry.name);
|
|
29
|
+
}
|
|
30
|
+
return bindings;
|
|
31
|
+
}
|
|
1
32
|
/**
|
|
2
33
|
* Registry mapping classIds to parser functions.
|
|
3
34
|
* ClassIds are assigned deterministically by alphabetical sort (C strcmp)
|
|
@@ -5,114 +36,74 @@
|
|
|
5
36
|
* via bindDeterministicGhosts/Events/DataBlocks.
|
|
6
37
|
*/
|
|
7
38
|
export class ClassRegistry {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Named parser catalog (classId-independent)
|
|
12
|
-
eventCatalog = new Map();
|
|
13
|
-
ghostCatalog = new Map();
|
|
14
|
-
dataBlockCatalog = new Map();
|
|
39
|
+
events = newCatalog();
|
|
40
|
+
ghosts = newCatalog();
|
|
41
|
+
dataBlocks = newCatalog();
|
|
15
42
|
// --- Catalog registration (name → parser, no classId yet) ---
|
|
43
|
+
//
|
|
44
|
+
// Parsers return precisely typed objects (PlayerGhostData, ...), which
|
|
45
|
+
// are stored behind the generic ParsedData shape. The generic signatures
|
|
46
|
+
// let each parser keep its own return type — so a misspelled field is a
|
|
47
|
+
// compile error inside the parser — while the registry erases it.
|
|
16
48
|
catalogEvent(entry) {
|
|
17
|
-
this.
|
|
49
|
+
this.events.byName.set(entry.name, entry);
|
|
18
50
|
}
|
|
19
51
|
catalogGhost(entry) {
|
|
20
|
-
this.
|
|
52
|
+
this.ghosts.byName.set(entry.name, entry);
|
|
21
53
|
}
|
|
22
54
|
catalogDataBlock(entry) {
|
|
23
|
-
this.
|
|
55
|
+
this.dataBlocks.byName.set(entry.name, entry);
|
|
24
56
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* mapping. For each class name in the sorted list, if we have a parser
|
|
28
|
-
* in the catalog, bind it to classId = DataBlockClassFirst + index.
|
|
29
|
-
*/
|
|
57
|
+
// --- Deterministic binding (classId = classFirst + index in the sorted
|
|
58
|
+
// class name list) ---
|
|
30
59
|
bindDeterministicDataBlocks(classNames, classFirst) {
|
|
31
|
-
|
|
32
|
-
const missing = [];
|
|
33
|
-
for (let i = 0; i < classNames.length; i++) {
|
|
34
|
-
const name = classNames[i];
|
|
35
|
-
const entry = this.dataBlockCatalog.get(name);
|
|
36
|
-
if (entry) {
|
|
37
|
-
this.dataBlockParsers.set(classFirst + i, entry);
|
|
38
|
-
bound++;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
missing.push(name);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return { bound, missing };
|
|
60
|
+
return bindCatalog(this.dataBlocks, classNames, classFirst);
|
|
45
61
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Bind all event (NetEvent) parsers deterministically using the known
|
|
48
|
-
* class name mapping. For each class name in the sorted list, if we have
|
|
49
|
-
* a parser in the catalog, bind it to classId = classFirst + index.
|
|
50
|
-
*/
|
|
51
62
|
bindDeterministicEvents(classNames, classFirst) {
|
|
52
|
-
|
|
53
|
-
const missing = [];
|
|
54
|
-
for (let i = 0; i < classNames.length; i++) {
|
|
55
|
-
const name = classNames[i];
|
|
56
|
-
const entry = this.eventCatalog.get(name);
|
|
57
|
-
if (entry) {
|
|
58
|
-
this.eventParsers.set(classFirst + i, entry);
|
|
59
|
-
bound++;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
missing.push(name);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return { bound, missing };
|
|
63
|
+
return bindCatalog(this.events, classNames, classFirst);
|
|
66
64
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Bind all ghost (NetObject) parsers deterministically using the known
|
|
69
|
-
* class name mapping. For each class name in the sorted list, if we have
|
|
70
|
-
* a parser in the catalog, bind it to classId = classFirst + index.
|
|
71
|
-
*/
|
|
72
65
|
bindDeterministicGhosts(classNames, classFirst) {
|
|
73
|
-
|
|
74
|
-
const missing = [];
|
|
75
|
-
for (let i = 0; i < classNames.length; i++) {
|
|
76
|
-
const name = classNames[i];
|
|
77
|
-
const entry = this.ghostCatalog.get(name);
|
|
78
|
-
if (entry) {
|
|
79
|
-
this.ghostParsers.set(classFirst + i, entry);
|
|
80
|
-
bound++;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
missing.push(name);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return { bound, missing };
|
|
66
|
+
return bindCatalog(this.ghosts, classNames, classFirst);
|
|
87
67
|
}
|
|
88
|
-
// --- Lookup ---
|
|
68
|
+
// --- Lookup by classId ---
|
|
89
69
|
getEventParser(classId) {
|
|
90
|
-
return this.
|
|
70
|
+
return this.events.byClassId.get(classId);
|
|
91
71
|
}
|
|
92
72
|
getGhostParser(classId) {
|
|
93
|
-
return this.
|
|
73
|
+
return this.ghosts.byClassId.get(classId);
|
|
94
74
|
}
|
|
95
75
|
getDataBlockParser(classId) {
|
|
96
|
-
return this.
|
|
76
|
+
return this.dataBlocks.byClassId.get(classId);
|
|
77
|
+
}
|
|
78
|
+
// --- Lookup by class name (bound classId) ---
|
|
79
|
+
getEventClassId(name) {
|
|
80
|
+
return this.events.classIdByName.get(name);
|
|
81
|
+
}
|
|
82
|
+
getGhostClassId(name) {
|
|
83
|
+
return this.ghosts.classIdByName.get(name);
|
|
84
|
+
}
|
|
85
|
+
getDataBlockClassId(name) {
|
|
86
|
+
return this.dataBlocks.classIdByName.get(name);
|
|
87
|
+
}
|
|
88
|
+
// --- Catalog access (name → parser, independent of binding) ---
|
|
89
|
+
getEventCatalog() {
|
|
90
|
+
return this.events.byName;
|
|
97
91
|
}
|
|
98
|
-
// --- Catalog access ---
|
|
99
92
|
getGhostCatalog() {
|
|
100
|
-
return this.
|
|
93
|
+
return this.ghosts.byName;
|
|
94
|
+
}
|
|
95
|
+
getDataBlockCatalog() {
|
|
96
|
+
return this.dataBlocks.byName;
|
|
101
97
|
}
|
|
102
|
-
// --- Debug ---
|
|
98
|
+
// --- Debug: classId → parser name ---
|
|
103
99
|
getEventBindings() {
|
|
104
|
-
|
|
105
|
-
for (const [id, entry] of this.eventParsers) {
|
|
106
|
-
bindings.set(id, entry.name);
|
|
107
|
-
}
|
|
108
|
-
return bindings;
|
|
100
|
+
return bindingsOf(this.events);
|
|
109
101
|
}
|
|
110
102
|
getGhostBindings() {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return bindings;
|
|
103
|
+
return bindingsOf(this.ghosts);
|
|
104
|
+
}
|
|
105
|
+
getDataBlockBindings() {
|
|
106
|
+
return bindingsOf(this.dataBlocks);
|
|
116
107
|
}
|
|
117
108
|
}
|
|
118
109
|
//# sourceMappingURL=ClassRegistry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassRegistry.js","sourceRoot":"","sources":["../src/ClassRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClassRegistry.js","sourceRoot":"","sources":["../src/ClassRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BitStream } from \"./BitStream.js\";\nimport type { EventData } from \"./eventDataTypes.js\";\n\n/**\n * Base type for all parsed data objects. Individual parsers return more\n * specific interfaces, but the registry stores them generically.\n */\nexport type ParsedData = { [key: string]: unknown };\n\n// --- Parser function signatures ---\n\nexport type EventParser = (\n bs: BitStream,\n conn: ConnectionContext\n) => EventData;\n\nexport type GhostUpdateParser = (\n bs: BitStream,\n isInitial: boolean,\n conn: ConnectionContext\n) => ParsedData;\n\nexport type GhostPacketDataParser = (\n bs: BitStream,\n conn: ConnectionContext\n) => ParsedData;\n\nexport type DataBlockParser = (\n bs: BitStream\n) => ParsedData;\n\n/** Shared context passed to parsers from the connection state. */\nexport interface ConnectionContext {\n compressionPoint: { x: number; y: number; z: number };\n ghostTracker: GhostTrackerInterface;\n getDataBlockParser?: (classId: number) => DataBlockParserEntry | undefined;\n getDataBlockData?: (objectId: number) => ParsedData | undefined;\n getGhostParser?: (classId: number) => GhostParserEntry | undefined;\n}\n\n/** Minimal interface for ghost tracker used by parsers. */\nexport interface GhostTrackerInterface {\n getGhost(index: number): GhostEntry | undefined;\n}\n\nexport interface GhostEntry {\n classId: number;\n className: string;\n}\n\nexport interface GhostParserEntry {\n name: string;\n unpackUpdate: GhostUpdateParser;\n readPacketData?: GhostPacketDataParser;\n}\n\nexport interface EventParserEntry {\n name: string;\n unpack: EventParser;\n}\n\nexport interface DataBlockParserEntry {\n name: string;\n unpackData: DataBlockParser;\n}\n\ninterface Catalog<T extends { name: string }> {\n byName: Map<string, T>;\n byClassId: Map<number, T>;\n classIdByName: Map<string, number>;\n}\n\nfunction newCatalog<T extends { name: string }>(): Catalog<T> {\n return { byName: new Map(), byClassId: new Map(), classIdByName: new Map() };\n}\n\n/**\n * Bind every cataloged parser whose name appears in `classNames` to\n * classId = classFirst + index. Names without a parser are reported.\n */\nfunction bindCatalog<T extends { name: string }>(\n catalog: Catalog<T>,\n classNames: readonly string[],\n classFirst: number,\n): { bound: number; missing: string[] } {\n let bound = 0;\n const missing: string[] = [];\n for (let i = 0; i < classNames.length; i++) {\n const name = classNames[i];\n const entry = catalog.byName.get(name);\n if (entry) {\n catalog.byClassId.set(classFirst + i, entry);\n catalog.classIdByName.set(name, classFirst + i);\n bound++;\n } else {\n missing.push(name);\n }\n }\n return { bound, missing };\n}\n\nfunction bindingsOf<T extends { name: string }>(\n catalog: Catalog<T>,\n): Map<number, string> {\n const bindings = new Map<number, string>();\n for (const [id, entry] of catalog.byClassId) {\n bindings.set(id, entry.name);\n }\n return bindings;\n}\n\n/**\n * Registry mapping classIds to parser functions.\n * ClassIds are assigned deterministically by alphabetical sort (C strcmp)\n * at engine link time. Parsers are cataloged by name and bound to classIds\n * via bindDeterministicGhosts/Events/DataBlocks.\n */\nexport class ClassRegistry {\n private events = newCatalog<EventParserEntry>();\n private ghosts = newCatalog<GhostParserEntry>();\n private dataBlocks = newCatalog<DataBlockParserEntry>();\n\n // --- Catalog registration (name → parser, no classId yet) ---\n //\n // Parsers return precisely typed objects (PlayerGhostData, ...), which\n // are stored behind the generic ParsedData shape. The generic signatures\n // let each parser keep its own return type — so a misspelled field is a\n // compile error inside the parser — while the registry erases it.\n\n catalogEvent<T extends EventData>(entry: {\n name: string;\n unpack: (bs: BitStream, conn: ConnectionContext) => T;\n }): void {\n this.events.byName.set(entry.name, entry);\n }\n\n catalogGhost<T extends object, P extends object = ParsedData>(entry: {\n name: string;\n unpackUpdate: (bs: BitStream, isInitial: boolean, conn: ConnectionContext) => T;\n readPacketData?: (bs: BitStream, conn: ConnectionContext) => P;\n }): void {\n this.ghosts.byName.set(entry.name, entry as unknown as GhostParserEntry);\n }\n\n catalogDataBlock<T extends object>(entry: {\n name: string;\n unpackData: (bs: BitStream) => T;\n }): void {\n this.dataBlocks.byName.set(\n entry.name,\n entry as unknown as DataBlockParserEntry,\n );\n }\n\n // --- Deterministic binding (classId = classFirst + index in the sorted\n // class name list) ---\n\n bindDeterministicDataBlocks(\n classNames: readonly string[],\n classFirst: number,\n ): { bound: number; missing: string[] } {\n return bindCatalog(this.dataBlocks, classNames, classFirst);\n }\n\n bindDeterministicEvents(\n classNames: readonly string[],\n classFirst: number,\n ): { bound: number; missing: string[] } {\n return bindCatalog(this.events, classNames, classFirst);\n }\n\n bindDeterministicGhosts(\n classNames: readonly string[],\n classFirst: number,\n ): { bound: number; missing: string[] } {\n return bindCatalog(this.ghosts, classNames, classFirst);\n }\n\n // --- Lookup by classId ---\n\n getEventParser(classId: number): EventParserEntry | undefined {\n return this.events.byClassId.get(classId);\n }\n\n getGhostParser(classId: number): GhostParserEntry | undefined {\n return this.ghosts.byClassId.get(classId);\n }\n\n getDataBlockParser(classId: number): DataBlockParserEntry | undefined {\n return this.dataBlocks.byClassId.get(classId);\n }\n\n // --- Lookup by class name (bound classId) ---\n\n getEventClassId(name: string): number | undefined {\n return this.events.classIdByName.get(name);\n }\n\n getGhostClassId(name: string): number | undefined {\n return this.ghosts.classIdByName.get(name);\n }\n\n getDataBlockClassId(name: string): number | undefined {\n return this.dataBlocks.classIdByName.get(name);\n }\n\n // --- Catalog access (name → parser, independent of binding) ---\n\n getEventCatalog(): ReadonlyMap<string, EventParserEntry> {\n return this.events.byName;\n }\n\n getGhostCatalog(): ReadonlyMap<string, GhostParserEntry> {\n return this.ghosts.byName;\n }\n\n getDataBlockCatalog(): ReadonlyMap<string, DataBlockParserEntry> {\n return this.dataBlocks.byName;\n }\n\n // --- Debug: classId → parser name ---\n\n getEventBindings(): Map<number, string> {\n return bindingsOf(this.events);\n }\n\n getGhostBindings(): Map<number, string> {\n return bindingsOf(this.ghosts);\n }\n\n getDataBlockBindings(): Map<number, string> {\n return bindingsOf(this.dataBlocks);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataBlockParsers.d.ts","sourceRoot":"","sources":["../src/DataBlockParsers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"DataBlockParsers.d.ts","sourceRoot":"","sources":["../src/DataBlockParsers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAuwExD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CA0OtE"}
|