some definitions headers

This commit is contained in:
tresabhi committed 2026-08-01 12:56:12 -05:00
1 parent 39745dd475
commit 17c54be1c8
13 files changed
+208 -169

No files matched your search

+1 -3
View File
@@ -1,5 +1,3 @@
import { GameDefinitions } from "../../protos";
export abstract class BlitzKitAPI { export abstract class BlitzKitAPI {
abstract game(): Promise<GameDefinitions>; // abstract game(): Promise<GameDefinitions>;
} }
+101 -46
View File
@@ -1,69 +1,124 @@
import { import {
AbstractVFS, AbstractVFS,
AvailableNationsYaml, BlitzStrings,
SquadBattleTypeStylesYaml, CamouflageDefinitions,
ConsumableDefinitions,
ConsumablesCommon,
EquipmentDefinitions,
I18nString,
MapDefinitions,
ModelDefinitions,
OptionalDevices,
OptionalDeviceSlots,
ProvisionDefinitions,
ProvisionsCommon,
SkillDefinitions,
TankDefinitions,
} from "@blitzkit/core"; } from "@blitzkit/core";
import { GameDefinitions } from "../../protos"; import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n";
import locales from "@blitzkit/i18n/locales.json";
import { parse as parseYaml } from "yaml";
import { BlitzKitAPI } from "./base"; import { BlitzKitAPI } from "./base";
export class ServerBlitzKitAPI extends BlitzKitAPI { export class ServerBlitzKitAPI extends BlitzKitAPI {
vfs: AbstractVFS; private vfs: AbstractVFS;
private stringsI18n: Record<string, Record<string, string>> = {};
private nationsDir?: string[];
consumablesCommon: ConsumablesCommon = {};
provisionsCommon: ProvisionsCommon = {};
private optionalDevices?: { root: OptionalDevices };
private optionalDeviceSlots?: { root: OptionalDeviceSlots };
constructor(vfs: AbstractVFS) { constructor(vfs: AbstractVFS) {
super(); super();
this.vfs = vfs; this.vfs = vfs;
} }
async game() { async init() {
const versionFile = await this.vfs.text("Data/version.txt"); await Promise.all(
const version = versionFile.split(" ")[0]; locales.supported.map(async ({ locale }) => {
const blitzLocale = SUPPORTED_LOCALE_BLITZ_MAP[locale];
const availableNations = await this.vfs.yaml<AvailableNationsYaml>( const cache = await fetch(
"Data/available_nations.yaml", `https://stufficons.wgcdn.co/localizations/${blitzLocale}.yaml`,
)
.then((response) => response.text())
.then((string) => parseYaml(string) as BlitzStrings);
const preInstalled = await this.vfs.yaml<BlitzStrings>(
`Data/Strings/${blitzLocale}.yaml`,
); );
const nations = availableNations.available_nations;
const game: GameDefinitions = { this.stringsI18n[locale] = {
version, ...cache,
nations, ...preInstalled,
gameModes: {}, };
roles: {}, }),
);
this.nationsDir = await this.vfs
.dir("Data/XML/item_defs/vehicles")
.then((files) => files.filter((nation) => nation !== "common"));
this.optionalDevices = await this.vfs.xml<{ root: OptionalDevices }>(
"Data/XML/item_defs/vehicles/common/optional_devices.xml",
);
this.optionalDeviceSlots = await this.vfs.xml<{
root: OptionalDeviceSlots;
}>(`Data/XML/item_defs/vehicles/common/optional_device_slots.xml`);
}
private getString(name: string) {
const collection: Record<string, string> = {
[locales.default]: this.stringsI18n[locales.default][name],
}; };
const squadBattleTypeStyles = for (const { locale } of locales.supported) {
await this.vfs.yaml<SquadBattleTypeStylesYaml>( const localizedString = this.stringsI18n[locale][name];
`Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
);
for (const match of squadBattleTypeStyles.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll( if (
/"(\d+)" -> "(battleType\/([a-zA-Z]+))"/g, localizedString === undefined ||
)) { localizedString === collection[locales.default]
const id = Number(match[1]); ) {
const name = getString(match[2]); continue;
gameModeNativeNames[match[3]] = id;
game.gameModes[id] = {
name,
};
} }
Object.entries(combatRoles).forEach(([, value]) => { collection[locale] = localizedString;
gameDefinitions.roles[value.id] = { provisions: [], consumables: [] }; }
value.default_abilities.forEach((ability) => { return { locales: collection } satisfies I18nString;
if (ability in consumableNativeNames) { }
gameDefinitions.roles[value.id].consumables.push(
consumableNativeNames[ability],
);
} else if (ability in provisionNativeNames) {
gameDefinitions.roles[value.id].provisions.push(
provisionNativeNames[ability],
);
} else throw new Error(`Unknown ability ${ability}`);
});
});
return game; async tankDefinitions() {
const tankDefinitions = TankDefinitions.create();
}
async camouflageDefinitions() {
const camouflageDefinitions = CamouflageDefinitions.create();
}
async modelDefinitions() {
const modelDefinitions = ModelDefinitions.create();
}
async mapDefinitions() {
const mapDefinitions = MapDefinitions.create();
}
async equipmentDefinitions() {
const equipmentDefinitions = EquipmentDefinitions.create();
}
async consumableDefinitions() {
const consumableDefinitions = ConsumableDefinitions.create();
}
async provisionDefinitions() {
const provisionDefinitions = ProvisionDefinitions.create();
}
async skillDefinitions() {
const skillDefinitions = SkillDefinitions.create();
} }
} }
+3
View File
@@ -0,0 +1,3 @@
export interface BlitzStrings {
[key: string]: string;
}
@@ -0,0 +1,7 @@
export type CombatRolesYaml = Record<
string,
{
id: number;
default_abilities: string[];
}
>;
@@ -0,0 +1,24 @@
import { ConsumablesVehicleFilter } from "./consumablesVehicleFilter";
export interface ConsumablesCommon {
[key: string]: {
id: number;
userString: string;
description: string;
icon: string;
category: string;
tags: string;
vehicleFilter?: {
include: { vehicle: ConsumablesVehicleFilter; nations?: string };
exclude?: { vehicle: ConsumablesVehicleFilter; nations?: string };
};
script: {
"#text": string;
automatic?: boolean;
cooldown: number;
duration?: number;
shotEffect?: string;
bonusValues?: { [key: string]: number };
} & Record<string, string>;
};
}
@@ -0,0 +1,4 @@
export type ConsumablesVehicleFilter =
| { minLevel: number; maxLevel: number }
| { name: string }
| { extendedTags: string };
+7
View File
@@ -1,4 +1,11 @@
export * from "./availableNationsYaml"; export * from "./availableNationsYaml";
export * from "./blitzStrings";
export * from "./combatRolesYaml";
export * from "./consumablesCommon";
export * from "./consumablesVehicleFilter";
export * from "./glossary"; export * from "./glossary";
export * from "./optionalDevices";
export * from "./optionalDeviceSlots";
export * from "./provisionsCommon";
export * from "./squadBattleTypeStylesYaml"; export * from "./squadBattleTypeStylesYaml";
export * from "./tanksStats"; export * from "./tanksStats";
@@ -0,0 +1,13 @@
export interface OptionalDeviceSlots {
presets: {
[key: string]: {
level0: OptionalDeviceSlotRow;
level1: OptionalDeviceSlotRow;
level2: OptionalDeviceSlotRow;
};
};
}
interface OptionalDeviceSlotRow {
[key: string]: { device0: string; device1: string };
}
@@ -0,0 +1,10 @@
export interface OptionalDevices {
[key: string]: {
id: number;
userString: string;
description: string;
icon: string;
script: unknown;
display_params: unknown;
};
}
@@ -0,0 +1,22 @@
import { ConsumablesVehicleFilter } from "./consumablesVehicleFilter";
export interface ProvisionsCommon {
[key: string]: {
id: number;
userString: string;
description: string;
icon: string;
category: string;
tags: string;
vehicleFilter?: {
include: { vehicle: ConsumablesVehicleFilter; nations?: string };
exclude?: { vehicle: ConsumablesVehicleFilter; nations?: string };
};
script: {
"#text": string;
automatic?: boolean;
shotEffect?: string;
bonusValues?: { [key: string]: number };
} & Record<string, string>;
};
}
@@ -1,9 +1,11 @@
import { assertSecret } from "@blitzkit/core"; import {
import { AbstractVFS } from "../core/vfs/abstract"; AbstractVFS,
import { LocalVFS } from "../core/vfs/local"; assertSecret,
import { MixedVFS } from "../core/vfs/mixed"; LocalVFS,
import { SteamVFS } from "../core/vfs/steam"; MixedVFS,
import { ZipVFS } from "../core/vfs/zip"; SteamVFS,
ZipVFS,
} from "@blitzkit/core";
export const PATCHES_ROOT = "../../temp/patches"; export const PATCHES_ROOT = "../../temp/patches";
+7 -113
View File
@@ -12,7 +12,6 @@ import {
EquipmentDefinitions, EquipmentDefinitions,
EquipmentSlot, EquipmentSlot,
GunDefinition, GunDefinition,
I18nString,
MapDefinitions, MapDefinitions,
ModelDefinitions, ModelDefinitions,
ModuleType, ModuleType,
@@ -22,6 +21,7 @@ import {
ShellType, ShellType,
SkillDefinitions, SkillDefinitions,
sluggify, sluggify,
SquadBattleTypeStylesYaml,
TankClass, TankClass,
TankDefinitions, TankDefinitions,
TankPrice, TankPrice,
@@ -31,13 +31,9 @@ import {
Unlock, Unlock,
Vector3, Vector3,
} from "@blitzkit/core"; } from "@blitzkit/core";
import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n";
import locales from "@blitzkit/i18n/locales.json";
import { readFile } from "fs/promises"; import { readFile } from "fs/promises";
import { parse as parsePath } from "path"; import { parse as parsePath } from "path";
import type { Vector3Tuple } from "three"; import type { Vector3Tuple } from "three";
import { parse as parseYaml } from "yaml";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants"; import { vfs } from "./constants";
import type { Avatar } from "./skillIcons"; import type { Avatar } from "./skillIcons";
import type { TankParameters } from "./tankIcons"; import type { TankParameters } from "./tankIcons";
@@ -350,31 +346,6 @@ interface GunDefinitionsList {
}; };
}; };
} }
export interface OptionalDevices {
[key: string]: {
id: number;
userString: string;
description: string;
icon: string;
script: unknown;
display_params: unknown;
};
}
interface OptionalDeviceSlots {
presets: {
[key: string]: {
level0: OptionalDeviceSlotRow;
level1: OptionalDeviceSlotRow;
level2: OptionalDeviceSlotRow;
};
};
}
interface OptionalDeviceSlotRow {
[key: string]: { device0: string; device1: string };
}
export interface ConsumablesCommon { export interface ConsumablesCommon {
[key: string]: { [key: string]: {
id: number; id: number;
@@ -530,84 +501,7 @@ function assignArmor(
} }
export async function definitions() { export async function definitions() {
console.log("Building definitions...");
const uploader = new AssetUploader("definitions");
const tankDefinitions: TankDefinitions = { tanks: {} };
const camouflageDefinitions: CamouflageDefinitions = { camouflages: {} };
const modelDefinitions: ModelDefinitions = { models: {} };
const mapDefinitions: MapDefinitions = { maps: {} };
const equipmentDefinitions: EquipmentDefinitions = {
presets: {},
equipments: {},
};
const consumableDefinitions: ConsumableDefinitions = { consumables: {} };
const provisionDefinitions: ProvisionDefinitions = { provisions: {} };
const skillDefinitions: SkillDefinitions = {
classes: {
[TankClass.TANK_CLASS_LIGHT]: { skills: [] },
[TankClass.TANK_CLASS_MEDIUM]: { skills: [] },
[TankClass.TANK_CLASS_HEAVY]: { skills: [] },
[TankClass.TANK_CLASS_TANK_DESTROYER]: { skills: [] },
},
};
const nations = await vfs
.dir("Data/XML/item_defs/vehicles")
.then((files) => files.filter((nation) => nation !== "common"));
const tankStringIdMap: Record<string, number> = {}; const tankStringIdMap: Record<string, number> = {};
const optionalDevices = await vfs.xml<{ root: OptionalDevices }>(
"Data/XML/item_defs/vehicles/common/optional_devices.xml",
);
const stringsI18n: Record<string, Record<string, string>> = {};
await Promise.all(
locales.supported.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 vfs.yaml<BlitzStrings>(
`Data/Strings/${blitzLocale}.yaml`,
);
stringsI18n[locale] = {
...cache,
...preInstalled,
};
console.log(`Loaded strings for ${locale}`);
}),
);
function getString(name: string) {
const collection: Record<string, string> = {
[locales.default]: stringsI18n[locales.default][name],
};
for (const { locale } of locales.supported) {
const localizedString = stringsI18n[locale][name];
if (
localizedString === undefined ||
localizedString === collection[locales.default]
) {
continue;
}
collection[locale] = localizedString;
}
return { locales: collection } satisfies I18nString;
}
const optionalDeviceSlots = await vfs.xml<{
root: OptionalDeviceSlots;
}>(`Data/XML/item_defs/vehicles/common/optional_device_slots.xml`);
const consumables: ConsumablesCommon = {};
const provisions: ProvisionsCommon = {};
for (const match of ( for (const match of (
await vfs.text(`Data/XML/item_defs/vehicles/common/consumables/list.xml`) await vfs.text(`Data/XML/item_defs/vehicles/common/consumables/list.xml`)
@@ -615,7 +509,7 @@ export async function definitions() {
if (match[1] === "prototypes") continue; if (match[1] === "prototypes") continue;
Object.assign( Object.assign(
consumables, consumablesCommon,
( (
await vfs.xml<{ root: 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`,
@@ -630,7 +524,7 @@ export async function definitions() {
if (match[1] === "prototypes") continue; if (match[1] === "prototypes") continue;
Object.assign( Object.assign(
provisions, provisionsCommon,
( (
await vfs.xml<{ root: ConsumablesCommon }>( await vfs.xml<{ root: ConsumablesCommon }>(
`Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`, `Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`,
@@ -723,7 +617,7 @@ export async function definitions() {
const slugRequesters = new Map<string, { id: number; key: string }[]>(); const slugRequesters = new Map<string, { id: number; key: string }[]>();
const idToNation: Record<number, string> = {}; const idToNation: Record<number, string> = {};
for (const nation of nations) { for (const nation of nationsDir) {
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>( const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`Data/XML/item_defs/vehicles/${nation}/list.xml`, `Data/XML/item_defs/vehicles/${nation}/list.xml`,
); );
@@ -803,7 +697,7 @@ export async function definitions() {
} }
}); });
for (const nation of nations) { for (const nation of nationsDir) {
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>( const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`Data/XML/item_defs/vehicles/${nation}/list.xml`, `Data/XML/item_defs/vehicles/${nation}/list.xml`,
); );
@@ -1538,7 +1432,7 @@ export async function definitions() {
}, },
); );
Object.entries(consumables).forEach(([key, consumable]) => { Object.entries(consumablesCommon).forEach(([key, consumable]) => {
consumableNativeNames[key] = consumable.id; consumableNativeNames[key] = consumable.id;
const entry: Consumable = { const entry: Consumable = {
@@ -1638,7 +1532,7 @@ export async function definitions() {
} }
}); });
Object.entries(provisions).forEach(([key, provision]) => { Object.entries(provisionsCommon).forEach(([key, provision]) => {
provisionNativeNames[key] = provision.id; provisionNativeNames[key] = provision.id;
const entry: Provision = { const entry: Provision = {
+1 -1
View File
@@ -7,7 +7,7 @@ import {
let _api: BlitzKitAPI; let _api: BlitzKitAPI;
if (import.meta.env.SSR) { if (import.meta.env.SSR) {
_api = new ServerBlitzKitAPI(); _api = await new ServerBlitzKitAPI(vfs).init();
} else { } else {
_api = new ClientBlitzKitAPI(); _api = new ClientBlitzKitAPI();
} }