diff --git a/.gitignore b/.gitignore index 6a7316df2..aaf1ca689 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ depots public/sitemap* /firebase.json target +packages/core/src/protos/generated/* diff --git a/bun.lockb b/bun.lockb index bfd8bd34e..2afba3b64 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/core/src/blitzkit/averageDefinitions/index.ts b/packages/core/src/blitzkit/averageDefinitions/index.ts index f93b03626..7d3a190cd 100644 --- a/packages/core/src/blitzkit/averageDefinitions/index.ts +++ b/packages/core/src/blitzkit/averageDefinitions/index.ts @@ -1,41 +1,6 @@ -import { decodeProtobuf } from '../../protobuf/decodeProtobuf'; -import { BlitzkitStats } from '../../statistics'; +import { AverageDefinitions } from '../../protos'; import { asset } from '../asset'; -export interface AverageDefinitionsEntry { - mu: BlitzkitStats; - sigma: BlitzkitStats; - r: BlitzkitStats; - samples: Samples; -} - -export interface AverageDefinitionsEntrySubPartial { - mu: Partial; - sigma: Partial; - r: Partial; - samples: Samples; -} - -export interface AverageDefinitionsEntryWithId extends AverageDefinitionsEntry { - id: number; -} - -export interface AverageDefinitions { - averages: Record; - samples: Samples; - time: number; -} - -export interface Samples { - d_1: number; - d_7: number; - d_30: number; - d_60: number; - d_90: number; - d_120: number; - total: number; -} - export interface AverageDefinitionsManifest { version: 1; /** @@ -44,30 +9,18 @@ export interface AverageDefinitionsManifest { latest: number; } -export const averageDefinitions = fetch(asset('averages/manifest.json'), { - cache: 'no-store', -}) - .then((response) => response.json() as Promise) - .then((manifest) => fetch(asset(`averages/${manifest.latest}.pb`))) - .then((response) => response.arrayBuffer()) - .then((buffer) => - decodeProtobuf( - 'average_definitions', - 'blitzkit.AverageDefinitions', - new Uint8Array(buffer), - ), +export async function fetchAverageDefinitions() { + const manifestResponse = await fetch(asset('averages/manifest.json')); + const manifestJson = + (await manifestResponse.json()) as AverageDefinitionsManifest; + const averageDefinitionsResponse = await fetch( + asset(`averages/${manifestJson.latest}.pb`), ); + const averageDefinitionsBuffer = + await averageDefinitionsResponse.arrayBuffer(); + const averageDefinitionsArray = new Uint8Array(averageDefinitionsBuffer); -export const averageDefinitionsArray = averageDefinitions.then((data) => - Object.entries(data.averages) - .map( - ([key, value]) => - ({ - id: Number(key), - ...(value as AverageDefinitionsEntry), - }) satisfies AverageDefinitionsEntryWithId, - ) - .filter((tank) => tank.mu.battles > 0), -); + return AverageDefinitions.deserializeBinary(averageDefinitionsArray); +} export * from './constants'; diff --git a/packages/core/src/blitzkit/reviews.ts b/packages/core/src/blitzkit/reviews.ts index 21d4805d3..d203df4a7 100644 --- a/packages/core/src/blitzkit/reviews.ts +++ b/packages/core/src/blitzkit/reviews.ts @@ -1,26 +1,10 @@ -import { decodeProtobuf } from '../protobuf'; +import { Reviews } from '../protos'; import { asset } from './asset'; -export interface Reviews { - reviews: Record; -} +export async function fetchReviews() { + const response = await fetch(asset('definitions/reviews.pb')); + const buffer = await response.arrayBuffer(); + const array = new Uint8Array(buffer); -interface Review { - last_updated: number; - videos?: Video[]; + return Reviews.deserializeBinary(array); } - -export interface Video { - id: string; - author: string; -} - -export const reviews = fetch(asset('definitions/reviews.pb')) - .then((response) => response.arrayBuffer()) - .then((buffer) => - decodeProtobuf( - 'reviews', - 'blitzkit.Reviews', - new Uint8Array(buffer), - ), - ); diff --git a/packages/core/src/blitzkit/tankDefinitions/index.ts b/packages/core/src/blitzkit/tankDefinitions/index.ts index 970f129d0..3c9bfe303 100644 --- a/packages/core/src/blitzkit/tankDefinitions/index.ts +++ b/packages/core/src/blitzkit/tankDefinitions/index.ts @@ -1,224 +1,12 @@ -import { Vector2Tuple } from 'three'; +import { TankDefinitions } from '../../protos'; import { asset } from '../asset'; -import { fetchCdonLz4 } from '../fetchCdonLz4'; -export enum TankClass { - Unspecified, - Light, - Medium, - Heavy, - TankDestroyer, -} -export enum TankType { - Unspecified, - Researchable, - Premium, - Collector, -} +export async function fetchTankDefinitions() { + const response = await fetch(asset('definitions/tanks.pb')); + const buffer = await response.arrayBuffer(); + const array = new Uint8Array(buffer); -export enum ShellType { - Unspecified, - AP, - APCR, - HEAT, - HE, -} - -export enum CrewType { - Unspecified, - Commander, - Radioman, - Gunner, - Driver, - Loader, -} - -export type TankDefinitions = Record; -export enum ModuleType { - Unspecified, - Vehicle, - Engine, - Tracks, - Turret, - Gun, -} - -export interface Unlock { - type: ModuleType; - id: number; - cost: { - // string being the season coins - type: 'xp' | string; - value: number; - }; -} -export interface Crew { - type: CrewType; - count?: number; - substitute?: CrewType[]; -} -export type ModuleDefinition = - | TrackDefinition - | EngineDefinition - | TurretDefinition - | GunDefinition; -export interface TankDefinition { - id: number; - roles: Record; - description?: string; - fixed_camouflage: boolean; - camouflages: number[]; - ancestors: number[]; - successors: number[]; - crew: Crew[]; - health: number; - nation: string; - name: string; - nameFull?: string; - type: TankType; - max_consumables: number; - max_provisions: number; - tier: Tier; - class: TankClass; - testing: boolean; - deprecated: boolean; - turrets: TurretDefinition[]; - engines: EngineDefinition[]; - tracks: TrackDefinition[]; - price: TankPrice; - xp?: number; - speed_forwards: number; - speed_backwards: number; - camouflage_still: number; - camouflage_moving: number; - camouflage_onFire: number; - equipment_preset: string; - weight: number; -} -export interface TrackDefinition { - id: number; - tier: Tier; - name: string; - weight: number; - traverse_speed: number; - xp?: number; - dispersion_move: number; - dispersion_traverse: number; - resistance_hard: number; - resistance_medium: number; - resistance_soft: number; - unlocks?: Unlock[]; -} -export interface EngineDefinition { - id: number; - name: string; - xp?: number; - tier: Tier; - fire_chance: number; - power: number; - weight: number; - unlocks?: Unlock[]; -} -export type TankPrice = { - type: TankPriceType; - value: number; -}; -enum TankPriceType { - Unspecified, - Credits, - Gold, -} -export interface TurretDefinition { - health: number; - view_range: number; - traverse_speed: number; - xp?: number; - id: number; - name: string; - tier: Tier; - guns: GunDefinition[]; - weight: number; - unlocks?: Unlock[]; -} -export type GunDefinition = - | GunDefinitionRegular - | GunDefinitionAutoLoader - | GunDefinitionAutoReloader; -interface GunDefinitionBase { - rotation_speed: number; - xp?: number; - weight: number; - id: number; - name: string; - tier: Tier; - shells: ShellDefinition[]; - camouflage_loss: number; - aim_time: number; - dispersion_base: number; - dispersion_traverse: number; - dispersion_shot: number; - dispersion_damaged: number; - unlocks?: Unlock[]; -} -interface GunDefinitionRegular { - gun: GunDefinitionBase; - regular: GunDefinitionRegularProperties; -} -interface GunDefinitionRegularProperties { - reload: number; -} -interface GunDefinitionAutoLoader { - gun: GunDefinitionBase; - auto_loader: GunDefinitionAutoLoaderProperties; -} -interface GunDefinitionAutoLoaderProperties { - reload: number; - intra_clip: number; - count: number; -} -interface GunDefinitionAutoReloader { - gun: GunDefinitionBase; - auto_reloader: GunDefinitionAutoReloaderProperties; -} -interface GunDefinitionAutoReloaderProperties { - reload: number[]; - intraClip: number; - count: number; -} -export interface ShellDefinition { - id: number; - name: string; - velocity: number; - armor_damage: number; - module_damage: number; - caliber: number; - icon: string; - penetration: number | Vector2Tuple; - type: ShellType; - normalization?: number; - ricochet?: number; - explosion_radius?: number; -} - -export const tankDefinitions = fetchCdonLz4( - asset('definitions/tanks.cdon.lz4'), -); - -export const tankDefinitionsArray = tankDefinitions.then((tanks) => - Object.values(tanks), -); -export enum Tier { - Unspecified, - I, - II, - III, - IV, - V, - VI, - VII, - VIII, - IX, - X, + return TankDefinitions.deserializeBinary(array); } export * from './constants'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 628ad93da..77791f659 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,11 +1,11 @@ export * from './blitz'; export * from './blitzkit'; +export * from './protos'; // export * from './blitzstars'; // export * from './databases'; export * from './imgur'; export * from './math'; export * from './patreon'; -// export * from './protobuf'; export * from './statistics'; // export * from './streams'; // export * from './types'; diff --git a/packages/core/src/protobuf/decodeProtobuf.ts b/packages/core/src/protobuf/decodeProtobuf.ts deleted file mode 100644 index b811f48ca..000000000 --- a/packages/core/src/protobuf/decodeProtobuf.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { lookupProtobufType, ProtoSource } from './lookupProtobufType'; - -export function decodeProtobuf( - source: ProtoSource, - type: string, - data: Uint8Array, -) { - return lookupProtobufType(source, type).decode(data).toJSON() as Type; -} diff --git a/packages/core/src/protobuf/encodeProtobuf.ts b/packages/core/src/protobuf/encodeProtobuf.ts deleted file mode 100644 index 66893b3d7..000000000 --- a/packages/core/src/protobuf/encodeProtobuf.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { lookupProtobufType, ProtoSource } from './lookupProtobufType'; - -export function encodeProtobuf( - source: ProtoSource, - type: string, - data: Record, -) { - const message = lookupProtobufType(source, type); - const verification = message.verify(data); - - if (verification !== null) throw new Error(verification); - - return message.encode(message.create(data)).finish(); -} diff --git a/packages/core/src/protobuf/encodeProtobufToBase64.ts b/packages/core/src/protobuf/encodeProtobufToBase64.ts deleted file mode 100644 index 2402a3934..000000000 --- a/packages/core/src/protobuf/encodeProtobufToBase64.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { encodeProtobuf } from './encodeProtobuf'; -import { ProtoSource } from './lookupProtobufType'; - -export async function encodeProtobufToBase64( - source: ProtoSource, - type: string, - data: any, -) { - const array = encodeProtobuf(source, type, data); - return Buffer.from(array).toString('base64'); -} diff --git a/packages/core/src/protobuf/index.ts b/packages/core/src/protobuf/index.ts deleted file mode 100644 index 94ecff4d2..000000000 --- a/packages/core/src/protobuf/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './decodeProtobuf'; -export * from './encodeProtobuf'; -export * from './encodeProtobufToBase64'; -export * from './lookupProtobufType'; diff --git a/packages/core/src/protobuf/lookupProtobufType.ts b/packages/core/src/protobuf/lookupProtobufType.ts deleted file mode 100644 index 880f13713..000000000 --- a/packages/core/src/protobuf/lookupProtobufType.ts +++ /dev/null @@ -1,12 +0,0 @@ -import protobuf from 'protobufjs'; -import average_definitions from '../../protos/average_definitions.proto'; -import reviews from '../../protos/reviews.proto'; -import tank_definitions from '../../protos/tank_definitions.proto'; - -export type ProtoSource = keyof typeof protos; - -const protos = { reviews, average_definitions, tank_definitions }; - -export function lookupProtobufType(source: ProtoSource, type: string) { - return protobuf.parse(protos[source]).root.lookupType(type); -} diff --git a/packages/core/src/protos/index.ts b/packages/core/src/protos/index.ts new file mode 100644 index 000000000..69e4e4eb8 --- /dev/null +++ b/packages/core/src/protos/index.ts @@ -0,0 +1 @@ +export * from './generated'; diff --git a/packages/core/protos/raw/average_definitions.proto b/packages/core/src/protos/raw/average_definitions.proto similarity index 100% rename from packages/core/protos/raw/average_definitions.proto rename to packages/core/src/protos/raw/average_definitions.proto diff --git a/packages/core/protos/raw/reviews.proto b/packages/core/src/protos/raw/reviews.proto similarity index 100% rename from packages/core/protos/raw/reviews.proto rename to packages/core/src/protos/raw/reviews.proto diff --git a/packages/core/protos/raw/tank_definitions.proto b/packages/core/src/protos/raw/tank_definitions.proto similarity index 77% rename from packages/core/protos/raw/tank_definitions.proto rename to packages/core/src/protos/raw/tank_definitions.proto index dfedaa730..7ec168eac 100644 --- a/packages/core/protos/raw/tank_definitions.proto +++ b/packages/core/src/protos/raw/tank_definitions.proto @@ -41,9 +41,9 @@ message TankDefinition { } enum TankPriceType { - TYPE_UNSPECIFIED = 0; - TYPE_CREDITS = 1; - TYPE_GOLD = 2; + TANK_PRICE_TYPE_UNSPECIFIED = 0; + TANK_PRICE_TYPE_CREDITS = 1; + TANK_PRICE_TYPE_GOLD = 2; } message TankPrice { @@ -103,16 +103,32 @@ message GunDefinitionRegular { GunDefinitionRegularProperties regular = 2; } +message GunDefinitionRegularProperties { + float reload = 1; +} + message GunDefinitionAutoLoader { GunDefinitionBase gun = 1; GunDefinitionAutoLoaderProperties auto_loader = 2; } +message GunDefinitionAutoLoaderProperties { + float clip_reload = 1; + float intra_clip = 2; + float shell_count = 3; +} + message GunDefinitionAutoReloader { GunDefinitionBase gun = 1; GunDefinitionAutoReloaderProperties auto_reloader = 2; } +message GunDefinitionAutoReloaderProperties { + repeated float shell_reloads = 1; + float intra_clip = 2; + float shell_count = 3; +} + message GunDefinitionBase { uint32 id = 1; float rotation_speed = 2; @@ -146,11 +162,11 @@ message ShellDefinition { } enum ShellType { - SHELL_UNSPECIFIED = 0; - SHELL_AP = 1; - SHELL_APCR = 2; - SHELL_HEAT = 3; - SHELL_HE = 4; + SHELL_TYPE_UNSPECIFIED = 0; + SHELL_TYPE_AP = 1; + SHELL_TYPE_APCR = 2; + SHELL_TYPE_HEAT = 3; + SHELL_TYPE_HE = 4; } message ShellPenetration { @@ -170,20 +186,20 @@ message UnlockCost { } enum ModuleType { - MODULE_UNSPECIFIED = 0; - MODULE_VEHICLE = 1; - MODULE_ENGINE = 2; - MODULE_TRACKS = 3; - MODULE_TURRET = 4; - MODULE_GUN = 5; + MODULE_TYPE_UNSPECIFIED = 0; + MODULE_TYPE_VEHICLE = 1; + MODULE_TYPE_ENGINE = 2; + MODULE_TYPE_TRACKS = 3; + MODULE_TYPE_TURRET = 4; + MODULE_TYPE_GUN = 5; } enum TankClass { - CLASS_UNSPECIFIED = 0; - CLASS_LIGHT = 1; - CLASS_MEDIUM = 2; - CLASS_HEAVY = 3; - CLASS_TANK_DESTROYER = 4; + TANK_CLASS_UNSPECIFIED = 0; + TANK_CLASS_LIGHT = 1; + TANK_CLASS_MEDIUM = 2; + TANK_CLASS_HEAVY = 3; + TANK_CLASS_TANK_DESTROYER = 4; } enum Tier { @@ -201,10 +217,10 @@ enum Tier { } enum TankType { - TYPE_UNSPECIFIED = 0; - TYPE_RESEARCHABLE = 1; - TYPE_PREMIUM = 2; - TYPE_COLLECTOR = 3; + TANK_TYPE_UNSPECIFIED = 0; + TANK_TYPE_RESEARCHABLE = 1; + TANK_TYPE_PREMIUM = 2; + TANK_TYPE_COLLECTOR = 3; } message Crew { @@ -214,10 +230,10 @@ message Crew { } enum CrewType { - CREW_UNSPECIFIED = 0; - CREW_COMMANDER = 1; - CREW_RADIOMAN = 2; - CREW_GUNNER = 3; - CREW_DRIVER = 4; - CREW_LOADER = 5; + CREW_TYPE_UNSPECIFIED = 0; + CREW_TYPE_COMMANDER = 1; + CREW_TYPE_RADIOMAN = 2; + CREW_TYPE_GUNNER = 3; + CREW_TYPE_DRIVER = 4; + CREW_TYPE_LOADER = 5; } \ No newline at end of file diff --git a/packages/scripts/src/protos.ts b/packages/scripts/src/protos.ts index df08b44d6..5faa2236c 100644 --- a/packages/scripts/src/protos.ts +++ b/packages/scripts/src/protos.ts @@ -1,16 +1,41 @@ -import { $ } from 'bun'; -import { readdir } from 'fs/promises'; +import { exec as execSync } from 'child_process'; +import { existsSync } from 'fs'; +import { cp, mkdir, readdir, rm, writeFile } from 'fs/promises'; +import { promisify } from 'util'; -const ROOT = 'packages/core/protos'; +const ROOT = 'packages/core/src/protos'; + +const exec = promisify(execSync); + +let executableFileExtension: string; + +if (existsSync('node_modules/.bin/protoc-gen-ts.exe')) { + executableFileExtension = '.exe'; +} else { + executableFileExtension = ''; +} const files = await readdir(`${ROOT}/raw`); const args = [ - '--plugin="./node_modules/.bin/protoc-gen-ts"', - '--js_out="import_style=commonjs,binary:${OUT_DIR}"', - `--ts_out="${ROOT}/generated"`, + `--plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts${executableFileExtension}"`, + '--ts_opt=esModuleInterop=true', + `--js_out="import_style=commonjs,binary:./${ROOT}/generated"`, + `--ts_out="./${ROOT}/generated"`, ...files.map((file) => `${ROOT}/raw/${file}`), ]; -console.log(`protoc ${args.join(' ')}`); +await rm(`${ROOT}/generated`, { recursive: true, force: true }); +await mkdir(`${ROOT}/generated`, { recursive: true }); +await exec(`protoc ${args.join(' ')}`); +await cp(`${ROOT}/generated/${ROOT}/raw`, `${ROOT}/generated`, { + recursive: true, +}); +await rm(`${ROOT}/generated/packages`, { recursive: true, force: true }); -console.log(await $`protoc ${args.join(' ')}`.text()); +await writeFile( + `${ROOT}/generated/index.ts`, + files + .map((file) => file.replace('.proto', '')) + .map((file) => `export * from './${file}_pb';`) + .join('\n'), +);