@rhyster/wow-casc-dbc 2.7.6 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +4 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +101 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +101 -11
- package/dist/index.mjs.map +1 -1
- package/dist/parsers/installFile.d.ts +19 -0
- package/dist/parsers/installFile.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/client.ts +43 -4
- package/src/dbd.ts +2 -2
- package/src/index.ts +2 -0
- package/src/parsers/installFile.ts +113 -0
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type ADBReader from './adb.ts';
|
|
|
2
2
|
import type { MissingKeyBlock } from './blte.ts';
|
|
3
3
|
import type { ArchiveIndex } from './parsers/archiveIndex.ts';
|
|
4
4
|
import type { EncodingData } from './parsers/encodingFile.ts';
|
|
5
|
+
import type { InstallFile, InstallData } from './parsers/installFile.ts';
|
|
5
6
|
import type { Version } from './parsers/productConfig.ts';
|
|
6
7
|
import type { FileInfo, RootData } from './parsers/rootFile.ts';
|
|
7
8
|
interface ClientPreloadData {
|
|
@@ -9,6 +10,7 @@ interface ClientPreloadData {
|
|
|
9
10
|
archives: Map<string, ArchiveIndex>;
|
|
10
11
|
encoding: EncodingData;
|
|
11
12
|
rootFile: RootData;
|
|
13
|
+
install: InstallData;
|
|
12
14
|
}
|
|
13
15
|
interface FileFetchResultFull {
|
|
14
16
|
type: 'full';
|
|
@@ -77,8 +79,9 @@ export default class CASCClient {
|
|
|
77
79
|
loadBroadcastTACTKeys(adb: ADBReader): void;
|
|
78
80
|
getFileDataIDByName(name: string): number | undefined;
|
|
79
81
|
getContentKeysByFileDataID(fileDataID: number): FileInfo[] | undefined;
|
|
82
|
+
getContentKeysFromInstall(name: string): InstallFile[] | undefined;
|
|
80
83
|
getFileByContentKey(cKey: string, allowMissingKey?: false): Promise<FileFetchResultFull>;
|
|
81
84
|
getFileByContentKey(cKey: string, allowMissingKey: true): Promise<FileFetchResult>;
|
|
82
85
|
}
|
|
83
|
-
export type { Version, ClientPreloadData, ArchiveIndex, EncodingData, RootData, FileInfo, FileFetchResultFull, FileFetchResultPartial, FileFetchResult, MissingKeyBlock, };
|
|
86
|
+
export type { Version, ClientPreloadData, ArchiveIndex, EncodingData, InstallFile, InstallData, RootData, FileInfo, FileFetchResultFull, FileFetchResultPartial, FileFetchResult, MissingKeyBlock, };
|
|
84
87
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -692,8 +692,8 @@ const parseCDNConfig = (text) => parseConfig(text);
|
|
|
692
692
|
const parseBuildConfig = (text) => parseConfig(text);
|
|
693
693
|
|
|
694
694
|
const ENC_MAGIC = 17742;
|
|
695
|
-
const MAGIC_OFFSET = 0;
|
|
696
|
-
const VERSION_OFFSET = 2;
|
|
695
|
+
const MAGIC_OFFSET$1 = 0;
|
|
696
|
+
const VERSION_OFFSET$1 = 2;
|
|
697
697
|
const HASH_SIZE_CKEY_OFFSET = 3;
|
|
698
698
|
const HASH_SIZE_EKEY_OFFSET = 4;
|
|
699
699
|
const CKEY_PAGE_SIZE_OFFSET = 5;
|
|
@@ -708,9 +708,9 @@ const parseEncodingFile = (inputBuffer, eKey, cKey) => {
|
|
|
708
708
|
const { buffer } = reader;
|
|
709
709
|
const encodingHash = crypto__default.createHash("md5").update(buffer).digest("hex");
|
|
710
710
|
assert__default(encodingHash === cKey, `Invalid encoding hash: expected ${cKey}, got ${encodingHash}`);
|
|
711
|
-
const magic = buffer.readUInt16BE(MAGIC_OFFSET);
|
|
711
|
+
const magic = buffer.readUInt16BE(MAGIC_OFFSET$1);
|
|
712
712
|
assert__default(magic === ENC_MAGIC, `Invalid encoding magic: ${magic.toString(16).padStart(4, "0")}`);
|
|
713
|
-
const version = buffer.readUInt8(VERSION_OFFSET);
|
|
713
|
+
const version = buffer.readUInt8(VERSION_OFFSET$1);
|
|
714
714
|
const hashSizeCKey = buffer.readUInt8(HASH_SIZE_CKEY_OFFSET);
|
|
715
715
|
const hashSizeEKey = buffer.readUInt8(HASH_SIZE_EKEY_OFFSET);
|
|
716
716
|
const cKeyPageSizeKB = buffer.readUInt16BE(CKEY_PAGE_SIZE_OFFSET);
|
|
@@ -808,6 +808,71 @@ const parseEncodingFile = (inputBuffer, eKey, cKey) => {
|
|
|
808
808
|
};
|
|
809
809
|
};
|
|
810
810
|
|
|
811
|
+
const INSTALL_MAGIC = 18766;
|
|
812
|
+
const MAGIC_OFFSET = 0;
|
|
813
|
+
const VERSION_OFFSET = 2;
|
|
814
|
+
const HASH_SIZE_OFFSET = 3;
|
|
815
|
+
const NUM_TAGS_OFFSET = 4;
|
|
816
|
+
const NUM_ENTRIES_OFFSET = 6;
|
|
817
|
+
const TAGS_OFFSET = 10;
|
|
818
|
+
const parseInstallFile = (inputBuffer, eKey, cKey) => {
|
|
819
|
+
const reader = new BLTEReader(inputBuffer, eKey);
|
|
820
|
+
reader.processBytes();
|
|
821
|
+
const { buffer } = reader;
|
|
822
|
+
const installHash = crypto__default.createHash("md5").update(buffer).digest("hex");
|
|
823
|
+
assert__default(installHash === cKey, `Invalid root hash: expected ${cKey}, got ${installHash}`);
|
|
824
|
+
const magic = buffer.readUInt16BE(MAGIC_OFFSET);
|
|
825
|
+
assert__default(magic === INSTALL_MAGIC, `Invalid install magic: ${magic.toString(16).padStart(4, "0")}`);
|
|
826
|
+
const version = buffer.readUInt8(VERSION_OFFSET);
|
|
827
|
+
const hashSize = buffer.readUInt8(HASH_SIZE_OFFSET);
|
|
828
|
+
const numTags = buffer.readUInt16BE(NUM_TAGS_OFFSET);
|
|
829
|
+
const numEntries = buffer.readUInt32BE(NUM_ENTRIES_OFFSET);
|
|
830
|
+
assert__default(version === 1, `Invalid install version: ${version.toString()}`);
|
|
831
|
+
let pointer = TAGS_OFFSET;
|
|
832
|
+
const tags = [];
|
|
833
|
+
for (let i = 0; i < numTags; i += 1) {
|
|
834
|
+
const startOffset = pointer;
|
|
835
|
+
while (buffer[pointer] !== 0) {
|
|
836
|
+
pointer += 1;
|
|
837
|
+
}
|
|
838
|
+
const name = buffer.toString("utf-8", startOffset, pointer);
|
|
839
|
+
pointer += 1;
|
|
840
|
+
const type = buffer.readUInt16BE(pointer);
|
|
841
|
+
pointer += 2;
|
|
842
|
+
const files2 = [];
|
|
843
|
+
const finalOffset = pointer + Math.ceil(numEntries / 8);
|
|
844
|
+
while (pointer < finalOffset) {
|
|
845
|
+
const byte = buffer.readUInt8(pointer);
|
|
846
|
+
pointer += 1;
|
|
847
|
+
for (let j = 7; j >= 0; j -= 1) {
|
|
848
|
+
files2.push((byte & 1 << j) > 0);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
tags.push({ name, type, files: files2 });
|
|
852
|
+
}
|
|
853
|
+
const files = [];
|
|
854
|
+
for (let i = 0; i < numEntries; i += 1) {
|
|
855
|
+
const startOffset = pointer;
|
|
856
|
+
while (buffer[pointer] !== 0) {
|
|
857
|
+
pointer += 1;
|
|
858
|
+
}
|
|
859
|
+
const name = buffer.toString("utf-8", startOffset, pointer);
|
|
860
|
+
pointer += 1;
|
|
861
|
+
const hash = buffer.toString("hex", pointer, pointer + hashSize);
|
|
862
|
+
pointer += hashSize;
|
|
863
|
+
const size = buffer.readUInt32BE(pointer);
|
|
864
|
+
pointer += 4;
|
|
865
|
+
const fileTags = tags.filter((tag) => tag.files[i]);
|
|
866
|
+
files.push({
|
|
867
|
+
name,
|
|
868
|
+
hash,
|
|
869
|
+
size,
|
|
870
|
+
tags: fileTags
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
return { tags, files };
|
|
874
|
+
};
|
|
875
|
+
|
|
811
876
|
const parseProductConfig = (text) => {
|
|
812
877
|
const lines = text.split(/\r?\n/);
|
|
813
878
|
const headers = lines[0].split("|").map((header) => header.split("!")[0].replace(" ", ""));
|
|
@@ -1606,11 +1671,19 @@ class CASCClient {
|
|
|
1606
1671
|
this.log(2 /* info */, "Parsing encoding table...");
|
|
1607
1672
|
const encoding = parseEncodingFile(encodingBuffer, encodingEKey, encodingCKey);
|
|
1608
1673
|
this.log(2 /* info */, `Parsed encoding table (${encoding.cKey2EKey.size.toString()} entries)`);
|
|
1674
|
+
const getBuildConfigKeys = (configText) => {
|
|
1675
|
+
if (configText.includes(" ")) {
|
|
1676
|
+
const [cKey2, eKey2] = configText.split(" ");
|
|
1677
|
+
return [cKey2, eKey2];
|
|
1678
|
+
}
|
|
1679
|
+
const cKey = configText;
|
|
1680
|
+
const eKeys = encoding.cKey2EKey.get(cKey);
|
|
1681
|
+
assert__default(eKeys !== void 0, `Failing to find encoding key for ${cKey}`);
|
|
1682
|
+
const eKey = typeof eKeys === "string" ? eKeys : eKeys[0];
|
|
1683
|
+
return [cKey, eKey];
|
|
1684
|
+
};
|
|
1609
1685
|
this.log(2 /* info */, "Loading root table...");
|
|
1610
|
-
const rootCKey = buildConfig.root;
|
|
1611
|
-
const rootEKeys = encoding.cKey2EKey.get(rootCKey);
|
|
1612
|
-
assert__default(rootEKeys !== void 0, "Failing to find EKey for root table.");
|
|
1613
|
-
const rootEKey = typeof rootEKeys === "string" ? rootEKeys : rootEKeys[0];
|
|
1686
|
+
const [rootCKey, rootEKey] = getBuildConfigKeys(buildConfig.root);
|
|
1614
1687
|
const rootBuffer = await getDataFile(prefixes, rootEKey, "build", this.version.BuildConfig, {
|
|
1615
1688
|
name: "root",
|
|
1616
1689
|
showProgress: this.logLevel >= 2 /* info */,
|
|
@@ -1620,11 +1693,23 @@ class CASCClient {
|
|
|
1620
1693
|
this.log(2 /* info */, "Parsing root file...");
|
|
1621
1694
|
const rootFile = parseRootFile(rootBuffer, rootEKey, rootCKey);
|
|
1622
1695
|
this.log(2 /* info */, `Parsed root file (${rootFile.fileDataID2CKey.size.toString()} entries, ${rootFile.nameHash2FileDataID.size.toString()} hashes)`);
|
|
1696
|
+
this.log(2 /* info */, "Loading install manifest...");
|
|
1697
|
+
const [installCKey, installEKey] = getBuildConfigKeys(buildConfig.install);
|
|
1698
|
+
const installBuffer = await getDataFile(prefixes, installEKey, "build", this.version.BuildConfig, {
|
|
1699
|
+
name: "install",
|
|
1700
|
+
showProgress: this.logLevel >= 2 /* info */,
|
|
1701
|
+
showAttemptFail: this.logLevel >= 1 /* warn */
|
|
1702
|
+
});
|
|
1703
|
+
this.log(2 /* info */, `Loaded install manifest (${formatFileSize(installBuffer.byteLength)})`);
|
|
1704
|
+
this.log(2 /* info */, "Parsing install manifest...");
|
|
1705
|
+
const install = parseInstallFile(installBuffer, installEKey, installCKey);
|
|
1706
|
+
this.log(2 /* info */, `Parsed install manifest (${install.tags.length.toString()} tags, ${install.files.length.toString()} files)`);
|
|
1623
1707
|
this.preload = {
|
|
1624
1708
|
prefixes,
|
|
1625
1709
|
archives,
|
|
1626
1710
|
encoding,
|
|
1627
|
-
rootFile
|
|
1711
|
+
rootFile,
|
|
1712
|
+
install
|
|
1628
1713
|
};
|
|
1629
1714
|
}
|
|
1630
1715
|
async loadRemoteListFile() {
|
|
@@ -1712,6 +1797,11 @@ class CASCClient {
|
|
|
1712
1797
|
const { rootFile } = this.preload;
|
|
1713
1798
|
return rootFile.fileDataID2CKey.get(fileDataID);
|
|
1714
1799
|
}
|
|
1800
|
+
getContentKeysFromInstall(name) {
|
|
1801
|
+
assert__default(this.preload, "Client not initialized");
|
|
1802
|
+
const { install } = this.preload;
|
|
1803
|
+
return install.files.filter((file) => file.name === name);
|
|
1804
|
+
}
|
|
1715
1805
|
async getFileByContentKey(cKey, allowMissingKey = false) {
|
|
1716
1806
|
assert__default(this.preload, "Client not initialized");
|
|
1717
1807
|
const { prefixes, encoding, archives } = this.preload;
|
|
@@ -1837,8 +1927,8 @@ class DBDParser {
|
|
|
1837
1927
|
const versionChunk = chunks.find((chunk) => chunk.find((line) => {
|
|
1838
1928
|
const layoutsMatch = PATTERN_LAYOUT.exec(line);
|
|
1839
1929
|
const layouts = layoutsMatch?.[1].split(",").map((v) => v.trim().toLowerCase());
|
|
1840
|
-
return layouts?.includes(layoutHashHex);
|
|
1841
|
-
}));
|
|
1930
|
+
return layouts?.includes(layoutHashHex) === true;
|
|
1931
|
+
}) !== void 0);
|
|
1842
1932
|
assert__default(versionChunk, `No version definition found for layout hash ${layoutHashHex}`);
|
|
1843
1933
|
versionChunk.forEach((line) => {
|
|
1844
1934
|
if (line.startsWith("LAYOUT") || line.startsWith("BUILD") || line.startsWith("COMMENT")) {
|