@rhyster/wow-casc-dbc 2.3.0 → 2.4.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 +47 -4
- package/dist/index.cjs +180 -67
- package/dist/index.d.cts +29 -2
- package/dist/index.d.mts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.mjs +180 -68
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,7 +4,11 @@ Node.js tool to fetch World of Warcraft data files from CASC and parse DBC/DB2 f
|
|
|
4
4
|
|
|
5
5
|
## Snippet
|
|
6
6
|
|
|
7
|
+
### Basic Usage
|
|
8
|
+
|
|
7
9
|
```javascript
|
|
10
|
+
import { CASCClient, WDCReader, DBDParser } from '@rhyster/wow-casc-dbc';
|
|
11
|
+
|
|
8
12
|
// Get version
|
|
9
13
|
const region = 'us';
|
|
10
14
|
const product = 'wow';
|
|
@@ -14,10 +18,10 @@ const version = await CASCClient.getProductVersion(region, product);
|
|
|
14
18
|
const client = new CASCClient(region, product, version);
|
|
15
19
|
await client.init();
|
|
16
20
|
await client.loadRemoteTACTKeys();
|
|
17
|
-
await client.loadRemoteListFile();
|
|
21
|
+
await client.loadRemoteListFile(); // pretty slow, recommend to provide fileDataID directly
|
|
18
22
|
|
|
19
23
|
// Fetch file
|
|
20
|
-
const fileDataID = client.getFileDataIDByName('dbfilesclient/questxp.db2');
|
|
24
|
+
const fileDataID = client.getFileDataIDByName('dbfilesclient/questxp.db2'); // see previous line
|
|
21
25
|
const cKeys = client.getContentKeysByFileDataID(fileDataID);
|
|
22
26
|
const cKey = cKeys.find((data) => !!(data.localeFlags & CASCClient.LocaleFlags.enUS));
|
|
23
27
|
const { buffer } = await client.getFileByContentKey(cKey.cKey);
|
|
@@ -27,8 +31,47 @@ const reader = new WDCReader(buffer);
|
|
|
27
31
|
const parser = await DBDParser.parse(reader);
|
|
28
32
|
|
|
29
33
|
// Access DB2 file
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
reader.getAllIDs().forEach((id) => {
|
|
35
|
+
const rowFields = reader.getRowData(id);
|
|
36
|
+
});
|
|
37
|
+
parser.getAllIDs().forEach((id) => {
|
|
38
|
+
const rowObject = parser.getRowData(id);
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Partial Decrypt
|
|
43
|
+
|
|
44
|
+
Some file is encrypted and no key released yet. For DB2 files, you can ignore the encrypted part and parse the others.
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// ...
|
|
48
|
+
|
|
49
|
+
const result = await client.getFileByContentKey(cKey.cKey, true);
|
|
50
|
+
const reader = new WDCReader(result.buffer, result.type === 'partial' ? result.blocks : []);
|
|
51
|
+
const parser = await DBDParser.parse(reader);
|
|
52
|
+
|
|
53
|
+
// ...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Hotfix
|
|
57
|
+
|
|
58
|
+
Applying hotfix requires `DBCache.bin` file from the client, and it seems the only way to get this is from the client. So, you need to search for `DBCache.bin` yourself, like `<WoWPath>/_retail_/Cache/ADB/enUS/DBCache.bin` or download it somewhere.
|
|
59
|
+
|
|
60
|
+
It's also important to compare build, region and locale with the db2 file that to be patched to avoid broken data.
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
// ...
|
|
64
|
+
|
|
65
|
+
const dbcache = await fs.readFile('path/to/DBCache.bin');
|
|
66
|
+
const buffer = await fs.readFile('path/to/name.db2');
|
|
67
|
+
|
|
68
|
+
const adb = new ADBReader(dbcache);
|
|
69
|
+
assert(adb.build === parseInt(version.BuildId, 10));
|
|
70
|
+
|
|
71
|
+
const reader = new WDCReader(buffer, [], adb);
|
|
72
|
+
const parser = await DBDParser.parse(reader);
|
|
73
|
+
|
|
74
|
+
// ...
|
|
32
75
|
```
|
|
33
76
|
|
|
34
77
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -19,17 +19,17 @@ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
|
19
19
|
const http__default = /*#__PURE__*/_interopDefaultCompat(http);
|
|
20
20
|
const zlib__default = /*#__PURE__*/_interopDefaultCompat(zlib);
|
|
21
21
|
|
|
22
|
-
var __defProp$
|
|
23
|
-
var __defNormalProp$
|
|
24
|
-
var __publicField$
|
|
25
|
-
__defNormalProp$
|
|
22
|
+
var __defProp$6 = Object.defineProperty;
|
|
23
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
24
|
+
var __publicField$6 = (obj, key, value) => {
|
|
25
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
26
26
|
return value;
|
|
27
27
|
};
|
|
28
28
|
class Store {
|
|
29
29
|
constructor(dataFile) {
|
|
30
|
-
__publicField$
|
|
31
|
-
__publicField$
|
|
32
|
-
__publicField$
|
|
30
|
+
__publicField$6(this, "data");
|
|
31
|
+
__publicField$6(this, "dataFile");
|
|
32
|
+
__publicField$6(this, "promise");
|
|
33
33
|
this.dataFile = dataFile;
|
|
34
34
|
this.data = {};
|
|
35
35
|
this.promise = new Promise((resolve) => {
|
|
@@ -294,21 +294,21 @@ const parseArchiveIndex = (buffer, cKey) => {
|
|
|
294
294
|
return result;
|
|
295
295
|
};
|
|
296
296
|
|
|
297
|
-
var __defProp$
|
|
298
|
-
var __defNormalProp$
|
|
299
|
-
var __publicField$
|
|
300
|
-
__defNormalProp$
|
|
297
|
+
var __defProp$5 = Object.defineProperty;
|
|
298
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
299
|
+
var __publicField$5 = (obj, key, value) => {
|
|
300
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
301
301
|
return value;
|
|
302
302
|
};
|
|
303
303
|
class Salsa20 {
|
|
304
304
|
constructor(key, nonce) {
|
|
305
|
-
__publicField$
|
|
306
|
-
__publicField$
|
|
307
|
-
__publicField$
|
|
308
|
-
__publicField$
|
|
309
|
-
__publicField$
|
|
310
|
-
__publicField$
|
|
311
|
-
__publicField$
|
|
305
|
+
__publicField$5(this, "fixed");
|
|
306
|
+
__publicField$5(this, "key");
|
|
307
|
+
__publicField$5(this, "nonce");
|
|
308
|
+
__publicField$5(this, "counter", new Uint32Array([0, 0]));
|
|
309
|
+
__publicField$5(this, "state", new Uint32Array(16));
|
|
310
|
+
__publicField$5(this, "block", new Uint8Array(64));
|
|
311
|
+
__publicField$5(this, "position", 0);
|
|
312
312
|
assert__default(key.length === 32 || key.length === 16, "Salsa20 requires 128-bit or 256-bit key");
|
|
313
313
|
assert__default(nonce.length === 8, "Salsa20 requires 64-bit nonce");
|
|
314
314
|
this.key = new Uint32Array(8);
|
|
@@ -411,10 +411,10 @@ class Salsa20 {
|
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
413
|
|
|
414
|
-
var __defProp$
|
|
415
|
-
var __defNormalProp$
|
|
416
|
-
var __publicField$
|
|
417
|
-
__defNormalProp$
|
|
414
|
+
var __defProp$4 = Object.defineProperty;
|
|
415
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
416
|
+
var __publicField$4 = (obj, key, value) => {
|
|
417
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
418
418
|
return value;
|
|
419
419
|
};
|
|
420
420
|
const BLTE_MAGIC = 1112298565;
|
|
@@ -422,12 +422,12 @@ const ENC_TYPE_SALSA20 = 83;
|
|
|
422
422
|
const EMPTY_HASH = "00000000000000000000000000000000";
|
|
423
423
|
class BLTEReader {
|
|
424
424
|
constructor(buffer, eKey, keys = /* @__PURE__ */ new Map()) {
|
|
425
|
-
__publicField$
|
|
426
|
-
__publicField$
|
|
427
|
-
__publicField$
|
|
428
|
-
__publicField$
|
|
429
|
-
__publicField$
|
|
430
|
-
__publicField$
|
|
425
|
+
__publicField$4(this, "buffer");
|
|
426
|
+
__publicField$4(this, "blte");
|
|
427
|
+
__publicField$4(this, "blocks", []);
|
|
428
|
+
__publicField$4(this, "keys");
|
|
429
|
+
__publicField$4(this, "processedBlock", 0);
|
|
430
|
+
__publicField$4(this, "processedOffset", 0);
|
|
431
431
|
this.blte = buffer;
|
|
432
432
|
this.buffer = Buffer.alloc(0);
|
|
433
433
|
this.keys = keys;
|
|
@@ -895,10 +895,10 @@ const getNameHash = (name) => {
|
|
|
895
895
|
return `${pc.toString(16).padStart(8, "0")}${pb.toString(16).padStart(8, "0")}`;
|
|
896
896
|
};
|
|
897
897
|
|
|
898
|
-
var __defProp$
|
|
899
|
-
var __defNormalProp$
|
|
900
|
-
var __publicField$
|
|
901
|
-
__defNormalProp$
|
|
898
|
+
var __defProp$3 = Object.defineProperty;
|
|
899
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
900
|
+
var __publicField$3 = (obj, key, value) => {
|
|
901
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
902
902
|
return value;
|
|
903
903
|
};
|
|
904
904
|
const WDC5_MAGIC = 1464091445;
|
|
@@ -924,17 +924,18 @@ const readBitpackedValue = (buffer, fieldOffsetBits, fieldSizeBits, signed = fal
|
|
|
924
924
|
return signed ? BigInt.asIntN(fieldSizeBits, value >> BigInt(bitOffset)) : BigInt.asUintN(fieldSizeBits, value >> BigInt(bitOffset));
|
|
925
925
|
};
|
|
926
926
|
class WDCReader {
|
|
927
|
-
constructor(buffer, blocks = []) {
|
|
928
|
-
__publicField$
|
|
929
|
-
__publicField$
|
|
930
|
-
__publicField$
|
|
931
|
-
__publicField$
|
|
932
|
-
__publicField$
|
|
933
|
-
__publicField$
|
|
934
|
-
__publicField$
|
|
935
|
-
__publicField$
|
|
936
|
-
__publicField$
|
|
937
|
-
__publicField$
|
|
927
|
+
constructor(buffer, blocks = [], adb) {
|
|
928
|
+
__publicField$3(this, "tableHash");
|
|
929
|
+
__publicField$3(this, "layoutHash");
|
|
930
|
+
__publicField$3(this, "locale");
|
|
931
|
+
__publicField$3(this, "isNormal");
|
|
932
|
+
__publicField$3(this, "hasRelationshipData");
|
|
933
|
+
__publicField$3(this, "fields");
|
|
934
|
+
__publicField$3(this, "fieldsInfo");
|
|
935
|
+
__publicField$3(this, "rows", /* @__PURE__ */ new Map());
|
|
936
|
+
__publicField$3(this, "relationships", /* @__PURE__ */ new Map());
|
|
937
|
+
__publicField$3(this, "copyTable", /* @__PURE__ */ new Map());
|
|
938
|
+
__publicField$3(this, "hotfixes", /* @__PURE__ */ new Map());
|
|
938
939
|
const magic = buffer.readUInt32BE(0);
|
|
939
940
|
const fieldCount = buffer.readUInt32LE(140);
|
|
940
941
|
const recordSize = buffer.readUInt32LE(144);
|
|
@@ -1339,11 +1340,43 @@ class WDCReader {
|
|
|
1339
1340
|
}
|
|
1340
1341
|
}
|
|
1341
1342
|
});
|
|
1343
|
+
const entries = adb?.tableEntries.get(tableHash);
|
|
1344
|
+
entries?.filter((entry) => entry.pushID !== -1).sort((a, b) => a.pushID - b.pushID).forEach((entry) => {
|
|
1345
|
+
switch (entry.recordState) {
|
|
1346
|
+
case 1:
|
|
1347
|
+
this.hotfixes.set(entry.recordID, { type: "modify", data: entry.data });
|
|
1348
|
+
break;
|
|
1349
|
+
case 2:
|
|
1350
|
+
this.hotfixes.set(entry.recordID, { type: "delete" });
|
|
1351
|
+
break;
|
|
1352
|
+
case 3:
|
|
1353
|
+
this.hotfixes.delete(entry.recordID);
|
|
1354
|
+
break;
|
|
1355
|
+
case 4:
|
|
1356
|
+
break;
|
|
1357
|
+
default:
|
|
1358
|
+
throw new Error(`Unknown record state: ${entry.recordState.toString()}`);
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1342
1361
|
}
|
|
1343
1362
|
getAllIDs() {
|
|
1344
1363
|
return [...this.rows.keys(), ...this.copyTable.keys()];
|
|
1345
1364
|
}
|
|
1346
1365
|
getRowData(id) {
|
|
1366
|
+
const hotfix = this.hotfixes.get(id);
|
|
1367
|
+
if (hotfix) {
|
|
1368
|
+
switch (hotfix.type) {
|
|
1369
|
+
case "modify":
|
|
1370
|
+
return {
|
|
1371
|
+
type: "sparse",
|
|
1372
|
+
data: hotfix.data
|
|
1373
|
+
};
|
|
1374
|
+
case "delete":
|
|
1375
|
+
return void 0;
|
|
1376
|
+
default:
|
|
1377
|
+
throw new Error("Unreachable");
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1347
1380
|
const dst = this.copyTable.get(id);
|
|
1348
1381
|
if (dst) {
|
|
1349
1382
|
return this.rows.get(dst);
|
|
@@ -1405,10 +1438,10 @@ const formatFileSize = (input) => {
|
|
|
1405
1438
|
return result.join(" ");
|
|
1406
1439
|
};
|
|
1407
1440
|
|
|
1408
|
-
var __defProp$
|
|
1409
|
-
var __defNormalProp$
|
|
1410
|
-
var __publicField$
|
|
1411
|
-
__defNormalProp$
|
|
1441
|
+
var __defProp$2 = Object.defineProperty;
|
|
1442
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1443
|
+
var __publicField$2 = (obj, key, value) => {
|
|
1444
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1412
1445
|
return value;
|
|
1413
1446
|
};
|
|
1414
1447
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
@@ -1421,13 +1454,13 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
1421
1454
|
const textLogLevel = ["ERROR", "WARN", "INFO", "DEBUG"];
|
|
1422
1455
|
class CASCClient {
|
|
1423
1456
|
constructor(region, product, version, logLevel = 2 /* info */) {
|
|
1424
|
-
__publicField$
|
|
1425
|
-
__publicField$
|
|
1426
|
-
__publicField$
|
|
1427
|
-
__publicField$
|
|
1428
|
-
__publicField$
|
|
1429
|
-
__publicField$
|
|
1430
|
-
__publicField$
|
|
1457
|
+
__publicField$2(this, "region");
|
|
1458
|
+
__publicField$2(this, "product");
|
|
1459
|
+
__publicField$2(this, "version");
|
|
1460
|
+
__publicField$2(this, "name2FileDataID", /* @__PURE__ */ new Map());
|
|
1461
|
+
__publicField$2(this, "keys", /* @__PURE__ */ new Map());
|
|
1462
|
+
__publicField$2(this, "preload");
|
|
1463
|
+
__publicField$2(this, "logLevel");
|
|
1431
1464
|
this.region = region;
|
|
1432
1465
|
this.product = product;
|
|
1433
1466
|
this.version = version;
|
|
@@ -1572,7 +1605,7 @@ class CASCClient {
|
|
|
1572
1605
|
]);
|
|
1573
1606
|
const keysReader = new WDCReader(keysResult.buffer);
|
|
1574
1607
|
const lookupReader = new WDCReader(lookupResult.buffer);
|
|
1575
|
-
|
|
1608
|
+
lookupReader.getAllIDs().forEach((keyID) => {
|
|
1576
1609
|
const lookupRow = lookupReader.rows.get(keyID);
|
|
1577
1610
|
const keyRow = keysReader.rows.get(keyID);
|
|
1578
1611
|
if (keyRow) {
|
|
@@ -1588,6 +1621,31 @@ class CASCClient {
|
|
|
1588
1621
|
}
|
|
1589
1622
|
});
|
|
1590
1623
|
}
|
|
1624
|
+
loadBroadcastTACTKeys(adb) {
|
|
1625
|
+
adb.tableEntries.get(35137211)?.forEach(({ data }) => {
|
|
1626
|
+
if (data.byteLength > 0) {
|
|
1627
|
+
let pointer = 0;
|
|
1628
|
+
while (data[pointer] !== 0) {
|
|
1629
|
+
pointer += 1;
|
|
1630
|
+
}
|
|
1631
|
+
pointer += 1;
|
|
1632
|
+
while (data[pointer] !== 0) {
|
|
1633
|
+
pointer += 1;
|
|
1634
|
+
}
|
|
1635
|
+
pointer += 1 + 43;
|
|
1636
|
+
if (pointer < data.byteLength) {
|
|
1637
|
+
const extraTableHash = data.readUInt32LE(pointer);
|
|
1638
|
+
if (extraTableHash === 3744420815) {
|
|
1639
|
+
const keyName = data.readBigUInt64LE(pointer + 4).toString(16).padStart(16, "0");
|
|
1640
|
+
const key = Uint8Array.from(data.subarray(pointer + 12));
|
|
1641
|
+
if (!this.keys.has(keyName)) {
|
|
1642
|
+
this.keys.set(keyName, key);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1591
1649
|
getFileDataIDByName(name) {
|
|
1592
1650
|
assert__default(this.preload, "Client not initialized");
|
|
1593
1651
|
const { rootFile } = this.preload;
|
|
@@ -1641,14 +1699,14 @@ class CASCClient {
|
|
|
1641
1699
|
};
|
|
1642
1700
|
}
|
|
1643
1701
|
}
|
|
1644
|
-
__publicField$
|
|
1645
|
-
__publicField$
|
|
1646
|
-
__publicField$
|
|
1702
|
+
__publicField$2(CASCClient, "LocaleFlags", LocaleFlags);
|
|
1703
|
+
__publicField$2(CASCClient, "ContentFlags", ContentFlags);
|
|
1704
|
+
__publicField$2(CASCClient, "LogLevel", LogLevel);
|
|
1647
1705
|
|
|
1648
|
-
var __defProp = Object.defineProperty;
|
|
1649
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1650
|
-
var __publicField = (obj, key, value) => {
|
|
1651
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1706
|
+
var __defProp$1 = Object.defineProperty;
|
|
1707
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1708
|
+
var __publicField$1 = (obj, key, value) => {
|
|
1709
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1652
1710
|
return value;
|
|
1653
1711
|
};
|
|
1654
1712
|
const PATTERN_COLUMN = /^(int|float|locstring|string)(<[^:]+::[^>]+>)?\s([^\s]+)/;
|
|
@@ -1684,10 +1742,10 @@ const castBigInt64 = (value, srcSigned, dstSigned) => {
|
|
|
1684
1742
|
};
|
|
1685
1743
|
class DBDParser {
|
|
1686
1744
|
constructor(wdc) {
|
|
1687
|
-
__publicField(this, "wdc");
|
|
1688
|
-
__publicField(this, "definitions", /* @__PURE__ */ new Map());
|
|
1689
|
-
__publicField(this, "columns", []);
|
|
1690
|
-
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
1745
|
+
__publicField$1(this, "wdc");
|
|
1746
|
+
__publicField$1(this, "definitions", /* @__PURE__ */ new Map());
|
|
1747
|
+
__publicField$1(this, "columns", []);
|
|
1748
|
+
__publicField$1(this, "cache", /* @__PURE__ */ new Map());
|
|
1691
1749
|
this.wdc = wdc;
|
|
1692
1750
|
}
|
|
1693
1751
|
async init() {
|
|
@@ -1855,6 +1913,9 @@ class DBDParser {
|
|
|
1855
1913
|
if (column.isID) {
|
|
1856
1914
|
data[column.name] = id;
|
|
1857
1915
|
if (column.isInline) {
|
|
1916
|
+
const currField = this.wdc.fields[fieldIndex];
|
|
1917
|
+
const size = Math.ceil((column.size ?? 32 - currField.size) / 8);
|
|
1918
|
+
offset += size;
|
|
1858
1919
|
fieldIndex += 1;
|
|
1859
1920
|
}
|
|
1860
1921
|
} else if (column.isInline) {
|
|
@@ -1876,7 +1937,7 @@ class DBDParser {
|
|
|
1876
1937
|
const size = Math.ceil((column.size ?? 32 - currField.size) / 8);
|
|
1877
1938
|
let count;
|
|
1878
1939
|
if (fieldIndex + 1 < this.wdc.fields.length) {
|
|
1879
|
-
count = (nextField.position - currField.position) / size;
|
|
1940
|
+
count = Math.max((nextField.position - currField.position) / size, 1);
|
|
1880
1941
|
} else {
|
|
1881
1942
|
count = column.arraySize ? (buffer.byteLength - offset) / size : 1;
|
|
1882
1943
|
}
|
|
@@ -1910,6 +1971,58 @@ class DBDParser {
|
|
|
1910
1971
|
}
|
|
1911
1972
|
}
|
|
1912
1973
|
|
|
1974
|
+
var __defProp = Object.defineProperty;
|
|
1975
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1976
|
+
var __publicField = (obj, key, value) => {
|
|
1977
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1978
|
+
return value;
|
|
1979
|
+
};
|
|
1980
|
+
const ADB_MAGIC = 1481004104;
|
|
1981
|
+
class ADBReader {
|
|
1982
|
+
constructor(buffer) {
|
|
1983
|
+
__publicField(this, "build");
|
|
1984
|
+
__publicField(this, "entries", []);
|
|
1985
|
+
__publicField(this, "tableEntries", /* @__PURE__ */ new Map());
|
|
1986
|
+
const magic = buffer.readUInt32BE(0);
|
|
1987
|
+
assert__default(magic === ADB_MAGIC, `[ADB]: Invalid magic: ${magic.toString(16).padStart(8, "0")}`);
|
|
1988
|
+
const version = buffer.readUInt32LE(4);
|
|
1989
|
+
assert__default(version === 9, `[ADB]: Invalid version: ${version.toString()}`);
|
|
1990
|
+
const build = buffer.readUInt32LE(8);
|
|
1991
|
+
this.build = build;
|
|
1992
|
+
let pointer = 44;
|
|
1993
|
+
while (pointer < buffer.byteLength) {
|
|
1994
|
+
const offset = pointer;
|
|
1995
|
+
const entryMagic = buffer.readUInt32BE(offset);
|
|
1996
|
+
assert__default(entryMagic === ADB_MAGIC, `[ADB]: Invalid entry magic: ${magic.toString(16).padStart(8, "0")}`);
|
|
1997
|
+
const regionID = buffer.readInt32LE(offset + 4);
|
|
1998
|
+
const pushID = buffer.readInt32LE(offset + 8);
|
|
1999
|
+
const uniqueID = buffer.readUInt32LE(offset + 12);
|
|
2000
|
+
const tableHash = buffer.readUInt32LE(offset + 16);
|
|
2001
|
+
const recordID = buffer.readUInt32LE(offset + 20);
|
|
2002
|
+
const dataSize = buffer.readUInt32LE(offset + 24);
|
|
2003
|
+
const recordState = buffer.readUInt32LE(offset + 28);
|
|
2004
|
+
const data = buffer.subarray(offset + 32, offset + 32 + dataSize);
|
|
2005
|
+
const entry = {
|
|
2006
|
+
regionID,
|
|
2007
|
+
pushID,
|
|
2008
|
+
uniqueID,
|
|
2009
|
+
tableHash,
|
|
2010
|
+
recordID,
|
|
2011
|
+
dataSize,
|
|
2012
|
+
recordState,
|
|
2013
|
+
data
|
|
2014
|
+
};
|
|
2015
|
+
this.entries.push(entry);
|
|
2016
|
+
if (!this.tableEntries.has(tableHash)) {
|
|
2017
|
+
this.tableEntries.set(tableHash, []);
|
|
2018
|
+
}
|
|
2019
|
+
this.tableEntries.get(tableHash)?.push(entry);
|
|
2020
|
+
pointer += 32 + dataSize;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
exports.ADBReader = ADBReader;
|
|
1913
2026
|
exports.CASCClient = CASCClient;
|
|
1914
2027
|
exports.DBDParser = DBDParser;
|
|
1915
2028
|
exports.WDCReader = WDCReader;
|
package/dist/index.d.cts
CHANGED
|
@@ -42,6 +42,23 @@ interface MissingKeyBlock {
|
|
|
42
42
|
keyName: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
interface HotfixEntry {
|
|
46
|
+
regionID: number;
|
|
47
|
+
pushID: number;
|
|
48
|
+
uniqueID: number;
|
|
49
|
+
tableHash: number;
|
|
50
|
+
recordID: number;
|
|
51
|
+
dataSize: number;
|
|
52
|
+
recordState: number;
|
|
53
|
+
data: Buffer;
|
|
54
|
+
}
|
|
55
|
+
declare class ADBReader {
|
|
56
|
+
build: number;
|
|
57
|
+
entries: HotfixEntry[];
|
|
58
|
+
tableEntries: Map<number, HotfixEntry[]>;
|
|
59
|
+
constructor(buffer: Buffer);
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
interface ClientPreloadData {
|
|
46
63
|
prefixes: string[];
|
|
47
64
|
archives: ReturnType<typeof parseArchiveIndex>;
|
|
@@ -111,6 +128,7 @@ declare class CASCClient {
|
|
|
111
128
|
loadRemoteListFile(): Promise<void>;
|
|
112
129
|
loadRemoteTACTKeys(): Promise<void>;
|
|
113
130
|
loadTACTKeys(): Promise<void>;
|
|
131
|
+
loadBroadcastTACTKeys(adb: ADBReader): void;
|
|
114
132
|
getFileDataIDByName(name: string): number | undefined;
|
|
115
133
|
getContentKeysByFileDataID(fileDataID: number): FileInfo[] | undefined;
|
|
116
134
|
getFileByContentKey(cKey: string, allowMissingKey?: false): Promise<FileFetchResultFull>;
|
|
@@ -192,6 +210,14 @@ interface SparseRow {
|
|
|
192
210
|
type: 'sparse';
|
|
193
211
|
data: Buffer;
|
|
194
212
|
}
|
|
213
|
+
interface HotfixModify {
|
|
214
|
+
type: 'modify';
|
|
215
|
+
data: Buffer;
|
|
216
|
+
}
|
|
217
|
+
interface HotfixDelete {
|
|
218
|
+
type: 'delete';
|
|
219
|
+
}
|
|
220
|
+
type Hotfix = HotfixModify | HotfixDelete;
|
|
195
221
|
declare class WDCReader {
|
|
196
222
|
readonly tableHash: number;
|
|
197
223
|
readonly layoutHash: number;
|
|
@@ -203,7 +229,8 @@ declare class WDCReader {
|
|
|
203
229
|
readonly rows: Map<number, SparseRow | ParsedField[]>;
|
|
204
230
|
readonly relationships: Map<number, number>;
|
|
205
231
|
readonly copyTable: Map<number, number>;
|
|
206
|
-
|
|
232
|
+
readonly hotfixes: Map<number, Hotfix>;
|
|
233
|
+
constructor(buffer: Buffer, blocks?: MissingKeyBlock[], adb?: ADBReader);
|
|
207
234
|
getAllIDs(): number[];
|
|
208
235
|
getRowData(id: number): ParsedField[] | SparseRow | undefined;
|
|
209
236
|
getRowRelationship(id: number): number | undefined;
|
|
@@ -232,4 +259,4 @@ declare class DBDParser {
|
|
|
232
259
|
getRowData(id: number): Record<string, ColumnData | ColumnData[]> | undefined;
|
|
233
260
|
}
|
|
234
261
|
|
|
235
|
-
export { CASCClient, DBDParser, WDCReader };
|
|
262
|
+
export { ADBReader, CASCClient, DBDParser, WDCReader };
|
package/dist/index.d.mts
CHANGED
|
@@ -42,6 +42,23 @@ interface MissingKeyBlock {
|
|
|
42
42
|
keyName: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
interface HotfixEntry {
|
|
46
|
+
regionID: number;
|
|
47
|
+
pushID: number;
|
|
48
|
+
uniqueID: number;
|
|
49
|
+
tableHash: number;
|
|
50
|
+
recordID: number;
|
|
51
|
+
dataSize: number;
|
|
52
|
+
recordState: number;
|
|
53
|
+
data: Buffer;
|
|
54
|
+
}
|
|
55
|
+
declare class ADBReader {
|
|
56
|
+
build: number;
|
|
57
|
+
entries: HotfixEntry[];
|
|
58
|
+
tableEntries: Map<number, HotfixEntry[]>;
|
|
59
|
+
constructor(buffer: Buffer);
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
interface ClientPreloadData {
|
|
46
63
|
prefixes: string[];
|
|
47
64
|
archives: ReturnType<typeof parseArchiveIndex>;
|
|
@@ -111,6 +128,7 @@ declare class CASCClient {
|
|
|
111
128
|
loadRemoteListFile(): Promise<void>;
|
|
112
129
|
loadRemoteTACTKeys(): Promise<void>;
|
|
113
130
|
loadTACTKeys(): Promise<void>;
|
|
131
|
+
loadBroadcastTACTKeys(adb: ADBReader): void;
|
|
114
132
|
getFileDataIDByName(name: string): number | undefined;
|
|
115
133
|
getContentKeysByFileDataID(fileDataID: number): FileInfo[] | undefined;
|
|
116
134
|
getFileByContentKey(cKey: string, allowMissingKey?: false): Promise<FileFetchResultFull>;
|
|
@@ -192,6 +210,14 @@ interface SparseRow {
|
|
|
192
210
|
type: 'sparse';
|
|
193
211
|
data: Buffer;
|
|
194
212
|
}
|
|
213
|
+
interface HotfixModify {
|
|
214
|
+
type: 'modify';
|
|
215
|
+
data: Buffer;
|
|
216
|
+
}
|
|
217
|
+
interface HotfixDelete {
|
|
218
|
+
type: 'delete';
|
|
219
|
+
}
|
|
220
|
+
type Hotfix = HotfixModify | HotfixDelete;
|
|
195
221
|
declare class WDCReader {
|
|
196
222
|
readonly tableHash: number;
|
|
197
223
|
readonly layoutHash: number;
|
|
@@ -203,7 +229,8 @@ declare class WDCReader {
|
|
|
203
229
|
readonly rows: Map<number, SparseRow | ParsedField[]>;
|
|
204
230
|
readonly relationships: Map<number, number>;
|
|
205
231
|
readonly copyTable: Map<number, number>;
|
|
206
|
-
|
|
232
|
+
readonly hotfixes: Map<number, Hotfix>;
|
|
233
|
+
constructor(buffer: Buffer, blocks?: MissingKeyBlock[], adb?: ADBReader);
|
|
207
234
|
getAllIDs(): number[];
|
|
208
235
|
getRowData(id: number): ParsedField[] | SparseRow | undefined;
|
|
209
236
|
getRowRelationship(id: number): number | undefined;
|
|
@@ -232,4 +259,4 @@ declare class DBDParser {
|
|
|
232
259
|
getRowData(id: number): Record<string, ColumnData | ColumnData[]> | undefined;
|
|
233
260
|
}
|
|
234
261
|
|
|
235
|
-
export { CASCClient, DBDParser, WDCReader };
|
|
262
|
+
export { ADBReader, CASCClient, DBDParser, WDCReader };
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,23 @@ interface MissingKeyBlock {
|
|
|
42
42
|
keyName: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
interface HotfixEntry {
|
|
46
|
+
regionID: number;
|
|
47
|
+
pushID: number;
|
|
48
|
+
uniqueID: number;
|
|
49
|
+
tableHash: number;
|
|
50
|
+
recordID: number;
|
|
51
|
+
dataSize: number;
|
|
52
|
+
recordState: number;
|
|
53
|
+
data: Buffer;
|
|
54
|
+
}
|
|
55
|
+
declare class ADBReader {
|
|
56
|
+
build: number;
|
|
57
|
+
entries: HotfixEntry[];
|
|
58
|
+
tableEntries: Map<number, HotfixEntry[]>;
|
|
59
|
+
constructor(buffer: Buffer);
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
interface ClientPreloadData {
|
|
46
63
|
prefixes: string[];
|
|
47
64
|
archives: ReturnType<typeof parseArchiveIndex>;
|
|
@@ -111,6 +128,7 @@ declare class CASCClient {
|
|
|
111
128
|
loadRemoteListFile(): Promise<void>;
|
|
112
129
|
loadRemoteTACTKeys(): Promise<void>;
|
|
113
130
|
loadTACTKeys(): Promise<void>;
|
|
131
|
+
loadBroadcastTACTKeys(adb: ADBReader): void;
|
|
114
132
|
getFileDataIDByName(name: string): number | undefined;
|
|
115
133
|
getContentKeysByFileDataID(fileDataID: number): FileInfo[] | undefined;
|
|
116
134
|
getFileByContentKey(cKey: string, allowMissingKey?: false): Promise<FileFetchResultFull>;
|
|
@@ -192,6 +210,14 @@ interface SparseRow {
|
|
|
192
210
|
type: 'sparse';
|
|
193
211
|
data: Buffer;
|
|
194
212
|
}
|
|
213
|
+
interface HotfixModify {
|
|
214
|
+
type: 'modify';
|
|
215
|
+
data: Buffer;
|
|
216
|
+
}
|
|
217
|
+
interface HotfixDelete {
|
|
218
|
+
type: 'delete';
|
|
219
|
+
}
|
|
220
|
+
type Hotfix = HotfixModify | HotfixDelete;
|
|
195
221
|
declare class WDCReader {
|
|
196
222
|
readonly tableHash: number;
|
|
197
223
|
readonly layoutHash: number;
|
|
@@ -203,7 +229,8 @@ declare class WDCReader {
|
|
|
203
229
|
readonly rows: Map<number, SparseRow | ParsedField[]>;
|
|
204
230
|
readonly relationships: Map<number, number>;
|
|
205
231
|
readonly copyTable: Map<number, number>;
|
|
206
|
-
|
|
232
|
+
readonly hotfixes: Map<number, Hotfix>;
|
|
233
|
+
constructor(buffer: Buffer, blocks?: MissingKeyBlock[], adb?: ADBReader);
|
|
207
234
|
getAllIDs(): number[];
|
|
208
235
|
getRowData(id: number): ParsedField[] | SparseRow | undefined;
|
|
209
236
|
getRowRelationship(id: number): number | undefined;
|
|
@@ -232,4 +259,4 @@ declare class DBDParser {
|
|
|
232
259
|
getRowData(id: number): Record<string, ColumnData | ColumnData[]> | undefined;
|
|
233
260
|
}
|
|
234
261
|
|
|
235
|
-
export { CASCClient, DBDParser, WDCReader };
|
|
262
|
+
export { ADBReader, CASCClient, DBDParser, WDCReader };
|
package/dist/index.mjs
CHANGED
|
@@ -7,17 +7,17 @@ import path from 'node:path';
|
|
|
7
7
|
import http from 'node:http';
|
|
8
8
|
import zlib from 'node:zlib';
|
|
9
9
|
|
|
10
|
-
var __defProp$
|
|
11
|
-
var __defNormalProp$
|
|
12
|
-
var __publicField$
|
|
13
|
-
__defNormalProp$
|
|
10
|
+
var __defProp$6 = Object.defineProperty;
|
|
11
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __publicField$6 = (obj, key, value) => {
|
|
13
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
14
14
|
return value;
|
|
15
15
|
};
|
|
16
16
|
class Store {
|
|
17
17
|
constructor(dataFile) {
|
|
18
|
-
__publicField$
|
|
19
|
-
__publicField$
|
|
20
|
-
__publicField$
|
|
18
|
+
__publicField$6(this, "data");
|
|
19
|
+
__publicField$6(this, "dataFile");
|
|
20
|
+
__publicField$6(this, "promise");
|
|
21
21
|
this.dataFile = dataFile;
|
|
22
22
|
this.data = {};
|
|
23
23
|
this.promise = new Promise((resolve) => {
|
|
@@ -282,21 +282,21 @@ const parseArchiveIndex = (buffer, cKey) => {
|
|
|
282
282
|
return result;
|
|
283
283
|
};
|
|
284
284
|
|
|
285
|
-
var __defProp$
|
|
286
|
-
var __defNormalProp$
|
|
287
|
-
var __publicField$
|
|
288
|
-
__defNormalProp$
|
|
285
|
+
var __defProp$5 = Object.defineProperty;
|
|
286
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
287
|
+
var __publicField$5 = (obj, key, value) => {
|
|
288
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
289
289
|
return value;
|
|
290
290
|
};
|
|
291
291
|
class Salsa20 {
|
|
292
292
|
constructor(key, nonce) {
|
|
293
|
-
__publicField$
|
|
294
|
-
__publicField$
|
|
295
|
-
__publicField$
|
|
296
|
-
__publicField$
|
|
297
|
-
__publicField$
|
|
298
|
-
__publicField$
|
|
299
|
-
__publicField$
|
|
293
|
+
__publicField$5(this, "fixed");
|
|
294
|
+
__publicField$5(this, "key");
|
|
295
|
+
__publicField$5(this, "nonce");
|
|
296
|
+
__publicField$5(this, "counter", new Uint32Array([0, 0]));
|
|
297
|
+
__publicField$5(this, "state", new Uint32Array(16));
|
|
298
|
+
__publicField$5(this, "block", new Uint8Array(64));
|
|
299
|
+
__publicField$5(this, "position", 0);
|
|
300
300
|
assert(key.length === 32 || key.length === 16, "Salsa20 requires 128-bit or 256-bit key");
|
|
301
301
|
assert(nonce.length === 8, "Salsa20 requires 64-bit nonce");
|
|
302
302
|
this.key = new Uint32Array(8);
|
|
@@ -399,10 +399,10 @@ class Salsa20 {
|
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
var __defProp$
|
|
403
|
-
var __defNormalProp$
|
|
404
|
-
var __publicField$
|
|
405
|
-
__defNormalProp$
|
|
402
|
+
var __defProp$4 = Object.defineProperty;
|
|
403
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
404
|
+
var __publicField$4 = (obj, key, value) => {
|
|
405
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
406
406
|
return value;
|
|
407
407
|
};
|
|
408
408
|
const BLTE_MAGIC = 1112298565;
|
|
@@ -410,12 +410,12 @@ const ENC_TYPE_SALSA20 = 83;
|
|
|
410
410
|
const EMPTY_HASH = "00000000000000000000000000000000";
|
|
411
411
|
class BLTEReader {
|
|
412
412
|
constructor(buffer, eKey, keys = /* @__PURE__ */ new Map()) {
|
|
413
|
-
__publicField$
|
|
414
|
-
__publicField$
|
|
415
|
-
__publicField$
|
|
416
|
-
__publicField$
|
|
417
|
-
__publicField$
|
|
418
|
-
__publicField$
|
|
413
|
+
__publicField$4(this, "buffer");
|
|
414
|
+
__publicField$4(this, "blte");
|
|
415
|
+
__publicField$4(this, "blocks", []);
|
|
416
|
+
__publicField$4(this, "keys");
|
|
417
|
+
__publicField$4(this, "processedBlock", 0);
|
|
418
|
+
__publicField$4(this, "processedOffset", 0);
|
|
419
419
|
this.blte = buffer;
|
|
420
420
|
this.buffer = Buffer.alloc(0);
|
|
421
421
|
this.keys = keys;
|
|
@@ -883,10 +883,10 @@ const getNameHash = (name) => {
|
|
|
883
883
|
return `${pc.toString(16).padStart(8, "0")}${pb.toString(16).padStart(8, "0")}`;
|
|
884
884
|
};
|
|
885
885
|
|
|
886
|
-
var __defProp$
|
|
887
|
-
var __defNormalProp$
|
|
888
|
-
var __publicField$
|
|
889
|
-
__defNormalProp$
|
|
886
|
+
var __defProp$3 = Object.defineProperty;
|
|
887
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
888
|
+
var __publicField$3 = (obj, key, value) => {
|
|
889
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
890
890
|
return value;
|
|
891
891
|
};
|
|
892
892
|
const WDC5_MAGIC = 1464091445;
|
|
@@ -912,17 +912,18 @@ const readBitpackedValue = (buffer, fieldOffsetBits, fieldSizeBits, signed = fal
|
|
|
912
912
|
return signed ? BigInt.asIntN(fieldSizeBits, value >> BigInt(bitOffset)) : BigInt.asUintN(fieldSizeBits, value >> BigInt(bitOffset));
|
|
913
913
|
};
|
|
914
914
|
class WDCReader {
|
|
915
|
-
constructor(buffer, blocks = []) {
|
|
916
|
-
__publicField$
|
|
917
|
-
__publicField$
|
|
918
|
-
__publicField$
|
|
919
|
-
__publicField$
|
|
920
|
-
__publicField$
|
|
921
|
-
__publicField$
|
|
922
|
-
__publicField$
|
|
923
|
-
__publicField$
|
|
924
|
-
__publicField$
|
|
925
|
-
__publicField$
|
|
915
|
+
constructor(buffer, blocks = [], adb) {
|
|
916
|
+
__publicField$3(this, "tableHash");
|
|
917
|
+
__publicField$3(this, "layoutHash");
|
|
918
|
+
__publicField$3(this, "locale");
|
|
919
|
+
__publicField$3(this, "isNormal");
|
|
920
|
+
__publicField$3(this, "hasRelationshipData");
|
|
921
|
+
__publicField$3(this, "fields");
|
|
922
|
+
__publicField$3(this, "fieldsInfo");
|
|
923
|
+
__publicField$3(this, "rows", /* @__PURE__ */ new Map());
|
|
924
|
+
__publicField$3(this, "relationships", /* @__PURE__ */ new Map());
|
|
925
|
+
__publicField$3(this, "copyTable", /* @__PURE__ */ new Map());
|
|
926
|
+
__publicField$3(this, "hotfixes", /* @__PURE__ */ new Map());
|
|
926
927
|
const magic = buffer.readUInt32BE(0);
|
|
927
928
|
const fieldCount = buffer.readUInt32LE(140);
|
|
928
929
|
const recordSize = buffer.readUInt32LE(144);
|
|
@@ -1327,11 +1328,43 @@ class WDCReader {
|
|
|
1327
1328
|
}
|
|
1328
1329
|
}
|
|
1329
1330
|
});
|
|
1331
|
+
const entries = adb?.tableEntries.get(tableHash);
|
|
1332
|
+
entries?.filter((entry) => entry.pushID !== -1).sort((a, b) => a.pushID - b.pushID).forEach((entry) => {
|
|
1333
|
+
switch (entry.recordState) {
|
|
1334
|
+
case 1:
|
|
1335
|
+
this.hotfixes.set(entry.recordID, { type: "modify", data: entry.data });
|
|
1336
|
+
break;
|
|
1337
|
+
case 2:
|
|
1338
|
+
this.hotfixes.set(entry.recordID, { type: "delete" });
|
|
1339
|
+
break;
|
|
1340
|
+
case 3:
|
|
1341
|
+
this.hotfixes.delete(entry.recordID);
|
|
1342
|
+
break;
|
|
1343
|
+
case 4:
|
|
1344
|
+
break;
|
|
1345
|
+
default:
|
|
1346
|
+
throw new Error(`Unknown record state: ${entry.recordState.toString()}`);
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1330
1349
|
}
|
|
1331
1350
|
getAllIDs() {
|
|
1332
1351
|
return [...this.rows.keys(), ...this.copyTable.keys()];
|
|
1333
1352
|
}
|
|
1334
1353
|
getRowData(id) {
|
|
1354
|
+
const hotfix = this.hotfixes.get(id);
|
|
1355
|
+
if (hotfix) {
|
|
1356
|
+
switch (hotfix.type) {
|
|
1357
|
+
case "modify":
|
|
1358
|
+
return {
|
|
1359
|
+
type: "sparse",
|
|
1360
|
+
data: hotfix.data
|
|
1361
|
+
};
|
|
1362
|
+
case "delete":
|
|
1363
|
+
return void 0;
|
|
1364
|
+
default:
|
|
1365
|
+
throw new Error("Unreachable");
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1335
1368
|
const dst = this.copyTable.get(id);
|
|
1336
1369
|
if (dst) {
|
|
1337
1370
|
return this.rows.get(dst);
|
|
@@ -1393,10 +1426,10 @@ const formatFileSize = (input) => {
|
|
|
1393
1426
|
return result.join(" ");
|
|
1394
1427
|
};
|
|
1395
1428
|
|
|
1396
|
-
var __defProp$
|
|
1397
|
-
var __defNormalProp$
|
|
1398
|
-
var __publicField$
|
|
1399
|
-
__defNormalProp$
|
|
1429
|
+
var __defProp$2 = Object.defineProperty;
|
|
1430
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1431
|
+
var __publicField$2 = (obj, key, value) => {
|
|
1432
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1400
1433
|
return value;
|
|
1401
1434
|
};
|
|
1402
1435
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
@@ -1409,13 +1442,13 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
1409
1442
|
const textLogLevel = ["ERROR", "WARN", "INFO", "DEBUG"];
|
|
1410
1443
|
class CASCClient {
|
|
1411
1444
|
constructor(region, product, version, logLevel = 2 /* info */) {
|
|
1412
|
-
__publicField$
|
|
1413
|
-
__publicField$
|
|
1414
|
-
__publicField$
|
|
1415
|
-
__publicField$
|
|
1416
|
-
__publicField$
|
|
1417
|
-
__publicField$
|
|
1418
|
-
__publicField$
|
|
1445
|
+
__publicField$2(this, "region");
|
|
1446
|
+
__publicField$2(this, "product");
|
|
1447
|
+
__publicField$2(this, "version");
|
|
1448
|
+
__publicField$2(this, "name2FileDataID", /* @__PURE__ */ new Map());
|
|
1449
|
+
__publicField$2(this, "keys", /* @__PURE__ */ new Map());
|
|
1450
|
+
__publicField$2(this, "preload");
|
|
1451
|
+
__publicField$2(this, "logLevel");
|
|
1419
1452
|
this.region = region;
|
|
1420
1453
|
this.product = product;
|
|
1421
1454
|
this.version = version;
|
|
@@ -1560,7 +1593,7 @@ class CASCClient {
|
|
|
1560
1593
|
]);
|
|
1561
1594
|
const keysReader = new WDCReader(keysResult.buffer);
|
|
1562
1595
|
const lookupReader = new WDCReader(lookupResult.buffer);
|
|
1563
|
-
|
|
1596
|
+
lookupReader.getAllIDs().forEach((keyID) => {
|
|
1564
1597
|
const lookupRow = lookupReader.rows.get(keyID);
|
|
1565
1598
|
const keyRow = keysReader.rows.get(keyID);
|
|
1566
1599
|
if (keyRow) {
|
|
@@ -1576,6 +1609,31 @@ class CASCClient {
|
|
|
1576
1609
|
}
|
|
1577
1610
|
});
|
|
1578
1611
|
}
|
|
1612
|
+
loadBroadcastTACTKeys(adb) {
|
|
1613
|
+
adb.tableEntries.get(35137211)?.forEach(({ data }) => {
|
|
1614
|
+
if (data.byteLength > 0) {
|
|
1615
|
+
let pointer = 0;
|
|
1616
|
+
while (data[pointer] !== 0) {
|
|
1617
|
+
pointer += 1;
|
|
1618
|
+
}
|
|
1619
|
+
pointer += 1;
|
|
1620
|
+
while (data[pointer] !== 0) {
|
|
1621
|
+
pointer += 1;
|
|
1622
|
+
}
|
|
1623
|
+
pointer += 1 + 43;
|
|
1624
|
+
if (pointer < data.byteLength) {
|
|
1625
|
+
const extraTableHash = data.readUInt32LE(pointer);
|
|
1626
|
+
if (extraTableHash === 3744420815) {
|
|
1627
|
+
const keyName = data.readBigUInt64LE(pointer + 4).toString(16).padStart(16, "0");
|
|
1628
|
+
const key = Uint8Array.from(data.subarray(pointer + 12));
|
|
1629
|
+
if (!this.keys.has(keyName)) {
|
|
1630
|
+
this.keys.set(keyName, key);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1579
1637
|
getFileDataIDByName(name) {
|
|
1580
1638
|
assert(this.preload, "Client not initialized");
|
|
1581
1639
|
const { rootFile } = this.preload;
|
|
@@ -1629,14 +1687,14 @@ class CASCClient {
|
|
|
1629
1687
|
};
|
|
1630
1688
|
}
|
|
1631
1689
|
}
|
|
1632
|
-
__publicField$
|
|
1633
|
-
__publicField$
|
|
1634
|
-
__publicField$
|
|
1690
|
+
__publicField$2(CASCClient, "LocaleFlags", LocaleFlags);
|
|
1691
|
+
__publicField$2(CASCClient, "ContentFlags", ContentFlags);
|
|
1692
|
+
__publicField$2(CASCClient, "LogLevel", LogLevel);
|
|
1635
1693
|
|
|
1636
|
-
var __defProp = Object.defineProperty;
|
|
1637
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1638
|
-
var __publicField = (obj, key, value) => {
|
|
1639
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1694
|
+
var __defProp$1 = Object.defineProperty;
|
|
1695
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1696
|
+
var __publicField$1 = (obj, key, value) => {
|
|
1697
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1640
1698
|
return value;
|
|
1641
1699
|
};
|
|
1642
1700
|
const PATTERN_COLUMN = /^(int|float|locstring|string)(<[^:]+::[^>]+>)?\s([^\s]+)/;
|
|
@@ -1672,10 +1730,10 @@ const castBigInt64 = (value, srcSigned, dstSigned) => {
|
|
|
1672
1730
|
};
|
|
1673
1731
|
class DBDParser {
|
|
1674
1732
|
constructor(wdc) {
|
|
1675
|
-
__publicField(this, "wdc");
|
|
1676
|
-
__publicField(this, "definitions", /* @__PURE__ */ new Map());
|
|
1677
|
-
__publicField(this, "columns", []);
|
|
1678
|
-
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
1733
|
+
__publicField$1(this, "wdc");
|
|
1734
|
+
__publicField$1(this, "definitions", /* @__PURE__ */ new Map());
|
|
1735
|
+
__publicField$1(this, "columns", []);
|
|
1736
|
+
__publicField$1(this, "cache", /* @__PURE__ */ new Map());
|
|
1679
1737
|
this.wdc = wdc;
|
|
1680
1738
|
}
|
|
1681
1739
|
async init() {
|
|
@@ -1843,6 +1901,9 @@ class DBDParser {
|
|
|
1843
1901
|
if (column.isID) {
|
|
1844
1902
|
data[column.name] = id;
|
|
1845
1903
|
if (column.isInline) {
|
|
1904
|
+
const currField = this.wdc.fields[fieldIndex];
|
|
1905
|
+
const size = Math.ceil((column.size ?? 32 - currField.size) / 8);
|
|
1906
|
+
offset += size;
|
|
1846
1907
|
fieldIndex += 1;
|
|
1847
1908
|
}
|
|
1848
1909
|
} else if (column.isInline) {
|
|
@@ -1864,7 +1925,7 @@ class DBDParser {
|
|
|
1864
1925
|
const size = Math.ceil((column.size ?? 32 - currField.size) / 8);
|
|
1865
1926
|
let count;
|
|
1866
1927
|
if (fieldIndex + 1 < this.wdc.fields.length) {
|
|
1867
|
-
count = (nextField.position - currField.position) / size;
|
|
1928
|
+
count = Math.max((nextField.position - currField.position) / size, 1);
|
|
1868
1929
|
} else {
|
|
1869
1930
|
count = column.arraySize ? (buffer.byteLength - offset) / size : 1;
|
|
1870
1931
|
}
|
|
@@ -1898,4 +1959,55 @@ class DBDParser {
|
|
|
1898
1959
|
}
|
|
1899
1960
|
}
|
|
1900
1961
|
|
|
1901
|
-
|
|
1962
|
+
var __defProp = Object.defineProperty;
|
|
1963
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1964
|
+
var __publicField = (obj, key, value) => {
|
|
1965
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1966
|
+
return value;
|
|
1967
|
+
};
|
|
1968
|
+
const ADB_MAGIC = 1481004104;
|
|
1969
|
+
class ADBReader {
|
|
1970
|
+
constructor(buffer) {
|
|
1971
|
+
__publicField(this, "build");
|
|
1972
|
+
__publicField(this, "entries", []);
|
|
1973
|
+
__publicField(this, "tableEntries", /* @__PURE__ */ new Map());
|
|
1974
|
+
const magic = buffer.readUInt32BE(0);
|
|
1975
|
+
assert(magic === ADB_MAGIC, `[ADB]: Invalid magic: ${magic.toString(16).padStart(8, "0")}`);
|
|
1976
|
+
const version = buffer.readUInt32LE(4);
|
|
1977
|
+
assert(version === 9, `[ADB]: Invalid version: ${version.toString()}`);
|
|
1978
|
+
const build = buffer.readUInt32LE(8);
|
|
1979
|
+
this.build = build;
|
|
1980
|
+
let pointer = 44;
|
|
1981
|
+
while (pointer < buffer.byteLength) {
|
|
1982
|
+
const offset = pointer;
|
|
1983
|
+
const entryMagic = buffer.readUInt32BE(offset);
|
|
1984
|
+
assert(entryMagic === ADB_MAGIC, `[ADB]: Invalid entry magic: ${magic.toString(16).padStart(8, "0")}`);
|
|
1985
|
+
const regionID = buffer.readInt32LE(offset + 4);
|
|
1986
|
+
const pushID = buffer.readInt32LE(offset + 8);
|
|
1987
|
+
const uniqueID = buffer.readUInt32LE(offset + 12);
|
|
1988
|
+
const tableHash = buffer.readUInt32LE(offset + 16);
|
|
1989
|
+
const recordID = buffer.readUInt32LE(offset + 20);
|
|
1990
|
+
const dataSize = buffer.readUInt32LE(offset + 24);
|
|
1991
|
+
const recordState = buffer.readUInt32LE(offset + 28);
|
|
1992
|
+
const data = buffer.subarray(offset + 32, offset + 32 + dataSize);
|
|
1993
|
+
const entry = {
|
|
1994
|
+
regionID,
|
|
1995
|
+
pushID,
|
|
1996
|
+
uniqueID,
|
|
1997
|
+
tableHash,
|
|
1998
|
+
recordID,
|
|
1999
|
+
dataSize,
|
|
2000
|
+
recordState,
|
|
2001
|
+
data
|
|
2002
|
+
};
|
|
2003
|
+
this.entries.push(entry);
|
|
2004
|
+
if (!this.tableEntries.has(tableHash)) {
|
|
2005
|
+
this.tableEntries.set(tableHash, []);
|
|
2006
|
+
}
|
|
2007
|
+
this.tableEntries.get(tableHash)?.push(entry);
|
|
2008
|
+
pointer += 32 + dataSize;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
export { ADBReader, CASCClient, DBDParser, WDCReader };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhyster/wow-casc-dbc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Fetch World of Warcraft data files from CASC and parse DBC/DB2 files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"@types/cli-progress": "^3.11.5",
|
|
42
42
|
"@types/jest": "^29.5.12",
|
|
43
43
|
"@types/node": "^20.12.7",
|
|
44
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
45
|
-
"@typescript-eslint/parser": "^7.
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
|
45
|
+
"@typescript-eslint/parser": "^7.8.0",
|
|
46
46
|
"eslint": "^8.57.0",
|
|
47
47
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
48
48
|
"eslint-config-airbnb-typescript": "^18.0.0",
|
|
49
49
|
"jest": "^29.7.0",
|
|
50
50
|
"ts-jest": "^29.1.2",
|
|
51
|
-
"
|
|
51
|
+
"tsx": "^4.7.3",
|
|
52
52
|
"typescript": "^5.4.5",
|
|
53
53
|
"unbuild": "^2.0.0"
|
|
54
54
|
},
|