mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
remove assets
This commit is contained in:
1 parent
24297dcae8
commit
84290b1c0e
9 files changed
-571
No files matched your search
@@ -1,83 +0,0 @@
|
|||||||
name: Assets
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: production
|
|
||||||
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
asset_repo:
|
|
||||||
type: choice
|
|
||||||
required: false
|
|
||||||
description: What asset repo to write to
|
|
||||||
options:
|
|
||||||
- blitzkit/assets
|
|
||||||
- blitzkit/assets-preview
|
|
||||||
- blitzkit/assets-dev
|
|
||||||
default: blitzkit/assets
|
|
||||||
|
|
||||||
asset_source:
|
|
||||||
type: string
|
|
||||||
required: false
|
|
||||||
description: "Archive URL or Steam to download (example: steam:APP_ID/DEPOT_ID or zip:URL_TO_ZIP)"
|
|
||||||
default: "steam:444200/444202"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.inputs.asset_repo }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }}
|
|
||||||
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
|
|
||||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
||||||
VIDEOS_SHEET: ${{ secrets.VIDEOS_SHEET }}
|
|
||||||
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
|
|
||||||
WOTB_GLOSSARY: ${{ secrets.WOTB_GLOSSARY }}
|
|
||||||
WOTB_DLC_CDN: ${{ secrets.WOTB_DLC_CDN }}
|
|
||||||
PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }}
|
|
||||||
PUBLIC_ASSET_REPO: ${{ github.event.inputs.asset_repo != '' && github.event.inputs.asset_repo || secrets.PUBLIC_ASSET_REPO }}
|
|
||||||
PUBLIC_ASSET_BRANCH: ${{ secrets.PUBLIC_ASSET_BRANCH }}
|
|
||||||
WOTB_GLOSSARY_DOMAIN: ${{ secrets.WOTB_GLOSSARY_DOMAIN }}
|
|
||||||
WOTB_GLOSSARY_PATH: ${{ secrets.WOTB_GLOSSARY_PATH }}
|
|
||||||
PUBLIC_PROMOTE_OPENTEST: ${{ secrets.PUBLIC_PROMOTE_OPENTEST }}
|
|
||||||
ALLOW_ROBOTS: true
|
|
||||||
PUBLIC_GOOGLE_TAG_MANAGER_ID: ${{ secrets.PUBLIC_GOOGLE_TAG_MANAGER_ID }}
|
|
||||||
PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ${{ secrets.PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID }}
|
|
||||||
PUBLIC_PATREON_CLIENT_ID: ${{ secrets.PUBLIC_PATREON_CLIENT_ID }}
|
|
||||||
PUBLIC_PATREON_REDIRECT_URI: ${{ secrets.PUBLIC_PATREON_REDIRECT_URI }}
|
|
||||||
PATREON_CLIENT_SECRET: ${{ secrets.PATREON_CLIENT_SECRET }}
|
|
||||||
PUBLIC_NITROPAY_ID: ${{ secrets.PUBLIC_NITROPAY_ID }}
|
|
||||||
PUBLIC_DEBUG_MISSING_I18N: false
|
|
||||||
PUBLIC_DISCORD_SERVER_ID: ${{ secrets.PUBLIC_DISCORD_SERVER_ID }}
|
|
||||||
PUBLIC_ASSET_FAST_USER: blitzkit
|
|
||||||
PUBLIC_ASSET_FAST_REPO: assets
|
|
||||||
PUBLIC_ASSET_BASE: ${{ secrets.PUBLIC_ASSET_BASE }}
|
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
||||||
STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
|
|
||||||
STEAM_PASSWORD: ${{ secrets.STEAM_PASSWORD }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_assets:
|
|
||||||
name: Build assets
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
|
||||||
- uses: arduino/setup-protoc@v3
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GH_TOKEN }}
|
|
||||||
- uses: oven-sh/setup-bun@v2
|
|
||||||
|
|
||||||
- run: bun run setup
|
|
||||||
|
|
||||||
- name: AppArmor hack
|
|
||||||
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
|
|
||||||
|
|
||||||
- name: Install patches
|
|
||||||
run: bun run setup:patches --source=${{ github.event.inputs.asset_source || 'steam:444200/444202' }}
|
|
||||||
|
|
||||||
- name: Build assets
|
|
||||||
run: bun run build:assets --all-targets --source=${{ github.event.inputs.asset_source || 'steam:444200/444202' }}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user