From a0bccc797367a214be914b577644283ce1a739ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:18:44 -0600 Subject: [PATCH] feat: update all --- packages/scripts/src/applyPatches.ts | 16 ++--- .../scripts/src/buildAssets/boosterIcons.ts | 11 ++- .../src/buildAssets/camouflageIcons.ts | 7 +- .../buildAssets/consumableProvisionIcons.ts | 45 ++++++------ .../scripts/src/buildAssets/currencies.ts | 5 +- .../scripts/src/buildAssets/equipmentIcons.ts | 22 +++--- packages/scripts/src/buildAssets/flags.ts | 25 +++---- .../src/buildAssets/gameModeBanners.ts | 14 ++-- packages/scripts/src/buildAssets/migration.ts | 12 ++-- .../scripts/src/buildAssets/moduleIcons.ts | 10 +-- .../scripts/src/buildAssets/shellIcons.ts | 19 +++-- .../scripts/src/buildAssets/skillIcons.ts | 12 ++-- .../scripts/src/buildAssets/tankArmors.ts | 14 ++-- packages/scripts/src/buildAssets/tankIcons.ts | 26 +++---- .../scripts/src/buildAssets/tankModels.ts | 19 ++--- .../scripts/src/core/blitz/extractArmor.ts | 58 +++++++-------- .../src/core/blitz/extractModel/index.ts | 20 +++--- .../scripts/src/core/blitz/readBase64DVPL.ts | 6 -- .../scripts/src/core/blitz/readDVPLFile.ts | 21 ------ .../src/core/blitz/readTexture/index.ts | 70 +------------------ packages/scripts/src/setupDepotDownloader.ts | 34 ++++----- 21 files changed, 160 insertions(+), 306 deletions(-) delete mode 100644 packages/scripts/src/core/blitz/readBase64DVPL.ts delete mode 100644 packages/scripts/src/core/blitz/readDVPLFile.ts diff --git a/packages/scripts/src/applyPatches.ts b/packages/scripts/src/applyPatches.ts index 83ab198b4..7064ce932 100644 --- a/packages/scripts/src/applyPatches.ts +++ b/packages/scripts/src/applyPatches.ts @@ -4,12 +4,10 @@ import { mkdir, writeFile } from "fs/promises"; import { parse as parsePath } from "path"; import ProgressBar from "progress"; import { parse as parseYaml, stringify as stringifyYaml } from "yaml"; -import { readStringDVPL } from "../src/core/blitz/readStringDVPL"; -import { DATA } from "./buildAssets/constants"; -import { readYAMLDVPL } from "./core/blitz/readYAMLDVPL"; +import { vfs } from "./buildAssets/constants"; import { writeDVPL } from "./core/blitz/writeDVPL"; -const versionTextFile = await readStringDVPL(`${DATA}/version.txt`); +const versionTextFile = await vfs.text(`Data/version.txt`); const currentVersion = versionTextFile .split(" ")[0] .split(".") @@ -51,7 +49,7 @@ while (true) { const { dir } = parsePath(path); try { - await mkdir(`${DATA}/${dir}`, { recursive: true }); + await mkdir(`Data/${dir}`, { recursive: true }); } catch (error) { console.warn(`Failed to make directory "${dir}"`); } @@ -60,7 +58,7 @@ while (true) { const buffer = Buffer.from(data); await writeFile( - `${DATA}/${path}${isDvpl ? "" : ".dvpl"}`, + `Data/${path}${isDvpl ? "" : ".dvpl"}`, new Uint8Array(isDvpl ? buffer : writeDVPL(buffer)) ); @@ -76,14 +74,14 @@ while (true) { }/en.yaml` ); const newStrings = parseYaml(await localizationsResponse.text()); - const oldStrings = await readYAMLDVPL>( - `${DATA}/Strings/en.yaml` + const oldStrings = await vfs.yaml>( + `Data/Strings/en.yaml` ); const patchedStrings = { ...oldStrings, ...newStrings }; const patchedContent = stringifyYaml(patchedStrings); await writeFile( - `${DATA}/Strings/en.yaml`, + `Data/Strings/en.yaml`, new Uint8Array(writeDVPL(Buffer.from(patchedContent))) ); } diff --git a/packages/scripts/src/buildAssets/boosterIcons.ts b/packages/scripts/src/buildAssets/boosterIcons.ts index d1cb9d316..486a732b2 100644 --- a/packages/scripts/src/buildAssets/boosterIcons.ts +++ b/packages/scripts/src/buildAssets/boosterIcons.ts @@ -1,19 +1,16 @@ -import { readdir } from "fs/promises"; import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; -import { readStringDVPL } from "../../src/core/blitz/readStringDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; export async function boosterIcons() { console.log("Building booster icons..."); using uploader = new AssetUploader("booster icons"); - const boosterFiles = (await readdir(`${DATA}/Gfx/Shared/boosters`)).filter( + const boosterFiles = (vfs.dir(`Data/Gfx/Shared/boosters`)).filter( (file) => !file.includes("@2x.txt") && !file.startsWith("texture0") ); const image = sharp( - await readDVPLFile(`${DATA}/Gfx/Shared/boosters/texture0.packed.webp`) + await vfs.file(`Data/Gfx/Shared/boosters/texture0.packed.webp`) ); for (const file of boosterFiles) { @@ -21,7 +18,7 @@ export async function boosterIcons() { if (name === undefined) continue; - const sizes = (await readStringDVPL(`${DATA}/Gfx/Shared/boosters/${file}`)) + const sizes = (await vfs.text(`Data/Gfx/Shared/boosters/${file}`)) .split("\n")[4] .split(" ") .map(Number); diff --git a/packages/scripts/src/buildAssets/camouflageIcons.ts b/packages/scripts/src/buildAssets/camouflageIcons.ts index 726a0c866..f0125a091 100644 --- a/packages/scripts/src/buildAssets/camouflageIcons.ts +++ b/packages/scripts/src/buildAssets/camouflageIcons.ts @@ -1,13 +1,12 @@ -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; export async function camouflageIcons() { console.log("Building camouflage icons..."); using uploader = new AssetUploader("camo icons"); - const content = await readDVPLFile( - `${DATA}/Gfx/UI/Hangar/IconCamouflage.packed.webp` + const content = await vfs.file( + `Data/Gfx/UI/Hangar/IconCamouflage.packed.webp` ); await uploader.add({ content, path: "icons/camo.webp" }); diff --git a/packages/scripts/src/buildAssets/consumableProvisionIcons.ts b/packages/scripts/src/buildAssets/consumableProvisionIcons.ts index 5028f730c..d99903e9c 100644 --- a/packages/scripts/src/buildAssets/consumableProvisionIcons.ts +++ b/packages/scripts/src/buildAssets/consumableProvisionIcons.ts @@ -1,11 +1,6 @@ -import { existsSync } from "fs"; import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; -import { readStringDVPL } from "../../src/core/blitz/readStringDVPL"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; -import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { ConsumablesCommon, ProvisionsCommon } from "./definitions"; interface Mappings { @@ -33,20 +28,20 @@ export async function consumableProvisionIcons() { styles.map(async (path) => Object.values( ( - await readYAMLDVPL(`${DATA}/${path}`) + await vfs.yaml(`Data/${path}`) ).StyleSheets ) ) ).then((array) => array.flat()); for (const match of ( - await readStringDVPL( - `${DATA}/XML/item_defs/vehicles/common/consumables/list.xml` + await vfs.text( + `Data/XML/item_defs/vehicles/common/consumables/list.xml` ) ).matchAll(listItemsPattern)) { - const consumablesCommon = await readXMLDVPL<{ + const consumablesCommon = await vfs.xml<{ root: ConsumablesCommon; - }>(`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`); + }>(`Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`); for (const consumable of Object.values(consumablesCommon.root)) { const styleSheet = styleSheets.find((styleSheet) => @@ -67,9 +62,9 @@ export async function consumableProvisionIcons() { .replace(".psd", "") .replace(".txt", ""); - if (existsSync(`${DATA}/${configPath}.packed.webp`)) { + if (vfs.has(`Data/${configPath}.packed.webp`)) { const image = sharp( - await readDVPLFile(`${DATA}/${configPath}.packed.webp`) + await vfs.file(`Data/${configPath}.packed.webp`) ); const content = await image.trim({ threshold: 100 }).toBuffer(); @@ -79,14 +74,14 @@ export async function consumableProvisionIcons() { }); } else { const consumablesTexture = sharp( - await readDVPLFile( - `${`${DATA}/${configPath}` + await vfs.file( + `${`Data/${configPath}` .split("/") .slice(0, -1) .join("/")}/texture0.packed.webp` ) ); - const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`)) + const sizes = (await vfs.text(`Data/${configPath}.txt`)) .split("\n")[4] .split(" ") .map(Number); @@ -109,13 +104,13 @@ export async function consumableProvisionIcons() { } for (const match of ( - await readStringDVPL( - `${DATA}/XML/item_defs/vehicles/common/provisions/list.xml` + await vfs.text( + `Data/XML/item_defs/vehicles/common/provisions/list.xml` ) ).matchAll(listItemsPattern)) { - const provisionsCommon = await readXMLDVPL<{ + const provisionsCommon = await vfs.xml<{ root: ProvisionsCommon; - }>(`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`); + }>(`Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`); for (const provision of Object.values(provisionsCommon.root)) { const styleSheet = styleSheets.find((styleSheet) => @@ -136,9 +131,9 @@ export async function consumableProvisionIcons() { .replace(".psd", "") .replace(".txt", ""); - if (existsSync(`${DATA}/${configPath}.packed.webp`)) { + if (vfs.has(`Data/${configPath}.packed.webp`)) { const image = sharp( - await readDVPLFile(`${DATA}/${configPath}.packed.webp`) + await vfs.file(`Data/${configPath}.packed.webp`) ); const content = await image.trim({ threshold: 100 }).toBuffer(); @@ -148,14 +143,14 @@ export async function consumableProvisionIcons() { }); } else { const provisionsTexture = sharp( - await readDVPLFile( - `${`${DATA}/${configPath}` + await vfs.file( + `${`Data/${configPath}` .split("/") .slice(0, -1) .join("/")}/texture0.packed.webp` ) ); - const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`)) + const sizes = (await vfs.text(`Data/${configPath}.txt`)) .split("\n")[4] .split(" ") .map(Number); diff --git a/packages/scripts/src/buildAssets/currencies.ts b/packages/scripts/src/buildAssets/currencies.ts index b6a0467a8..71eb4272d 100644 --- a/packages/scripts/src/buildAssets/currencies.ts +++ b/packages/scripts/src/buildAssets/currencies.ts @@ -1,8 +1,7 @@ import { assertSecret, BlitzGlossary } from "@blitzkit/core"; import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; const ICONS = [ ["currency_silver_m.packed.webp", "silver"], @@ -21,7 +20,7 @@ export async function currencies() { for (const [file, name] of ICONS) { const content = await sharp( - await readDVPLFile(`${DATA}/Gfx/Lobby/currency/${file}`) + await vfs.file(`Data/Gfx/Lobby/currency/${file}`) ) .trim() .toBuffer(); diff --git a/packages/scripts/src/buildAssets/equipmentIcons.ts b/packages/scripts/src/buildAssets/equipmentIcons.ts index 40a6cd55b..783d1458d 100644 --- a/packages/scripts/src/buildAssets/equipmentIcons.ts +++ b/packages/scripts/src/buildAssets/equipmentIcons.ts @@ -1,10 +1,6 @@ import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; -import { readStringDVPL } from "../../src/core/blitz/readStringDVPL"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; -import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { OptionalDevices } from "./definitions"; interface Mappings { @@ -20,15 +16,15 @@ export async function equipmentIcons() { console.log("Building equipment icons..."); using uploader = new AssetUploader("equipment icons"); - const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>( - `${DATA}/XML/item_defs/vehicles/common/optional_devices.xml` + const optionalDevices = await vfs.xml<{ root: OptionalDevices }>( + `Data/XML/item_defs/vehicles/common/optional_devices.xml` ); - const mappings = await readYAMLDVPL( - `${DATA}/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml` + const mappings = await vfs.yaml( + `Data/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml` ); const image = sharp( - await readDVPLFile( - `${DATA}/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp` + await vfs.file( + `Data/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp` ) ); @@ -54,7 +50,7 @@ export async function equipmentIcons() { if (configPath.startsWith("Gfx/Lobby")) { const configPathWebp = configPath.replace(".txt", ""); const image = sharp( - await readDVPLFile(`${DATA}/${configPathWebp}.packed.webp`) + await vfs.file(`Data/${configPathWebp}.packed.webp`) ); const content = await image.trim().toBuffer(); @@ -63,7 +59,7 @@ export async function equipmentIcons() { content, }); } else { - const config = await readStringDVPL(`${DATA}/${configPath}`); + const config = await vfs.text(`Data/${configPath}`); const sizes = config.split("\n")[4].split(" ").map(Number); const content = await image .clone() diff --git a/packages/scripts/src/buildAssets/flags.ts b/packages/scripts/src/buildAssets/flags.ts index 59dc04409..dbf3664ff 100644 --- a/packages/scripts/src/buildAssets/flags.ts +++ b/packages/scripts/src/buildAssets/flags.ts @@ -1,37 +1,28 @@ -import { readdir } from "fs/promises"; import sharp from "sharp"; -import { readDVPLFile } from "../core/blitz/readDVPLFile"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; export async function flags() { console.log("Building flags..."); using uploader = new AssetUploader("flags"); - const circleFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then((files) => - files.filter( + const circleFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter( (flag) => flag.startsWith("flag_profile-stat_") && !flag.endsWith("@2x.packed.webp") - ) - ); - const scratchedFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then( - (files) => - files.filter( + ); + const scratchedFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter( (flag) => flag.startsWith("flag_tutor-tank_") && !flag.endsWith("@2x.packed.webp") ) - ); - const fadedFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then((files) => - files.filter( + const fadedFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter( (flag) => flag.startsWith("flag_filter_") && flag.endsWith("@2x.packed.webp") ) - ); for (const flag of circleFiles) { - const image = sharp(await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`)); + const image = sharp(await vfs.file(`Data/Gfx/Lobby/flags/${flag}`)); const content = await image.trim({ threshold: 100 }).toBuffer(); const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1]; @@ -42,7 +33,7 @@ export async function flags() { } for (const flag of scratchedFiles) { - const content = await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`); + const content = await vfs.file(`Data/Gfx/Lobby/flags/${flag}`); const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1]; uploader.add({ @@ -53,7 +44,7 @@ export async function flags() { for (const flag of fadedFiles) { const content = await sharp( - await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`) + await vfs.file(`Data/Gfx/Lobby/flags/${flag}`) ) .trim({ threshold: 100, diff --git a/packages/scripts/src/buildAssets/gameModeBanners.ts b/packages/scripts/src/buildAssets/gameModeBanners.ts index 6c3bb1c10..feaf3b1f9 100644 --- a/packages/scripts/src/buildAssets/gameModeBanners.ts +++ b/packages/scripts/src/buildAssets/gameModeBanners.ts @@ -1,19 +1,17 @@ import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; -import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { SquadBattleTypeStyles } from "./definitions"; export async function gameModeBanners() { console.log("Building game mode banners..."); using uploader = new AssetUploader("game mode banners"); - const gameTypeSelectorStyles = await readYAMLDVPL( - `${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml` + const gameTypeSelectorStyles = await vfs.yaml( + `Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml` ); - const squadBattleTypeStyles = await readYAMLDVPL( - `${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml` + const squadBattleTypeStyles = await vfs.yaml( + `Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml` ); const bannerMatches: { name: string; path: string }[] = []; @@ -37,7 +35,7 @@ export async function gameModeBanners() { } const content = await sharp( - await readDVPLFile(`${DATA}${path}.packed.webp`) + await vfs.file(`Data${path}.packed.webp`) ) .trim({ background: { r: 0, g: 0, b: 0, alpha: 0 } }) .toBuffer(); diff --git a/packages/scripts/src/buildAssets/migration.ts b/packages/scripts/src/buildAssets/migration.ts index 128f4d3d1..64501700b 100644 --- a/packages/scripts/src/buildAssets/migration.ts +++ b/packages/scripts/src/buildAssets/migration.ts @@ -1,8 +1,6 @@ import { toUniqueId } from "@blitzkit/core"; -import { readdir } from "fs/promises"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { VehicleDefinitionList } from "./definitions"; export async function migration() { @@ -10,13 +8,11 @@ export async function migration() { using uploader = new AssetUploader("migration map"); const map: Record = {}; - const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( - (nations) => nations.filter((nation) => nation !== "common") - ); + const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common"); for (const nation of nations) { - const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml` + const tankList = await vfs.xml<{ root: VehicleDefinitionList }>( + `Data/XML/item_defs/vehicles/${nation}/list.xml` ); for (const tankKey in tankList.root) { diff --git a/packages/scripts/src/buildAssets/moduleIcons.ts b/packages/scripts/src/buildAssets/moduleIcons.ts index 9c8ed681c..3d372e489 100644 --- a/packages/scripts/src/buildAssets/moduleIcons.ts +++ b/packages/scripts/src/buildAssets/moduleIcons.ts @@ -1,24 +1,20 @@ -import { readdir } from "fs/promises"; import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; export async function moduleIcons() { console.log("Building module icons..."); using uploader = new AssetUploader("module icons"); - const files = await readdir(`${DATA}/Gfx/UI/ModulesTechTree`).then((dir) => - dir.filter( + const files = vfs.dir(`Data/Gfx/UI/ModulesTechTree`).filter( (file) => !file.endsWith("@2x.packed.webp") && file.startsWith("vehicle") ) - ); for (const file of files) { const nameRaw = file.match(/vehicle(.+)\.packed\.webp/)![1]; const name = nameRaw[0].toLowerCase() + nameRaw.slice(1); const content = await sharp( - await readDVPLFile(`${DATA}/Gfx/UI/ModulesTechTree/${file}`) + await vfs.file(`Data/Gfx/UI/ModulesTechTree/${file}`) ) .trim() .toBuffer(); diff --git a/packages/scripts/src/buildAssets/shellIcons.ts b/packages/scripts/src/buildAssets/shellIcons.ts index c7557eca5..ead72a07d 100644 --- a/packages/scripts/src/buildAssets/shellIcons.ts +++ b/packages/scripts/src/buildAssets/shellIcons.ts @@ -1,28 +1,25 @@ -import { readdir } from "fs/promises"; import sharp from "sharp"; -import { readDVPLFile } from "../../src/core/blitz/readDVPLFile"; -import { readStringDVPL } from "../../src/core/blitz/readStringDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; export async function shellIcons() { console.log("Building shell icons..."); using uploader = new AssetUploader("shell icons"); const image = sharp( - await readDVPLFile( - `${DATA}/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp` + await vfs.file( + `Data/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp` ) ); - const files = await readdir( - `${DATA}/Gfx/Shared/tank-supply/ammunition/big` - ).then((files) => files.filter((file) => file.endsWith("_l.txt"))); + const files = vfs.dir( + `Data/Gfx/Shared/tank-supply/ammunition/big` + ).filter((file) => file.endsWith("_l.txt")) for (const file of files) { const name = file.match(/(.+)_l\.txt/)![1]; const sizes = ( - await readStringDVPL( - `${DATA}/Gfx/Shared/tank-supply/ammunition/big/${file}` + await vfs.text( + `Data/Gfx/Shared/tank-supply/ammunition/big/${file}` ) ) .split("\n")[4] diff --git a/packages/scripts/src/buildAssets/skillIcons.ts b/packages/scripts/src/buildAssets/skillIcons.ts index 2088b31a8..4c6b67a4c 100644 --- a/packages/scripts/src/buildAssets/skillIcons.ts +++ b/packages/scripts/src/buildAssets/skillIcons.ts @@ -1,9 +1,7 @@ import { TankClass } from "@blitzkit/core"; import sharp from "sharp"; -import { readDVPLFile } from "../core/blitz/readDVPLFile"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; interface SkillIcon { name: string; @@ -27,8 +25,8 @@ export interface Avatar { export async function skillIcons() { console.log("Building skill icons..."); - const avatar = await readXMLDVPL<{ root: Avatar }>( - `${DATA}/XML/item_defs/tankmen/avatar.xml` + const avatar = await vfs.xml<{ root: Avatar }>( + `Data/XML/item_defs/tankmen/avatar.xml` ); using uploader = new AssetUploader("skill icons"); @@ -36,8 +34,8 @@ export async function skillIcons() { const skill = avatar.root.skills[key]; const icon = Array.isArray(skill.icon) ? skill.icon[0] : skill.icon; const name = icon.name.split("/").at(-1)!.replace(/_\d$/, ""); - const path = `${DATA}${icon.name.replace("~res:", "")}.packed.webp`; - const image = sharp(await readDVPLFile(path)).trim(); + const path = `Data${icon.name.replace("~res:", "")}.packed.webp`; + const image = sharp(await vfs.file(path)).trim(); const content = await image.toBuffer(); await uploader.add({ content, path: `icons/skills/${name}.webp` }); diff --git a/packages/scripts/src/buildAssets/tankArmors.ts b/packages/scripts/src/buildAssets/tankArmors.ts index e69807d70..0e8de7940 100644 --- a/packages/scripts/src/buildAssets/tankArmors.ts +++ b/packages/scripts/src/buildAssets/tankArmors.ts @@ -1,10 +1,8 @@ import { toUniqueId } from "@blitzkit/core"; import { NodeIO } from "@gltf-transform/core"; -import { readdir } from "fs/promises"; import { extractArmor } from "../core/blitz/extractArmor"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { VehicleDefinitionList } from "./definitions"; export async function tankArmors() { @@ -12,13 +10,11 @@ export async function tankArmors() { using uploader = new AssetUploader("tank armors"); const nodeIO = new NodeIO(); - const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( - (nations) => nations.filter((nation) => nation !== "common") - ); + const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common"); for (const nation of nations) { - const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml` + const tanks = await vfs.xml<{ root: VehicleDefinitionList }>( + `Data/XML/item_defs/vehicles/${nation}/list.xml` ); for (const tankKey in tanks.root) { @@ -27,7 +23,7 @@ export async function tankArmors() { if (tankKey.includes("tutorial_bot")) continue; const id = toUniqueId(nation, tank.id); - const model = await extractArmor(DATA, `${nation}-${tankKey}`); + const model = await extractArmor(vfs, `${nation}-${tankKey}`); const content = await nodeIO.writeBinary(model); await uploader.add({ path: `3d/tanks/armor/${id}.glb`, content }); diff --git a/packages/scripts/src/buildAssets/tankIcons.ts b/packages/scripts/src/buildAssets/tankIcons.ts index 7c69043f4..4ab8000fb 100644 --- a/packages/scripts/src/buildAssets/tankIcons.ts +++ b/packages/scripts/src/buildAssets/tankIcons.ts @@ -1,12 +1,8 @@ import { NATION_IDS } from "@blitzkit/core"; -import { readdir } from "fs/promises"; import sharp from "sharp"; import type { Vector3Tuple } from "three"; -import { readDVPLFile } from "../core/blitz/readDVPLFile"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; -import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import type { VehicleDefinitionList } from "./definitions"; export interface TankParameters { @@ -45,13 +41,11 @@ export async function tankIcons() { console.log("Building tank icons..."); using uploader = new AssetUploader("tank icons"); - const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( - (nations) => nations.filter((nation) => nation !== "common") - ); + const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common") for (const nation of nations) { - const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml` + const tanks = await vfs.xml<{ root: VehicleDefinitionList }>( + `Data/XML/item_defs/vehicles/${nation}/list.xml` ); for (const tankKey in tanks.root) { @@ -62,19 +56,19 @@ export async function tankIcons() { const nationVehicleId = tank.id; const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; - const parameters = await readYAMLDVPL( - `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` + const parameters = await vfs.yaml( + `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` ); - const smallPath = `${DATA}/${parameters.resourcesPath.smallIconPath + const smallPath = `Data/${parameters.resourcesPath.smallIconPath .replace(/~res:\//, "") .replace(/\..+/, "")}.packed.webp`; - const bigPath = `${DATA}/${parameters.resourcesPath.bigIconPath + const bigPath = `Data/${parameters.resourcesPath.bigIconPath .replace(/~res:\//, "") .replace(/\..+/, "")}.packed.webp`; - const big = await sharp(await readDVPLFile(bigPath)) + const big = await sharp(await vfs.file(bigPath)) .trim() .toBuffer(); - const small = await sharp(await readDVPLFile(smallPath)) + const small = await sharp(await vfs.file(smallPath)) .trim() .toBuffer(); diff --git a/packages/scripts/src/buildAssets/tankModels.ts b/packages/scripts/src/buildAssets/tankModels.ts index ff206605b..ca206dad4 100644 --- a/packages/scripts/src/buildAssets/tankModels.ts +++ b/packages/scripts/src/buildAssets/tankModels.ts @@ -1,12 +1,9 @@ import { toUniqueId } from "@blitzkit/core"; import { NodeIO } from "@gltf-transform/core"; import { ALL_EXTENSIONS } from "@gltf-transform/extensions"; -import { readdir } from "fs/promises"; import { extractModel } from "../core/blitz/extractModel"; -import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; -import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { AssetUploader } from "../core/github/assetUploader"; -import { DATA } from "./constants"; +import { vfs } from "./constants"; import { VehicleDefinitionList } from "./definitions"; import { TankParameters } from "./tankIcons"; @@ -15,14 +12,12 @@ export async function tankModels() { using uploader = new AssetUploader("tank models"); const nodeIO = new NodeIO().registerExtensions(ALL_EXTENSIONS); - const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( - (nations) => nations.filter((nation) => nation !== "common") - ); + const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common") for (const nationIndex in nations) { const nation = nations[nationIndex]; - const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml` + const tanks = await vfs.xml<{ root: VehicleDefinitionList }>( + `Data/XML/item_defs/vehicles/${nation}/list.xml` ); const entries = Object.entries(tanks.root); @@ -30,11 +25,11 @@ export async function tankModels() { if (tankKey.includes("tutorial_bot")) continue; const id = toUniqueId(nation, tank.id); - const parameters = await readYAMLDVPL( - `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` + const parameters = await vfs.yaml( + `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` ); const model = await extractModel( - DATA, + vfs, parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, "") ); const content = Buffer.from(await nodeIO.writeBinary(model)); diff --git a/packages/scripts/src/core/blitz/extractArmor.ts b/packages/scripts/src/core/blitz/extractArmor.ts index 5d55e9a63..2973e5a8f 100644 --- a/packages/scripts/src/core/blitz/extractArmor.ts +++ b/packages/scripts/src/core/blitz/extractArmor.ts @@ -2,24 +2,24 @@ import { Hierarchy, Sc2ReadStream, ScgReadStream, + SteamVFS, VertexAttribute, -} from '@blitzkit/core'; -import { Accessor, Document, Node, Scene } from '@gltf-transform/core'; -import { times } from 'lodash-es'; +} from "@blitzkit/core"; +import { Accessor, Document, Node, Scene } from "@gltf-transform/core"; +import { times } from "lodash-es"; import { vertexAttributeGLTFName, vertexAttributeGltfVectorSizes, -} from './extractModel/constants'; -import { readDVPLFile } from './readDVPLFile'; +} from "./extractModel/constants"; -export async function extractArmor(data: string, fileName: string) { - const sc2Path = `${data}/3d/Tanks/CollisionMeshes/${fileName}.sc2`; - const scgPath = `${data}/3d/Tanks/CollisionMeshes/${fileName}.scg`; +export async function extractArmor(vfs: SteamVFS, fileName: string) { + const sc2Path = `Data/3d/Tanks/CollisionMeshes/${fileName}.sc2`; + const scgPath = `Data/3d/Tanks/CollisionMeshes/${fileName}.scg`; const sc2 = new Sc2ReadStream( - (await readDVPLFile(sc2Path)).buffer as ArrayBuffer, + (await vfs.file(sc2Path)).buffer as ArrayBuffer ).sc2(); const scg = new ScgReadStream( - (await readDVPLFile(scgPath)).buffer as ArrayBuffer, + (await vfs.file(scgPath)).buffer as ArrayBuffer ).scg(); const document = new Document(); const scene = document.createScene(); @@ -29,21 +29,21 @@ export async function extractArmor(data: string, fileName: string) { hierarchies.forEach((hierarchy) => { const components = times( hierarchy.components.count, - (index) => hierarchy.components[index.toString().padStart(4, '0')], + (index) => hierarchy.components[index.toString().padStart(4, "0")] ); components.forEach((component) => { - switch (component['comp.typename']) { - case 'TransformComponent': + switch (component["comp.typename"]) { + case "TransformComponent": break; - case 'RenderComponent': { - const batch = component['rc.renderObj']['ro.batches']['0000']; - const polygonGroup = scg.get(batch['rb.datasource']); + case "RenderComponent": { + const batch = component["rc.renderObj"]["ro.batches"]["0000"]; + const polygonGroup = scg.get(batch["rb.datasource"]); if (!polygonGroup) { console.warn( - `Missing polygon group ${batch['rb.datasource']} (${hierarchy.name}); skipping...`, + `Missing polygon group ${batch["rb.datasource"]} (${hierarchy.name}); skipping...` ); break; @@ -73,7 +73,7 @@ export async function extractArmor(data: string, fileName: string) { VertexAttribute.TANGENT, attributes .get(VertexAttribute.TANGENT)! - .map((tangent) => [...tangent, 1]), + .map((tangent) => [...tangent, 1]) ); } @@ -85,7 +85,7 @@ export async function extractArmor(data: string, fileName: string) { const vertexSize = vertexAttributeGltfVectorSizes[attribute]; const accessor = document .createAccessor(name) - .setType(vertexSize === 1 ? 'SCALAR' : `VEC${vertexSize}`) + .setType(vertexSize === 1 ? "SCALAR" : `VEC${vertexSize}`) .setArray(new Float32Array(value.flat())) .setBuffer(buffer); @@ -94,19 +94,19 @@ export async function extractArmor(data: string, fileName: string) { hardJointIndices.forEach((hardJointIndex) => { const node = document.createNode( - `${hierarchy.name}_armor_${hardJointIndex}`, + `${hierarchy.name}_armor_${hardJointIndex}` ); - const mesh = document.createMesh(batch['##name']); + const mesh = document.createMesh(batch["##name"]); const indicesAccessor = document .createAccessor() - .setType('SCALAR') + .setType("SCALAR") .setArray( new Uint16Array( polygonGroup.indices.filter( (index) => - vertexHardJointIndices.get(index) === hardJointIndex, - ), - ), + vertexHardJointIndices.get(index) === hardJointIndex + ) + ) ) .setBuffer(buffer); const primitive = document @@ -127,18 +127,18 @@ export async function extractArmor(data: string, fileName: string) { default: throw new TypeError( - `Unhandled component type: ${component['comp.typename']}`, + `Unhandled component type: ${component["comp.typename"]}` ); } }); - if (hierarchy['#hierarchy']) { - parseHierarchies(hierarchy['#hierarchy'], parent); + if (hierarchy["#hierarchy"]) { + parseHierarchies(hierarchy["#hierarchy"], parent); } }); } - parseHierarchies(sc2['#hierarchy'], scene); + parseHierarchies(sc2["#hierarchy"], scene); return document; } diff --git a/packages/scripts/src/core/blitz/extractModel/index.ts b/packages/scripts/src/core/blitz/extractModel/index.ts index 7f888def8..20b7ce82e 100644 --- a/packages/scripts/src/core/blitz/extractModel/index.ts +++ b/packages/scripts/src/core/blitz/extractModel/index.ts @@ -2,6 +2,7 @@ import { Hierarchy, Sc2ReadStream, ScgReadStream, + SteamVFS, Textures, VertexAttribute, } from "@blitzkit/core"; @@ -10,7 +11,6 @@ import { dedup, prune } from "@gltf-transform/functions"; import { times } from "lodash-es"; import { dirname } from "path"; import { readBaseColor } from "../readBaseColor"; -import { readDVPLFile } from "../readDVPLFile"; import { readNormal } from "../readNormal"; import { readRoughnessMetallic } from "../readRoughnessMetallic"; import { @@ -25,14 +25,14 @@ const omitMeshNames = { end: ["_POINT"], }; -export async function extractModel(data: string, path: string) { - const sc2Path = `${data}/3d/${path}.sc2`; - const scgPath = `${data}/3d/${path}.scg`; +export async function extractModel(vfs: SteamVFS, path: string) { + const sc2Path = `Data/3d/${path}.sc2`; + const scgPath = `Data/3d/${path}.scg`; const sc2 = new Sc2ReadStream( - (await readDVPLFile(sc2Path)).buffer as ArrayBuffer + (await vfs.file(sc2Path)).buffer as ArrayBuffer ).sc2(); const scg = new ScgReadStream( - (await readDVPLFile(scgPath)).buffer as ArrayBuffer + (await vfs.file(scgPath)).buffer as ArrayBuffer ).scg(); const document = new Document(); const scene = document.createScene(); @@ -67,11 +67,11 @@ export async function extractModel(data: string, path: string) { .setMimeType("image/webp") .setImage( await readBaseColor( - `${data}/3d/${dirname(path)}/${ + `Data/3d/${dirname(path)}/${ textures.baseColorMap ?? textures.albedo }`, textures.miscMap - ? `${data}/3d/${dirname(path)}/${textures.miscMap}` + ? `Data/3d/${dirname(path)}/${textures.miscMap}` : undefined ) ) @@ -103,7 +103,7 @@ export async function extractModel(data: string, path: string) { .setMimeType("image/webp") .setImage( await readRoughnessMetallic( - `${data}/3d/${dirname(path)}/${textures.baseRMMap}` + `Data/3d/${dirname(path)}/${textures.baseRMMap}` ) ) ); @@ -118,7 +118,7 @@ export async function extractModel(data: string, path: string) { .setMimeType("image/webp") .setImage( await readNormal( - `${data}/3d/${dirname(path)}/${ + `Data/3d/${dirname(path)}/${ textures.baseNormalMap ?? textures.normalmap }`, isBase diff --git a/packages/scripts/src/core/blitz/readBase64DVPL.ts b/packages/scripts/src/core/blitz/readBase64DVPL.ts deleted file mode 100644 index 4e50b9042..000000000 --- a/packages/scripts/src/core/blitz/readBase64DVPL.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { readDVPLFile } from './readDVPLFile'; - -export async function readBase64DVPL(file: string) { - const buffer = await readDVPLFile(file); - return buffer.toString('base64'); -} diff --git a/packages/scripts/src/core/blitz/readDVPLFile.ts b/packages/scripts/src/core/blitz/readDVPLFile.ts deleted file mode 100644 index 422ef7258..000000000 --- a/packages/scripts/src/core/blitz/readDVPLFile.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { readFile } from 'fs/promises'; -import { DATA_COMPRESSED } from '../../buildAssets/constants'; -import { readDVPL } from './readDVPL'; - -export async function readDVPLFile(file: string) { - let path: string; - - if (DATA_COMPRESSED) { - path = file.endsWith('.dvpl') ? file : `${file}.dvpl`; - } else { - path = file.replace('.dvpl', ''); - } - - const content = await readFile(path); - - if (!DATA_COMPRESSED) return content; - - const dvpl = readDVPL(content); - - return dvpl; -} diff --git a/packages/scripts/src/core/blitz/readTexture/index.ts b/packages/scripts/src/core/blitz/readTexture/index.ts index 9893fcd2b..484889a61 100644 --- a/packages/scripts/src/core/blitz/readTexture/index.ts +++ b/packages/scripts/src/core/blitz/readTexture/index.ts @@ -1,81 +1,17 @@ import { DdsReadStream, PvrReadStream } from "@blitzkit/core"; -import { existsSync } from "fs"; -import { DATA_COMPRESSED } from "../../../buildAssets/constants"; -import { readDVPLFile } from "../readDVPLFile"; +import { vfs } from "../../../buildAssets/constants"; export async function readTexture(path: string) { const ddsTexturePath = path.replace(".tex", ".dx11.dds"); - const isDds = existsSync( - `${ddsTexturePath}${DATA_COMPRESSED ? ".dvpl" : ""}` - ); + const isDds = vfs.has(ddsTexturePath); const resolvedTexturePath = isDds ? ddsTexturePath : ddsTexturePath.replace(".dds", ".pvr"); - const decompressedDvpl = await readDVPLFile(`${resolvedTexturePath}.dvpl`); + const decompressedDvpl = await vfs.file(`${resolvedTexturePath}.dvpl`); const raw = isDds ? await new DdsReadStream(decompressedDvpl.buffer as ArrayBuffer).dds() : new PvrReadStream(decompressedDvpl.buffer as ArrayBuffer).pvr(); return raw; - - // switch (mutation) { - // case TextureMutation.Normal: { - // const bytes = 4 * raw.width * raw.height; - // for (let index = 0; index < bytes; index += 4) { - // /** - // * Red is always 255 and blue is always 0. Only alpha and green contain any - // * sort of information. - // */ - // let x = raw.data[index + 3] * (2 / 255) - 1; - // let y = raw.data[index + 1] * (2 / 255) - 1; - // const underSqrt = 1 - x ** 2 - y ** 2; - // let z = underSqrt > 0 ? Math.sqrt(underSqrt) : -Math.sqrt(-underSqrt); - - // raw.data[index] = Math.round((x + 1) * (255 / 2)); - // raw.data[index + 1] = Math.round((y + 1) * (255 / 2)); - // raw.data[index + 2] = Math.round((z + 1) * (255 / 2)); - // raw.data[index + 3] = 255; - // } - - // return await sharp(raw.data, { raw }).jpeg().toBuffer(); - // } - - // case TextureMutation.RoughnessMetallicness: { - // const newImage = sharp(Buffer.alloc(raw.width * raw.height), { - // raw: { ...raw, channels: 1 }, - // }); - // const metallicness = sharp(raw.data, { raw }) - // .extractChannel("green") - // .jpeg() - // .toBuffer(); - // const roughness = sharp(raw.data, { raw }) - // .extractChannel("alpha") - // .jpeg() - // .toBuffer(); - - // return await newImage - // .joinChannel(await Promise.all([roughness, metallicness])) - // .jpeg() - // .toBuffer(); - // } - - // case TextureMutation.Miscellaneous: { - // /** - // * Alpha is ambient occlusion and green is emissive. But very few tanks - // * use emissive so I am ignoring it for now. - // */ - // return await sharp(raw.data, { raw }) - // .extractChannel("alpha") - // .jpeg() - // .toBuffer(); - // } - - // case TextureMutation.Albedo: { - // return await sharp(raw.data, { raw }).removeAlpha().jpeg().toBuffer(); - // } - - // default: - // return await sharp(raw.data, { raw }).jpeg().toBuffer(); - // } } diff --git a/packages/scripts/src/setupDepotDownloader.ts b/packages/scripts/src/setupDepotDownloader.ts index ab4fe84f4..72ef9322b 100644 --- a/packages/scripts/src/setupDepotDownloader.ts +++ b/packages/scripts/src/setupDepotDownloader.ts @@ -1,39 +1,39 @@ -import decompress from 'decompress'; -import { existsSync } from 'fs'; -import { mkdir, readdir, writeFile } from 'fs/promises'; +import decompress from "decompress"; +import { existsSync } from "fs"; +import { mkdir, readdir, writeFile } from "fs/promises"; -if (!existsSync('../../temp')) { - console.log('Creating temp directory...'); - await mkdir('../../temp'); +if (!existsSync("../../temp")) { + console.log("Creating temp directory..."); + await mkdir("../../temp"); } -console.log('Downloading depot downloader...'); +console.log("Downloading depot downloader..."); await fetch( - 'https://api.github.com/repos/SteamRE/DepotDownloader/releases/latest', + "https://api.github.com/repos/SteamRE/DepotDownloader/releases/latest" ) .then( (response) => response.json() as Promise<{ assets: { browser_download_url: string; name: string }[]; - }>, + }> ) .then(({ assets }) => { - const asset = assets.find(({ name }) => name.includes('linux-x64')); - if (!asset) throw new Error('No asset found'); + const asset = assets.find(({ name }) => name.includes("linux-x64")); + if (!asset) throw new Error("No asset found"); return fetch(asset.browser_download_url); }) .then((response) => response.arrayBuffer()) .then((arrayBuffer) => - writeFile('../../temp/depotDownloader.zip', new Uint8Array(arrayBuffer)), + writeFile("../../temp/depotDownloader.zip", new Uint8Array(arrayBuffer)) ); -console.log('Unzipping...'); +console.log("Unzipping..."); await decompress( - '../../temp/depotDownloader.zip', - '../../temp/depotDownloader', + "../../temp/depotDownloader.zip", + "../../temp/depotDownloader" ); console.log( - 'Download complete; files:', - await readdir('../../temp/depotDownloader'), + "Download complete; files:", + await readdir("../../temp/depotDownloader") );