mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: localize game assets
This commit is contained in:
1 parent
d8459d373c
commit
ef9778ea96
90 files changed
+336
-251
No files matched your search
@@ -9,7 +9,7 @@ import { DATA } from './buildAssets/constants';
|
||||
import { readYAMLDVPL } from './core/blitz/readYAMLDVPL';
|
||||
import { writeDVPL } from './core/blitz/writeDVPL';
|
||||
|
||||
const versionTextFile = await readStringDVPL(`${DATA}/version.txt.dvpl`);
|
||||
const versionTextFile = await readStringDVPL(`${DATA}/version.txt`);
|
||||
const currentVersion = versionTextFile
|
||||
.split(' ')[0]
|
||||
.split('.')
|
||||
@@ -51,7 +51,7 @@ while (true) {
|
||||
|
||||
await mkdir(`${DATA}/${dir}`, { recursive: true });
|
||||
await writeFile(
|
||||
`${DATA}/${path}.dvpl`,
|
||||
`${DATA}/${path}`,
|
||||
new Uint8Array(writeDVPL(Buffer.from(data))),
|
||||
);
|
||||
|
||||
@@ -69,13 +69,13 @@ while (true) {
|
||||
);
|
||||
const newStrings = parseYaml(await localizationsResponse.text());
|
||||
const oldStrings = await readYAMLDVPL<Record<string, string>>(
|
||||
`${DATA}/Strings/en.yaml.dvpl`,
|
||||
`${DATA}/Strings/en.yaml`,
|
||||
);
|
||||
const patchedStrings = { ...oldStrings, ...newStrings };
|
||||
const patchedContent = stringifyYaml(patchedStrings);
|
||||
|
||||
await writeFile(
|
||||
`${DATA}/Strings/en.yaml.dvpl`,
|
||||
`${DATA}/Strings/en.yaml`,
|
||||
new Uint8Array(writeDVPL(Buffer.from(patchedContent))),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,16 +8,16 @@ import { DATA } from './constants';
|
||||
|
||||
export async function boosterIcons() {
|
||||
const boosterFiles = (await readdir(`${DATA}/Gfx/Shared/boosters`)).filter(
|
||||
(file) => !file.endsWith('@2x.txt.dvpl') && !file.startsWith('texture0'),
|
||||
(file) => !file.includes('@2x.txt') && !file.startsWith('texture0'),
|
||||
);
|
||||
const image = sharp(
|
||||
await readDVPLFile(`${DATA}/Gfx/Shared/boosters/texture0.packed.webp.dvpl`),
|
||||
await readDVPLFile(`${DATA}/Gfx/Shared/boosters/texture0.packed.webp`),
|
||||
);
|
||||
const changes: FileChange[] = [];
|
||||
|
||||
await Promise.all(
|
||||
boosterFiles.map(async (file) => {
|
||||
const name = file.match(/booster_(.+).txt.dvpl/)?.[1];
|
||||
const name = file.match(/booster_(.+).txt/)?.[1];
|
||||
|
||||
if (name === undefined) return;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { DATA } from './constants';
|
||||
export async function camouflageIcons() {
|
||||
console.log('Building camouflage icons...');
|
||||
const content = await readDVPLFile(
|
||||
`${DATA}/Gfx/UI/Hangar/IconCamouflage.packed.webp.dvpl`,
|
||||
`${DATA}/Gfx/UI/Hangar/IconCamouflage.packed.webp`,
|
||||
);
|
||||
const changes: FileChange[] = [
|
||||
{
|
||||
|
||||
@@ -1,11 +1,33 @@
|
||||
import { readdir } from 'fs/promises';
|
||||
import { argv } from 'process';
|
||||
|
||||
const WINDOWS_APPS = 'C:/Program Files/WindowsApps';
|
||||
const wotbPackageRegex = /7458BE2C\..+_\d+(\.\d+)+_x64__.+/;
|
||||
|
||||
const isDepot = argv.includes('--depot');
|
||||
|
||||
export const DATA = isDepot
|
||||
? await (async () => {
|
||||
const [installationVersion] = await readdir(`../../depots/444202`);
|
||||
return `../../depots/444202/${installationVersion}/Data`;
|
||||
})()
|
||||
: 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
||||
let data: string;
|
||||
let compressed: boolean;
|
||||
|
||||
if (isDepot) {
|
||||
const [installationVersion] = await readdir(`../../depots/444202`);
|
||||
data = `../../depots/444202/${installationVersion}/Data`;
|
||||
compressed = true;
|
||||
} else {
|
||||
const directories = await readdir(WINDOWS_APPS).then((files) =>
|
||||
files.filter((file) => wotbPackageRegex.test(file)),
|
||||
);
|
||||
|
||||
if (directories.length !== 1) {
|
||||
throw new Error(
|
||||
`Expected 1 directory for WoTB Windows App, got ${directories.length}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const [windowsApp] = directories;
|
||||
data = `${WINDOWS_APPS}/${windowsApp}/Data`;
|
||||
compressed = false;
|
||||
}
|
||||
|
||||
export const DATA = data;
|
||||
export const DATA_COMPRESSED = compressed;
|
||||
@@ -34,21 +34,19 @@ export async function consumableProvisionIcons() {
|
||||
const styleSheets = await Promise.all(
|
||||
styles.map(async (path) =>
|
||||
Object.values(
|
||||
(await readYAMLDVPL<Mappings>(`${DATA}/${path}.dvpl`)).StyleSheets,
|
||||
(await readYAMLDVPL<Mappings>(`${DATA}/${path}`)).StyleSheets,
|
||||
),
|
||||
),
|
||||
).then((array) => array.flat());
|
||||
|
||||
for (const match of (
|
||||
await readStringDVPL(
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml`,
|
||||
)
|
||||
).matchAll(listItemsPattern)) {
|
||||
const consumablesCommon = await readXMLDVPL<{
|
||||
root: ConsumablesCommon;
|
||||
}>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml.dvpl`,
|
||||
);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`);
|
||||
|
||||
await Promise.all(
|
||||
Object.values(consumablesCommon.root).map(async (consumable) => {
|
||||
@@ -70,9 +68,9 @@ export async function consumableProvisionIcons() {
|
||||
.replace('.psd', '')
|
||||
.replace('.txt', '');
|
||||
|
||||
if (existsSync(`${DATA}/${configPath}.packed.webp.dvpl`)) {
|
||||
if (existsSync(`${DATA}/${configPath}.packed.webp`)) {
|
||||
const image = sharp(
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`),
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp`),
|
||||
);
|
||||
const content = await image.trim({ threshold: 100 }).toBuffer();
|
||||
|
||||
@@ -83,10 +81,10 @@ export async function consumableProvisionIcons() {
|
||||
} else {
|
||||
const consumablesTexture = sharp(
|
||||
await readDVPLFile(
|
||||
`${`${DATA}/${configPath}`.split('/').slice(0, -1).join('/')}/texture0.packed.webp.dvpl`,
|
||||
`${`${DATA}/${configPath}`.split('/').slice(0, -1).join('/')}/texture0.packed.webp`,
|
||||
),
|
||||
);
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`))
|
||||
.split('\n')[4]
|
||||
.split(' ')
|
||||
.map(Number);
|
||||
@@ -111,12 +109,12 @@ export async function consumableProvisionIcons() {
|
||||
|
||||
for (const match of (
|
||||
await readStringDVPL(
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml`,
|
||||
)
|
||||
).matchAll(listItemsPattern)) {
|
||||
const provisionsCommon = await readXMLDVPL<{
|
||||
root: ProvisionsCommon;
|
||||
}>(`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml.dvpl`);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`);
|
||||
await Promise.all(
|
||||
Object.values(provisionsCommon.root).map(async (provision) => {
|
||||
const styleSheet = styleSheets.find((styleSheet) =>
|
||||
@@ -137,9 +135,9 @@ export async function consumableProvisionIcons() {
|
||||
.replace('.psd', '')
|
||||
.replace('.txt', '');
|
||||
|
||||
if (existsSync(`${DATA}/${configPath}.packed.webp.dvpl`)) {
|
||||
if (existsSync(`${DATA}/${configPath}.packed.webp`)) {
|
||||
const image = sharp(
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`),
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp`),
|
||||
);
|
||||
const content = await image.trim({ threshold: 100 }).toBuffer();
|
||||
|
||||
@@ -150,10 +148,10 @@ export async function consumableProvisionIcons() {
|
||||
} else {
|
||||
const provisionsTexture = sharp(
|
||||
await readDVPLFile(
|
||||
`${`${DATA}/${configPath}`.split('/').slice(0, -1).join('/')}/texture0.packed.webp.dvpl`,
|
||||
`${`${DATA}/${configPath}`.split('/').slice(0, -1).join('/')}/texture0.packed.webp`,
|
||||
),
|
||||
);
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`))
|
||||
.split('\n')[4]
|
||||
.split(' ')
|
||||
.map(Number);
|
||||
|
||||
@@ -23,7 +23,7 @@ export async function currencies() {
|
||||
await Promise.all(
|
||||
ICONS.map(async ([file, name]) => {
|
||||
const content = await sharp(
|
||||
await readDVPLFile(`${DATA}/Gfx/Lobby/currency/${file}.dvpl`),
|
||||
await readDVPLFile(`${DATA}/Gfx/Lobby/currency/${file}`),
|
||||
)
|
||||
.trim()
|
||||
.toBuffer();
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
ConsumableTankCategoryFilterCategory,
|
||||
Crew,
|
||||
CrewType,
|
||||
DEFAULT_LOCALE,
|
||||
encodePBBuffer,
|
||||
EquipmentDefinitions,
|
||||
EquipmentSlot,
|
||||
@@ -23,8 +22,6 @@ import {
|
||||
ResearchCost,
|
||||
ShellType,
|
||||
SkillDefinitions,
|
||||
SUPPORTED_LOCALE_BLITZ_MAP,
|
||||
SUPPORTED_LOCALES,
|
||||
TankClass,
|
||||
TankDefinitions,
|
||||
TankPrice,
|
||||
@@ -34,6 +31,11 @@ import {
|
||||
Unlock,
|
||||
Vector3,
|
||||
} from '@blitzkit/core';
|
||||
import {
|
||||
DEFAULT_LOCALE,
|
||||
SUPPORTED_LOCALE_BLITZ_MAP,
|
||||
SUPPORTED_LOCALES,
|
||||
} from '@blitzkit/i18n';
|
||||
import { readdir } from 'fs/promises';
|
||||
import { parse as parsePath } from 'path';
|
||||
import { Vector3Tuple } from 'three';
|
||||
@@ -513,11 +515,9 @@ export async function definitions() {
|
||||
console.log('Building definitions...');
|
||||
|
||||
const gameDefinitions: GameDefinitions = {
|
||||
version: (await readStringDVPL(`${DATA}/version.txt.dvpl`)).split(' ')[0],
|
||||
version: (await readStringDVPL(`${DATA}/version.txt`)).split(' ')[0],
|
||||
nations: (
|
||||
await readYAMLDVPL<AvailableNationsYaml>(
|
||||
`${DATA}/available_nations.yaml.dvpl`,
|
||||
)
|
||||
await readYAMLDVPL<AvailableNationsYaml>(`${DATA}/available_nations.yaml`)
|
||||
).available_nations,
|
||||
gameModes: {},
|
||||
roles: {},
|
||||
@@ -550,26 +550,30 @@ export async function definitions() {
|
||||
.then((response) => response.text())
|
||||
.then((string) => parseYaml(string) as BlitzStrings);
|
||||
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml`,
|
||||
);
|
||||
const stringsI18n: Record<string, Record<string, string>> = {};
|
||||
|
||||
for (const locale of SUPPORTED_LOCALES) {
|
||||
const blitzLocale = SUPPORTED_LOCALE_BLITZ_MAP[locale];
|
||||
const cache = await fetch(
|
||||
`https://stufficons.wgcdn.co/localizations/${blitzLocale}.yaml`,
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((string) => parseYaml(string) as BlitzStrings);
|
||||
const preInstalled = await readYAMLDVPL<BlitzStrings>(
|
||||
`${DATA}/Strings/${blitzLocale}.yaml.dvpl`,
|
||||
);
|
||||
await Promise.all(
|
||||
SUPPORTED_LOCALES.map(async (locale) => {
|
||||
const blitzLocale = SUPPORTED_LOCALE_BLITZ_MAP[locale];
|
||||
const cache = await fetch(
|
||||
`https://stufficons.wgcdn.co/localizations/${blitzLocale}.yaml`,
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((string) => parseYaml(string) as BlitzStrings);
|
||||
const preInstalled = await readYAMLDVPL<BlitzStrings>(
|
||||
`${DATA}/Strings/${blitzLocale}.yaml`,
|
||||
);
|
||||
|
||||
stringsI18n[locale] = {
|
||||
...cache,
|
||||
...preInstalled,
|
||||
};
|
||||
}
|
||||
stringsI18n[locale] = {
|
||||
...cache,
|
||||
...preInstalled,
|
||||
};
|
||||
|
||||
console.log(`Loaded strings for ${locale}`);
|
||||
}),
|
||||
);
|
||||
|
||||
function getString(name: string) {
|
||||
const locales: Record<string, string> = {
|
||||
@@ -594,13 +598,13 @@ export async function definitions() {
|
||||
|
||||
const optionalDeviceSlots = await readXMLDVPL<{
|
||||
root: OptionalDeviceSlots;
|
||||
}>(`${DATA}/XML/item_defs/vehicles/common/optional_device_slots.xml.dvpl`);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/common/optional_device_slots.xml`);
|
||||
const consumables: ConsumablesCommon = {};
|
||||
const provisions: ProvisionsCommon = {};
|
||||
|
||||
for (const match of (
|
||||
await readStringDVPL(
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml`,
|
||||
)
|
||||
).matchAll(/<items path="(.+)\.xml"\/>/g)) {
|
||||
if (match[1] === 'prototypes') continue;
|
||||
@@ -609,7 +613,7 @@ export async function definitions() {
|
||||
consumables,
|
||||
(
|
||||
await readXMLDVPL<{ root: ConsumablesCommon }>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`,
|
||||
)
|
||||
).root,
|
||||
);
|
||||
@@ -617,7 +621,7 @@ export async function definitions() {
|
||||
|
||||
for (const match of (
|
||||
await readStringDVPL(
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml`,
|
||||
)
|
||||
).matchAll(/<items path="(.+)\.xml"\/>/g)) {
|
||||
if (match[1] === 'prototypes') continue;
|
||||
@@ -626,33 +630,33 @@ export async function definitions() {
|
||||
provisions,
|
||||
(
|
||||
await readXMLDVPL<{ root: ConsumablesCommon }>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`,
|
||||
)
|
||||
).root,
|
||||
);
|
||||
}
|
||||
|
||||
const avatar = await readXMLDVPL<{ root: Avatar }>(
|
||||
`${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/tankmen/avatar.xml`,
|
||||
);
|
||||
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml.dvpl`);
|
||||
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml`);
|
||||
const tankXps = new Map<number, ResearchCost>();
|
||||
const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml`,
|
||||
);
|
||||
const camouflagesYaml = await readYAMLDVPL<CamouflagesYaml>(
|
||||
`${DATA}/camouflages.yaml.dvpl`,
|
||||
`${DATA}/camouflages.yaml`,
|
||||
);
|
||||
const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages);
|
||||
const squadBattleTypeStyles = await readYAMLDVPL<SquadBattleTypeStyles>(
|
||||
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml.dvpl`,
|
||||
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
|
||||
);
|
||||
const gameTypeSelectorStyles = await readYAMLDVPL<SquadBattleTypeStyles>(
|
||||
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml.dvpl`,
|
||||
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`,
|
||||
);
|
||||
const gameModeNativeNames: Record<string, number> = {};
|
||||
const combatRoles = await readYAMLDVPL<CombatRolesYaml>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/combat_roles.yaml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/combat_roles.yaml`,
|
||||
);
|
||||
const consumableNativeNames: Record<string, number> = {};
|
||||
const provisionNativeNames: Record<string, number> = {};
|
||||
@@ -702,29 +706,23 @@ export async function definitions() {
|
||||
await Promise.all(
|
||||
nations.map(async (nation) => {
|
||||
const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||
);
|
||||
const turretList = await readXMLDVPL<{
|
||||
root: TurretDefinitionsList;
|
||||
}>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/components/turrets.xml.dvpl`,
|
||||
);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/turrets.xml`);
|
||||
const gunList = await readXMLDVPL<{
|
||||
root: GunDefinitionsList;
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/guns.xml.dvpl`);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/guns.xml`);
|
||||
const shellList = await readXMLDVPL<{
|
||||
root: ShellDefinitionsList;
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/shells.xml.dvpl`);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/shells.xml`);
|
||||
const enginesList = await readXMLDVPL<{
|
||||
root: EngineDefinitionsList;
|
||||
}>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/components/engines.xml.dvpl`,
|
||||
);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/engines.xml`);
|
||||
const chassisList = await readXMLDVPL<{
|
||||
root: ChassisDefinitionsList;
|
||||
}>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/components/chassis.xml.dvpl`,
|
||||
);
|
||||
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/chassis.xml`);
|
||||
|
||||
function resolveUnlocks(unlocks?: BlitzModuleType) {
|
||||
if (!unlocks) return [];
|
||||
@@ -776,10 +774,10 @@ export async function definitions() {
|
||||
const tank = tankList.root[tankKey];
|
||||
let tankPrice: TankPrice;
|
||||
const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/${tankKey}.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/${tankKey}.xml`,
|
||||
);
|
||||
const tankParameters = await readYAMLDVPL<TankParameters>(
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml.dvpl`,
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
|
||||
);
|
||||
const turretOrigin = tankDefinition.root.hull.turretPositions.turret
|
||||
.split(' ')
|
||||
@@ -1667,8 +1665,6 @@ export async function definitions() {
|
||||
};
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
await commitAssets('definitions', [
|
||||
{
|
||||
content: encodePBBuffer(GameDefinitions, gameDefinitions),
|
||||
|
||||
@@ -22,14 +22,14 @@ export async function equipmentIcons() {
|
||||
|
||||
const changes: FileChange[] = [];
|
||||
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>(
|
||||
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml`,
|
||||
);
|
||||
const mappings = await readYAMLDVPL<Mappings>(
|
||||
`${DATA}/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml.dvpl`,
|
||||
`${DATA}/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml`,
|
||||
);
|
||||
const image = sharp(
|
||||
await readDVPLFile(
|
||||
`${DATA}/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp.dvpl`,
|
||||
`${DATA}/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp`,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -57,7 +57,7 @@ export async function equipmentIcons() {
|
||||
if (configPath.startsWith('Gfx/Lobby')) {
|
||||
const configPathWebp = configPath.replace('.txt', '');
|
||||
const image = sharp(
|
||||
await readDVPLFile(`${DATA}/${configPathWebp}.packed.webp.dvpl`),
|
||||
await readDVPLFile(`${DATA}/${configPathWebp}.packed.webp`),
|
||||
);
|
||||
const content = await image.trim().toBuffer();
|
||||
|
||||
@@ -66,7 +66,7 @@ export async function equipmentIcons() {
|
||||
content,
|
||||
});
|
||||
} else {
|
||||
const config = await readStringDVPL(`${DATA}/${configPath}.dvpl`);
|
||||
const config = await readStringDVPL(`${DATA}/${configPath}`);
|
||||
const sizes = config.split('\n')[4].split(' ').map(Number);
|
||||
const content = await image
|
||||
.clone()
|
||||
|
||||
@@ -14,7 +14,7 @@ export async function flags() {
|
||||
.filter(
|
||||
(flag) =>
|
||||
flag.startsWith('flag_profile-stat_') &&
|
||||
!flag.endsWith('@2x.packed.webp.dvpl'),
|
||||
!flag.endsWith('@2x.packed.webp'),
|
||||
)
|
||||
.map(async (flag) => {
|
||||
const image = sharp(
|
||||
@@ -34,7 +34,7 @@ export async function flags() {
|
||||
.filter(
|
||||
(flag) =>
|
||||
flag.startsWith('flag_tutor-tank_') &&
|
||||
!flag.endsWith('@2x.packed.webp.dvpl'),
|
||||
!flag.endsWith('@2x.packed.webp'),
|
||||
)
|
||||
.map(async (flag) => {
|
||||
const content = await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`);
|
||||
@@ -50,8 +50,7 @@ export async function flags() {
|
||||
(await readdir(`${DATA}/Gfx/Lobby/flags`))
|
||||
.filter(
|
||||
(flag) =>
|
||||
flag.startsWith('flag_filter_') &&
|
||||
flag.endsWith('@2x.packed.webp.dvpl'),
|
||||
flag.startsWith('flag_filter_') && flag.endsWith('@2x.packed.webp'),
|
||||
)
|
||||
.map(async (flag) => {
|
||||
const content = await sharp(
|
||||
|
||||
@@ -11,10 +11,10 @@ export async function gameModeBanners() {
|
||||
|
||||
const changes: FileChange[] = [];
|
||||
const gameTypeSelectorStyles = await readYAMLDVPL<SquadBattleTypeStyles>(
|
||||
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml.dvpl`,
|
||||
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`,
|
||||
);
|
||||
const squadBattleTypeStyles = await readYAMLDVPL<SquadBattleTypeStyles>(
|
||||
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml.dvpl`,
|
||||
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
|
||||
);
|
||||
const bannerMatches: { name: string; path: string }[] = [];
|
||||
|
||||
@@ -38,7 +38,7 @@ export async function gameModeBanners() {
|
||||
}
|
||||
|
||||
const content = await sharp(
|
||||
await readDVPLFile(`${DATA}${path}.packed.webp.dvpl`),
|
||||
await readDVPLFile(`${DATA}${path}.packed.webp`),
|
||||
)
|
||||
.trim({ background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
||||
.toBuffer();
|
||||
|
||||
@@ -12,10 +12,10 @@ export async function moduleIcons() {
|
||||
(await readdir(`${DATA}/Gfx/UI/ModulesTechTree`))
|
||||
.filter(
|
||||
(file) =>
|
||||
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
|
||||
!file.endsWith('@2x.packed.webp') && file.startsWith('vehicle'),
|
||||
)
|
||||
.map(async (file) => {
|
||||
const nameRaw = file.match(/vehicle(.+)\.packed\.webp\.dvpl/)![1];
|
||||
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}`),
|
||||
|
||||
@@ -11,15 +11,15 @@ export async function shellIcons() {
|
||||
|
||||
const image = sharp(
|
||||
await readDVPLFile(
|
||||
`${DATA}/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp.dvpl`,
|
||||
`${DATA}/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp`,
|
||||
),
|
||||
);
|
||||
|
||||
const changes = await Promise.all(
|
||||
(await readdir(`${DATA}/Gfx/Shared/tank-supply/ammunition/big`))
|
||||
.filter((file) => file.endsWith('_l.txt.dvpl'))
|
||||
.filter((file) => file.endsWith('_l.txt'))
|
||||
.map(async (file) => {
|
||||
const name = file.match(/(.+)_l\.txt\.dvpl/)![1];
|
||||
const name = file.match(/(.+)_l\.txt/)![1];
|
||||
const sizes = (
|
||||
await readStringDVPL(
|
||||
`${DATA}/Gfx/Shared/tank-supply/ammunition/big/${file}`,
|
||||
|
||||
@@ -29,13 +29,13 @@ export async function skillIcons() {
|
||||
console.log('Building skill icons...');
|
||||
|
||||
const avatar = await readXMLDVPL<{ root: Avatar }>(
|
||||
`${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/tankmen/avatar.xml`,
|
||||
);
|
||||
const changes = await Promise.all(
|
||||
Object.values(avatar.root.skills).map(async (skill) => {
|
||||
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.dvpl`;
|
||||
const path = `${DATA}${icon.name.replace('~res:', '')}.packed.webp`;
|
||||
const image = sharp(await readDVPLFile(path)).trim();
|
||||
const content = await image.toBuffer();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function tankArmors() {
|
||||
await Promise.all(
|
||||
nations.map(async (nation) => {
|
||||
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function tankIcons() {
|
||||
await Promise.all(
|
||||
nations.map(async (nation) => {
|
||||
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
@@ -63,14 +63,14 @@ export async function tankIcons() {
|
||||
const nationVehicleId = tank.id;
|
||||
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
|
||||
const parameters = await readYAMLDVPL<TankParameters>(
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml.dvpl`,
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
|
||||
);
|
||||
const smallPath = `${DATA}/${parameters.resourcesPath.smallIconPath
|
||||
.replace(/~res:\//, '')
|
||||
.replace(/\..+/, '')}.packed.webp.dvpl`;
|
||||
.replace(/\..+/, '')}.packed.webp`;
|
||||
const bigPath = `${DATA}/${parameters.resourcesPath.bigIconPath
|
||||
.replace(/~res:\//, '')
|
||||
.replace(/\..+/, '')}.packed.webp.dvpl`;
|
||||
.replace(/\..+/, '')}.packed.webp`;
|
||||
const big = await sharp(await readDVPLFile(bigPath))
|
||||
.trim()
|
||||
.toBuffer();
|
||||
|
||||
@@ -23,7 +23,7 @@ export async function tankModels() {
|
||||
const nation = nations[nationIndex];
|
||||
const changes: FileChange[] = [];
|
||||
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml.dvpl`,
|
||||
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||
);
|
||||
|
||||
console.log(`Building models for ${nation}`);
|
||||
@@ -35,7 +35,7 @@ export async function tankModels() {
|
||||
const id = toUniqueId(nation, tank.id);
|
||||
|
||||
const parameters = await readYAMLDVPL<TankParameters>(
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml.dvpl`,
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
|
||||
);
|
||||
const model = await extractModel(
|
||||
DATA,
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
import { readDVPLFile } from './readDVPLFile';
|
||||
|
||||
export async function extractArmor(data: string, fileName: string) {
|
||||
const sc2Path = `${data}/3d/Tanks/CollisionMeshes/${fileName}.sc2.dvpl`;
|
||||
const scgPath = `${data}/3d/Tanks/CollisionMeshes/${fileName}.scg.dvpl`;
|
||||
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,
|
||||
).sc2();
|
||||
|
||||
@@ -26,8 +26,8 @@ const omitMeshNames = {
|
||||
};
|
||||
|
||||
export async function extractModel(data: string, path: string) {
|
||||
const sc2Path = `${data}/3d/${path}.sc2.dvpl`;
|
||||
const scgPath = `${data}/3d/${path}.scg.dvpl`;
|
||||
const sc2Path = `${data}/3d/${path}.sc2`;
|
||||
const scgPath = `${data}/3d/${path}.scg`;
|
||||
const sc2 = new Sc2ReadStream(
|
||||
(await readDVPLFile(sc2Path)).buffer as ArrayBuffer,
|
||||
).sc2();
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { readFile } from 'fs/promises';
|
||||
import { DATA_COMPRESSED } from '../../buildAssets/constants';
|
||||
import { readDVPL } from './readDVPL';
|
||||
|
||||
export async function readDVPLFile(file: string) {
|
||||
return readDVPL(await readFile(file));
|
||||
if (DATA_COMPRESSED) {
|
||||
return readDVPL(await readFile(`${file}.dvpl`));
|
||||
}
|
||||
|
||||
return readFile(file);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { readDVPLFile } from '../readDVPLFile';
|
||||
import { TextureMutation } from './constants';
|
||||
|
||||
export async function readTexture(path: string, mutation?: TextureMutation) {
|
||||
const ddsTexturePath = path.replace('.tex', '.dx11.dds.dvpl');
|
||||
const ddsTexturePath = path.replace('.tex', '.dx11.dds');
|
||||
const isDds = existsSync(ddsTexturePath);
|
||||
const resolvedTexturePath = isDds
|
||||
? ddsTexturePath
|
||||
|
||||
Reference in new issue
Block a user