diff --git a/packages/core/src/blitzkit/api/server.ts b/packages/core/src/blitzkit/api/server.ts index b155390e7..377d7e8ba 100644 --- a/packages/core/src/blitzkit/api/server.ts +++ b/packages/core/src/blitzkit/api/server.ts @@ -2,18 +2,24 @@ import { AbstractVFS, BlitzStrings, CamouflageDefinitions, + CamouflagesXml, + CamouflagesYaml, + CombatRolesYaml, ConsumableDefinitions, ConsumablesCommon, EquipmentDefinitions, I18nString, MapDefinitions, + MapsYaml, ModelDefinitions, OptionalDevices, OptionalDeviceSlots, ProvisionDefinitions, ProvisionsCommon, SkillDefinitions, + SquadBattleTypeStylesYaml, TankDefinitions, + TankmenAvatar, } from "@blitzkit/core"; import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n"; import locales from "@blitzkit/i18n/locales.json"; @@ -29,8 +35,16 @@ export class ServerBlitzKitAPI extends BlitzKitAPI { consumablesCommon: ConsumablesCommon = {}; provisionsCommon: ProvisionsCommon = {}; + // TODO: suffix with "yaml"s and "xml"s private optionalDevices?: { root: OptionalDevices }; private optionalDeviceSlots?: { root: OptionalDeviceSlots }; + private tankmenAvatar?: { root: TankmenAvatar }; + private mapsYaml?: MapsYaml; + private camouflagesXml?: { root: CamouflagesXml }; + private camouflagesYaml?: CamouflagesYaml; + private squadBattleTypeStyles?: SquadBattleTypeStylesYaml; + private gameTypeSelectorStyles?: SquadBattleTypeStylesYaml; + private combatRoles?: CombatRolesYaml; constructor(vfs: AbstractVFS) { super(); @@ -38,6 +52,37 @@ export class ServerBlitzKitAPI extends BlitzKitAPI { } async init() { + 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"); + this.tankmenAvatar = await this.vfs.xml<{ root: TankmenAvatar }>( + "Data/XML/item_defs/tankmen/avatar.xml", + ); + this.mapsYaml = await this.vfs.yaml("Data/maps.yaml"); + this.camouflagesXml = await this.vfs.xml<{ root: CamouflagesXml }>( + "Data/XML/item_defs/vehicles/common/camouflages.xml", + ); + this.camouflagesYaml = await this.vfs.yaml( + "Data/camouflages.yaml", + ); + this.squadBattleTypeStyles = await this.vfs.yaml( + `Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`, + ); + this.gameTypeSelectorStyles = + await this.vfs.yaml( + `Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`, + ); + this.combatRoles = await this.vfs.yaml( + `Data/XML/item_defs/vehicles/common/combat_roles.yaml`, + ); + await Promise.all( locales.supported.map(async ({ locale }) => { const blitzLocale = SUPPORTED_LOCALE_BLITZ_MAP[locale]; @@ -57,16 +102,39 @@ export class ServerBlitzKitAPI extends BlitzKitAPI { }), ); - this.nationsDir = await this.vfs - .dir("Data/XML/item_defs/vehicles") - .then((files) => files.filter((nation) => nation !== "common")); + for (const match of ( + await this.vfs.text( + `Data/XML/item_defs/vehicles/common/consumables/list.xml`, + ) + ).matchAll(//g)) { + if (match[1] === "prototypes") continue; - 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`); + Object.assign( + this.consumablesCommon, + ( + await this.vfs.xml<{ root: ConsumablesCommon }>( + `Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`, + ) + ).root, + ); + } + + for (const match of ( + await this.vfs.text( + `Data/XML/item_defs/vehicles/common/provisions/list.xml`, + ) + ).matchAll(//g)) { + if (match[1] === "prototypes") continue; + + Object.assign( + this.provisionsCommon, + ( + await this.vfs.xml<{ root: ConsumablesCommon }>( + `Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`, + ) + ).root, + ); + } } private getString(name: string) { @@ -92,33 +160,49 @@ export class ServerBlitzKitAPI extends BlitzKitAPI { async tankDefinitions() { const tankDefinitions = TankDefinitions.create(); + + return tankDefinitions; } async camouflageDefinitions() { const camouflageDefinitions = CamouflageDefinitions.create(); + + return camouflageDefinitions; } async modelDefinitions() { const modelDefinitions = ModelDefinitions.create(); + + return modelDefinitions; } async mapDefinitions() { const mapDefinitions = MapDefinitions.create(); + + return mapDefinitions; } async equipmentDefinitions() { const equipmentDefinitions = EquipmentDefinitions.create(); + + return equipmentDefinitions; } async consumableDefinitions() { const consumableDefinitions = ConsumableDefinitions.create(); + + return consumableDefinitions; } async provisionDefinitions() { const provisionDefinitions = ProvisionDefinitions.create(); + + return provisionDefinitions; } async skillDefinitions() { const skillDefinitions = SkillDefinitions.create(); + + return skillDefinitions; } } diff --git a/packages/core/src/types/camouflagesXml.ts b/packages/core/src/types/camouflagesXml.ts new file mode 100644 index 000000000..9002904cf --- /dev/null +++ b/packages/core/src/types/camouflagesXml.ts @@ -0,0 +1,33 @@ +export interface CamouflagesXml { + camouflages: Record< + string, + { + id: number; + userString: string; + description: string; + category: string; + group: string; + kind: string; + notInShop: boolean; + unlockCostCategory?: string; + vehicleFilter: { + include?: CamouflagesInclude | CamouflagesInclude[]; + }; + script: string[] | string; + icon?: string; + unlockPremium?: string; + unlockQuest?: string; + unlockClanLevel?: number; + unlockShopBundle?: string; + unlockTankRank?: number; + } + >; +} + +type CamouflagesInclude = + | { + nations?: string; + } + | { + vehicle?: { name?: string; minLevel?: number; maxLevel?: number }; + }; diff --git a/packages/core/src/types/camouflagesYaml.ts b/packages/core/src/types/camouflagesYaml.ts new file mode 100644 index 000000000..7671432fe --- /dev/null +++ b/packages/core/src/types/camouflagesYaml.ts @@ -0,0 +1,7 @@ +export type CamouflagesYaml = Record< + string, + { + userString?: string; + shortUserString?: string; + } +>; diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index a0f1104fc..72dfb7218 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -1,11 +1,15 @@ export * from "./availableNationsYaml"; export * from "./blitzStrings"; +export * from "./camouflagesXml"; +export * from "./camouflagesYaml"; export * from "./combatRolesYaml"; export * from "./consumablesCommon"; export * from "./consumablesVehicleFilter"; export * from "./glossary"; +export * from "./mapsYaml"; export * from "./optionalDevices"; export * from "./optionalDeviceSlots"; export * from "./provisionsCommon"; export * from "./squadBattleTypeStylesYaml"; +export * from "./tankmenAvatar"; export * from "./tanksStats"; diff --git a/packages/core/src/types/mapsYaml.ts b/packages/core/src/types/mapsYaml.ts new file mode 100644 index 000000000..68aadc9b3 --- /dev/null +++ b/packages/core/src/types/mapsYaml.ts @@ -0,0 +1,24 @@ +export interface MapsYaml { + maps: { + [key: string]: { + id: number; + tags?: string; + localName: string; + avaliableInTrainingRoom: boolean; // lol wg typo + spriteFrame: number; + supremacyPointsThreshold?: number; + availableModes: number[]; + shadowMapsAvailable?: boolean; + assaultRespawnPoints: { + allies: MapAlly[]; + enemies: MapAlly[]; + }; + levels?: number[]; + }; + }; +} + +export interface MapAlly { + respawnNumber: number; + points: Array; +} diff --git a/packages/core/src/types/tankmenAvatar.ts b/packages/core/src/types/tankmenAvatar.ts new file mode 100644 index 000000000..b57550cbc --- /dev/null +++ b/packages/core/src/types/tankmenAvatar.ts @@ -0,0 +1,20 @@ +import { TankClass } from "@blitzkit/core"; + +export interface TankmenAvatar { + roles: unknown; + skillsByClasses: Record; + skills: { + [name: string]: { + userString: string; + effectDescription: string; + tipDescription: string; + icon: SkillIcon | SkillIcon[]; + type: "continuous" | "trigger"; + }; + }; +} + +interface SkillIcon { + name: string; + state: number; +} diff --git a/packages/scripts/src/buildAssets/definitions.ts b/packages/scripts/src/buildAssets/definitions.ts index 8d7f4ac99..b4a79511d 100644 --- a/packages/scripts/src/buildAssets/definitions.ts +++ b/packages/scripts/src/buildAssets/definitions.ts @@ -21,7 +21,6 @@ import { ShellType, SkillDefinitions, sluggify, - SquadBattleTypeStylesYaml, TankClass, TankDefinitions, TankPrice, @@ -35,7 +34,6 @@ import { readFile } from "fs/promises"; import { parse as parsePath } from "path"; import type { Vector3Tuple } from "three"; import { vfs } from "./constants"; -import type { Avatar } from "./skillIcons"; import type { TankParameters } from "./tankIcons"; const nationSlugDiscriminators = { @@ -389,78 +387,11 @@ export interface ProvisionsCommon { }; } -type CamouflagesInclude = - | { - nations?: string; - } - | { - vehicle?: { name?: string; minLevel?: number; maxLevel?: number }; - }; - -interface CamouflagesXML { - camouflages: Record< - string, - { - id: number; - userString: string; - description: string; - category: string; - group: string; - kind: string; - notInShop: boolean; - unlockCostCategory?: string; - vehicleFilter: { - include?: CamouflagesInclude | CamouflagesInclude[]; - }; - script: string[] | string; - icon?: string; - unlockPremium?: string; - unlockQuest?: string; - unlockClanLevel?: number; - unlockShopBundle?: string; - unlockTankRank?: number; - } - >; -} - -type CamouflagesYaml = Record< - string, - { - userString?: string; - shortUserString?: string; - } ->; - type ConsumablesVehicleFilter = | { minLevel: number; maxLevel: number } | { name: string } | { extendedTags: string }; -export interface Maps { - maps: { - [key: string]: { - id: number; - tags?: string; - localName: string; - avaliableInTrainingRoom: boolean; // lol wg typo - spriteFrame: number; - supremacyPointsThreshold?: number; - availableModes: number[]; - shadowMapsAvailable?: boolean; - assaultRespawnPoints: { - allies: MapAlly[]; - enemies: MapAlly[]; - }; - levels?: number[]; - }; - }; -} - -export interface MapAlly { - respawnNumber: number; - points: Array; -} - type CombatRolesYaml = Record< string, { @@ -502,59 +433,12 @@ function assignArmor( export async function definitions() { const tankStringIdMap: Record = {}; - - for (const match of ( - await vfs.text(`Data/XML/item_defs/vehicles/common/consumables/list.xml`) - ).matchAll(//g)) { - if (match[1] === "prototypes") continue; - - Object.assign( - consumablesCommon, - ( - await vfs.xml<{ root: ConsumablesCommon }>( - `Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`, - ) - ).root, - ); - } - - for (const match of ( - await vfs.text(`Data/XML/item_defs/vehicles/common/provisions/list.xml`) - ).matchAll(//g)) { - if (match[1] === "prototypes") continue; - - Object.assign( - provisionsCommon, - ( - await vfs.xml<{ root: ConsumablesCommon }>( - `Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`, - ) - ).root, - ); - } - - const avatar = await vfs.xml<{ root: Avatar }>( - `Data/XML/item_defs/tankmen/avatar.xml`, - ); - const maps = await vfs.yaml(`Data/maps.yaml`); const tankXps = new Map(); - const camouflagesXml = await vfs.xml<{ root: CamouflagesXML }>( - `Data/XML/item_defs/vehicles/common/camouflages.xml`, - ); - const camouflagesYaml = await vfs.yaml( - `Data/camouflages.yaml`, - ); + const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages); - const squadBattleTypeStyles = await vfs.yaml( - `Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`, - ); - const gameTypeSelectorStyles = await vfs.yaml( - `Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`, - ); + const gameModeNativeNames: Record = {}; - const combatRoles = await vfs.yaml( - `Data/XML/item_defs/vehicles/common/combat_roles.yaml`, - ); + const consumableNativeNames: Record = {}; const provisionNativeNames: Record = {}; let equalizerDefinitions: string[][]; @@ -1635,15 +1519,17 @@ export async function definitions() { } }); - Object.entries(avatar.root.skillsByClasses).forEach(([tankClass, skills]) => { - skillDefinitions.classes[ - blitzTankClassToBlitzkit[tankClass as BlitzTankClass] - ] = { - skills: skills.split(" "), - }; - }); + Object.entries(tankmenAvatar.root.skillsByClasses).forEach( + ([tankClass, skills]) => { + skillDefinitions.classes[ + blitzTankClassToBlitzkit[tankClass as BlitzTankClass] + ] = { + skills: skills.split(" "), + }; + }, + ); - Object.entries(maps.maps).forEach(([key, map]) => { + Object.entries(mapsYaml.maps).forEach(([key, map]) => { mapDefinitions.maps[map.id] = { id: map.id, name: getString(`#maps:${key}:${map.localName}`), diff --git a/packages/scripts/src/buildAssets/skillIcons.ts b/packages/scripts/src/buildAssets/skillIcons.ts index 4b3264ae1..02c27a2a3 100644 --- a/packages/scripts/src/buildAssets/skillIcons.ts +++ b/packages/scripts/src/buildAssets/skillIcons.ts @@ -1,31 +1,11 @@ -import { TankClass } from "@blitzkit/core"; import sharp from "sharp"; import { AssetUploader } from "../core/github/assetUploader"; import { vfs } from "./constants"; -interface SkillIcon { - name: string; - state: number; -} - -export interface Avatar { - roles: unknown; - skillsByClasses: Record; - skills: { - [name: string]: { - userString: string; - effectDescription: string; - tipDescription: string; - icon: SkillIcon | SkillIcon[]; - type: "continuous" | "trigger"; - }; - }; -} - export async function skillIcons() { console.log("Building skill icons..."); - const avatar = await vfs.xml<{ root: Avatar }>( + const avatar = await vfs.xml<{ root: TankmenAvatar }>( `Data/XML/item_defs/tankmen/avatar.xml`, ); const uploader = new AssetUploader("skill icons");