remove assets

This commit is contained in:
tresabhi committed 2026-08-05 13:19:27 -05:00
1 parent 24297dcae8
commit 84290b1c0e
9 files changed
-571

No files matched your search

@@ -1,43 +0,0 @@
import { assertSecret } from "@blitzkit/core";
import { AbstractVFS } from "@blitzkit/core/src/blitzkit/vfs/abstract";
import { LocalVFS } from "@blitzkit/core/src/blitzkit/vfs/local";
import { MixedVFS } from "@blitzkit/core/src/blitzkit/vfs/mixed";
import { SteamVFS } from "@blitzkit/core/src/blitzkit/vfs/steam";
import { ZipVFS } from "@blitzkit/core/src/blitzkit/vfs/zip";
export const PATCHES_ROOT = "../../temp/patches";
const steamPattern = /steam:(\d+)\/(\d+)/;
const zipPattern = /zip:(.+)/;
const localePattern = /local:"?(.+)"?/;
const source = Bun.argv
.find((arg) => arg.startsWith("--source="))
?.split("=")[1];
let resolved: AbstractVFS;
if (!source) {
throw new Error("No source specified");
} else if (steamPattern.test(source)) {
const [, app, depot] = source.match(steamPattern)!.map(Number);
resolved = await new SteamVFS(
assertSecret(import.meta.env.STEAM_USERNAME),
assertSecret(import.meta.env.STEAM_PASSWORD),
app,
depot,
).init();
} else if (zipPattern.test(source)) {
const [, url] = source.match(zipPattern)!;
resolved = await new ZipVFS(url).init();
} else if (localePattern.test(source)) {
const [, path] = source.match(localePattern)!;
resolved = await new LocalVFS(path).init();
} else {
throw new Error("No valid source specified");
}
resolved = new MixedVFS([new LocalVFS(PATCHES_ROOT), resolved]);
export const vfs = resolved;
@@ -1,73 +0,0 @@
import sharp from "sharp";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants";
import { OptionalDevices } from "./definitions";
export async function equipmentIcons() {
console.log("Building equipment icons...");
using uploader = new AssetUploader("equipment icons");
const optionalDevices = await vfs.xml<{ root: OptionalDevices }>(
`Data/XML/item_defs/vehicles/common/optional_devices.xml`,
);
const mappings = await vfs.yaml<Mappings>(
`Data/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml`,
);
const image = sharp(
await vfs.file(
`Data/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp`,
),
);
for (const optionalDeviceKey in optionalDevices.root) {
const optionalDevice = optionalDevices.root[optionalDeviceKey];
if (optionalDeviceKey === "nextAvailableId") continue;
const mapping = mappings.StyleSheets.find((mapping) =>
mapping.selectors.includes(
`.optional_device_item.${optionalDevice.icon} #Img`,
),
);
if (!mapping) {
console.warn(`No mapping found for ${optionalDevice.icon}; skipping...`);
continue;
}
const configPathRaw = mapping.properties["bg-sprite"];
const configPath = configPathRaw.replace("~res:/", "");
if (configPath.startsWith("Gfx/Lobby")) {
const configPathWebp = configPath.replace(".txt", "");
const image = sharp(await vfs.file(`Data/${configPathWebp}.packed.webp`));
const content = await image.trim().toBuffer();
await uploader.add({
path: `icons/equipment/${optionalDevice.id}.webp`,
content,
});
} else {
const config = await vfs.text(`Data/${configPath}`);
const sizes = config.split("\n")[4].split(" ").map(Number);
const content = await image
.clone()
.extract({
left: sizes[0],
top: sizes[1],
width: sizes[2],
height: sizes[3],
})
.toBuffer();
await uploader.add({
path: `icons/equipment/${optionalDevice.id}.webp`,
content,
});
}
}
await uploader.flush();
}
@@ -1,89 +0,0 @@
import { Avatar, fetchGlossary, Gallery } from "@blitzkit/core";
import locales from "@blitzkit/i18n/locales.json";
import { extname } from "path";
import ProgressBar from "progress";
import { AssetUploader } from "../core/github/assetUploader";
export async function glossary() {
console.log("Building glossary...");
using uploader = new AssetUploader("glossary");
const avatars: Record<string, { avatar: Avatar; url: string }> = {};
await Promise.all(
locales.supported.map(async (supported) => {
const glossary = await fetchGlossary(supported.blitz ?? supported.locale);
console.log(
`Found ${Object.keys(glossary).length} things for ${supported.locale}`,
);
for (const key in glossary) {
const glossaryEntry = glossary[key];
if (
!key.startsWith("avatar") ||
key.endsWith("_part") ||
glossaryEntry.image_url === null
) {
continue;
}
if (key in avatars) {
avatars[key].avatar.name!.locales[supported.locale] =
glossaryEntry.title;
} else {
const extension = extname(glossaryEntry.image_url);
avatars[key] = {
url: glossaryEntry.image_url,
avatar: {
id: key,
name: { locales: { [supported.locale]: glossaryEntry.title } },
extension,
},
};
}
}
}),
);
const gallery: Gallery = { avatars: [] };
const totalCount = Object.keys(avatars).length;
const bar = new ProgressBar(
`Fetching avatars of ${totalCount} things :bar`,
totalCount,
);
await Promise.all(
Object.entries(avatars).map(async ([key, { url, avatar }]) => {
if (!(locales.default in avatars[key].avatar.name!.locales)) {
console.warn(`Avatar ${key} has no ${locales.default} name`);
bar.tick();
return;
}
gallery.avatars.push(avatar);
const content = await fetch(url)
.then((response) => response.arrayBuffer())
.then((buffer) => new Uint8Array(buffer));
await uploader.add({
path: `gallery/avatars/${key}${avatar.extension}`,
content,
});
bar.tick();
}),
);
await uploader.add({
path: "definitions/gallery.pb",
content: Gallery.encode(gallery).finish(),
});
await uploader.flush();
}
-64
View File
@@ -1,64 +0,0 @@
import { config } from "dotenv";
import { argv } from "process";
import { boosterIcons } from "./boosterIcons";
import { camouflageIcons } from "./camouflageIcons";
import { vfs } from "./constants";
import { consumableProvisionIcons } from "./consumableProvisionIcons";
import { currencies } from "./currencies";
import { definitions } from "./definitions";
import { equipmentIcons } from "./equipmentIcons";
import { flags } from "./flags";
import { gameModeBanners } from "./gameModeBanners";
import { glossary } from "./glossary";
import { migration } from "./migration";
import { moduleIcons } from "./moduleIcons";
import { popularTanks } from "./popularTanks";
import { shellIcons } from "./shellIcons";
import { skillIcons } from "./skillIcons";
import { tankArmors } from "./tankArmors";
import { tankIcons } from "./tankIcons";
import { tankModels } from "./tankModels";
config();
const allTargets = argv.includes("--all-targets");
const targets = argv
.find((argument) => argument.startsWith("--target"))
?.split("=")[1]
.split(",");
if (!targets && !allTargets) throw new Error("No target(s) specified");
const methods = [
definitions,
tankIcons,
tankModels,
tankArmors,
gameModeBanners,
currencies,
skillIcons,
flags,
shellIcons,
moduleIcons,
equipmentIcons,
consumableProvisionIcons,
camouflageIcons,
boosterIcons,
glossary,
migration,
popularTanks,
];
for (const method of methods) {
if (allTargets || targets?.includes(method.name)) {
try {
await method();
} catch (error) {
console.warn(`Failed method ${method.name}; skipping...`);
console.error(error);
}
}
}
vfs.dispose();
process.exit(0);
@@ -1,34 +0,0 @@
import { toUniqueId } from "@blitzkit/core";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants";
import { VehicleDefinitionList } from "./definitions";
export async function migration() {
console.log("Building migration map...");
using uploader = new AssetUploader("migration map");
const map: Record<string, number> = {};
const nations = await vfs
.dir(`Data/XML/item_defs/vehicles`)
.then((files) => files.filter((nation) => nation !== "common"));
for (const nation of nations) {
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
);
for (const tankKey in tankList.root) {
const tank = tankList.root[tankKey];
const tankId = toUniqueId(nation, tank.id);
const davaKey = `${nation}:${tankKey}`;
map[davaKey] = tankId;
}
}
await uploader.add({
path: "definitions/migration.json",
content: new TextEncoder().encode(JSON.stringify(map)),
});
await uploader.flush();
}
@@ -1,77 +0,0 @@
import {
assertSecret,
fetchTankDefinitions,
PopularTanks,
} from "@blitzkit/core";
import { google } from "googleapis";
import { AssetUploader } from "../core/github/assetUploader";
export async function popularTanks() {
using uploader = new AssetUploader("popular tanks");
const tankDefinitions = await fetchTankDefinitions();
const auth = await google.auth.getClient({
keyFile: import.meta.env.GOOGLE_APPLICATION_CREDENTIALS,
scopes: ["https://www.googleapis.com/auth/analytics.readonly"],
});
const analytics = google.analyticsdata({ version: "v1beta", auth });
const report = await analytics.properties.runReport({
property: `properties/${assertSecret(
import.meta.env.PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID,
)}`,
requestBody: {
dateRanges: [{ startDate: "7daysAgo", endDate: "today" }],
dimensions: [{ name: "pagePath" }],
metrics: [{ name: "screenPageViews" }],
orderBys: [{ metric: { metricName: "screenPageViews" }, desc: true }],
dimensionFilter: {
filter: {
fieldName: "pagePath",
stringFilter: {
matchType: "BEGINS_WITH",
value: "/tanks/",
},
},
},
},
});
if (!report.data.rows) {
throw new Error("No rows in report");
}
const tanks = report.data.rows
.filter(
(row) =>
row.dimensionValues &&
row.dimensionValues[0].value &&
row.dimensionValues[0].value !== "/tanks/" &&
row.metricValues &&
row.metricValues[0].value,
)
.map((row) => ({
id: Number(
row.dimensionValues![0].value!.match(
/\/tools\/tankopedia\/(\d+)\/?/,
)?.[1],
),
views: Number(row.metricValues![0].value!),
}))
.filter((row) => {
if (!(row.id in tankDefinitions.tanks)) {
console.warn("Skipping unknown popular tank", row.id);
return false;
}
return row.id in tankDefinitions.tanks;
})
.slice(0, 8)
.map(({ id, views }) => ({ id, views }));
const popularTanks: PopularTanks = { tanks };
await uploader.add({
path: "definitions/popular-tanks.pb",
content: PopularTanks.encode(popularTanks).finish(),
});
await uploader.flush();
}
@@ -1,64 +0,0 @@
import { NATION_IDS } from "@blitzkit/core";
import sharp from "sharp";
import { parsePackedSpriteRect } from "../core/blitz/parsePackedSpriteRect";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants";
import type { VehicleDefinitionList } from "./definitions";
export async function tankIcons() {
console.log("Building tank icons...");
using uploader = new AssetUploader("tank icons");
const nations = await vfs
.dir(`Data/XML/item_defs/vehicles`)
.then((files) => files.filter((nation) => nation !== "common"));
for (const nation of nations) {
const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
);
for (const tankKey in tanks.root) {
const tank = tanks.root[tankKey];
if (tankKey.includes("tutorial_bot")) continue;
const nationVehicleId = tank.id;
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
const parameters = await vfs.yaml<TankParameters>(
`Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
);
const smallPath = `Data/${parameters.resourcesPath.smallIconPath
.replace(/~res:\//, "")
.replace(/\..+/, "")}.packed.webp`;
const bigPath = `Data/${parameters.resourcesPath.bigIconPath
.replace(/~res:\//, "")
.replace(/\..+/, "")}.packed.webp`;
const big = await extractPackedTankIcon(
await vfs.file(bigPath),
`tank ${tankKey} big`,
);
const small = await extractPackedTankIcon(
await vfs.file(smallPath),
`tank ${tankKey} small`,
);
if (big) {
await uploader.add({
content: big,
path: `icons/tanks/big/${id}.webp`,
});
}
if (small) {
await uploader.add({
content: small,
path: `icons/tanks/small/${id}.webp`,
});
}
}
}
await uploader.flush();
}
@@ -1,44 +0,0 @@
import { toUniqueId } from "@blitzkit/core";
import { NodeIO } from "@gltf-transform/core";
import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
import { extractModel } from "../core/blitz/extractModel";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants";
import { VehicleDefinitionList } from "./definitions";
import { TankParameters } from "./tankIcons";
export async function tankModels() {
console.log("Building tank models...");
using uploader = new AssetUploader("tank models");
const nodeIO = new NodeIO().registerExtensions(ALL_EXTENSIONS);
const nations = await vfs
.dir(`Data/XML/item_defs/vehicles`)
.then((files) => files.filter((nation) => nation !== "common"));
for (const nationIndex in nations) {
const nation = nations[nationIndex];
const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
);
const entries = Object.entries(tanks.root);
for (const [tankKey, tank] of entries) {
if (tankKey.includes("tutorial_bot")) continue;
const id = toUniqueId(nation, tank.id);
const parameters = await vfs.yaml<TankParameters>(
`Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
);
const model = await extractModel(
vfs,
parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ""),
);
const content = Buffer.from(await nodeIO.writeBinary(model));
await uploader.add({ path: `3d/tanks/models/${id}.glb`, content });
}
}
await uploader.flush();
}