From 45dc99e1ce77148b522ea08af004d8e0d0da6ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:07:00 -0500 Subject: [PATCH] feat: start of proto only --- bun.lockb | Bin 427565 -> 428329 bytes docs/technical/cdon.md | 99 ----- package.json | 6 +- .../core/protos/BattleResultsClient.proto | 298 -------------- packages/core/protos/PlayerAvatarImage.proto | 8 - .../{ => raw}/average_definitions.proto | 0 packages/core/protos/{ => raw}/reviews.proto | 0 .../core/protos/raw/tank_definitions.proto | 223 +++++++++++ packages/core/src/blitzkit/fetchCdonLz4.ts | 7 - packages/core/src/blitzkit/index.ts | 3 - packages/core/src/blitzkit/superCompress.ts | 8 - packages/core/src/blitzkit/superDecompress.ts | 8 - .../src/blitzkit/tankDefinitions/constants.ts | 8 +- .../src/blitzkit/tankDefinitions/index.ts | 183 +++++---- .../core/src/protobuf/lookupProtobufType.ts | 7 +- packages/core/src/streams/cdon.ts | 375 ------------------ packages/core/src/streams/index.ts | 1 - .../scripts/src/buildAssets/definitions.ts | 6 +- packages/scripts/src/protos.ts | 16 + 19 files changed, 365 insertions(+), 891 deletions(-) delete mode 100644 docs/technical/cdon.md delete mode 100644 packages/core/protos/BattleResultsClient.proto delete mode 100644 packages/core/protos/PlayerAvatarImage.proto rename packages/core/protos/{ => raw}/average_definitions.proto (100%) rename packages/core/protos/{ => raw}/reviews.proto (100%) create mode 100644 packages/core/protos/raw/tank_definitions.proto delete mode 100644 packages/core/src/blitzkit/fetchCdonLz4.ts delete mode 100644 packages/core/src/blitzkit/superCompress.ts delete mode 100644 packages/core/src/blitzkit/superDecompress.ts delete mode 100644 packages/core/src/streams/cdon.ts create mode 100644 packages/scripts/src/protos.ts diff --git a/bun.lockb b/bun.lockb index 5ef51acc4e89c4364442ae80179b1f8ea10f9f3f..bfd8bd34eb248cfa0c40d5279263685a78aee7b5 100644 GIT binary patch delta 85368 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/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 delta 84129 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 erRgKL286gg9jaWYYsTn_gL diff --git a/docs/technical/cdon.md b/docs/technical/cdon.md deleted file mode 100644 index ddb36bed5..000000000 --- a/docs/technical/cdon.md +++ /dev/null @@ -1,99 +0,0 @@ -# Cedilla Object Notation - -1. JSON compressed as CDON, written directly to disk (a direct 50% reduction). -2. CDON further compressed with LZ4 (a clean 90% reduction). -3. The raw JSON file as fetched from a random data source. -4. CDON decompressed once again to JSON. Note that this file is a little larger than the original JSON file as it contains a lot more decimal places due to float precision (this shouldn't affect the size in memory). - -![an image of file sizes](https://i.imgur.com/AHJiFpq.png) - -FS stands for "Fast String". - -```cpp -primary CedillaObjectNotation { - utf8"CDON" magic; - Header header; - primary Body body; -} - -Header { - uint16 version; // always 1 - FSFormat fsFormat; - StringTable stringTable; -} - -FSFormat enum { - Format8, - Format16, - Format32, -} - -FSPrimitive match(fsFormat) { - Format8: uint8; - Format16: uint16; - Format32: uint32; -} - -StringTable { - FSPrimitive count; - String[count] strings; -} - -Body { - primary Value object; -} - -ValueType enum { - Null, - Boolean, - Uint8, - Uint16, - Uint32, - Uint64, - Int8, - Int16, - Int32, - Int64, - Float32, - Float64, - String, - FS, - Array, - Object, -} - -String { - uint32 length; - primary utf8 value; -} - -StringValue Value & { (ValueType.String | ValueType.FS) type } - -Value { - ValueType type; - match { - Boolean: { uint8 value; } - Uint8: { uint8 value; } - Uint16: { uint16 value; } - Uint32: { uint32 value; } - Uint64: { uint64 value; } - Int8: { int8 value; } - Int16: { int16 value; } - Int32: { int32 value; } - Int64: { int64 value; } - Float32: { float32 value; } - Float64: { float64 value; } - String: { String value; } - FS: { FSPrimitive index; } - Array: { - uint32 count; - Value[count] values; - } - Object: { - uint32 count; - StringValue[count] keys; - Value[count] values; - } - } -} -``` diff --git a/package.json b/package.json index eb7837365..956a18c56 100644 --- a/package.json +++ b/package.json @@ -28,19 +28,21 @@ "format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\"", "update": "yarn upgrade --latest", "tunnel": "cloudflared tunnel --url http://localhost:3000", - "discoverids": "scripts/discoverIds.ts" + "discoverids": "scripts/discoverIds.ts", + "build:protos": "bun packages/scripts/src/protos.ts" }, "license": "MIT", "dependencies": { "lodash-es": "^4.17.21" }, "devDependencies": { - "@types/lodash-es": "^4.17.12", "@types/bun": "latest", + "@types/lodash-es": "^4.17.12", "@types/node": "^22.5.4", "esbuild": "^0.19.12", "prettier": "^3.3.3", "prisma": "^5.19.1", + "ts-protoc-gen": "^0.15.0", "typescript": "^5.5.4" } } diff --git a/packages/core/protos/BattleResultsClient.proto b/packages/core/protos/BattleResultsClient.proto deleted file mode 100644 index 53c53f1fa..000000000 --- a/packages/core/protos/BattleResultsClient.proto +++ /dev/null @@ -1,298 +0,0 @@ -syntax = "proto3"; - -package BattleResultsGenerated; - -import "PlayerAvatarImage.proto"; - -message Int32List { - repeated int32 values = 1; -} - -message PlayerInfo { - message AvatarEntry { - int32 key = 1; - .PlayerAvatarInfo value = 2; - } - - string name = 1; - int32 prebattleID = 2; - int32 team = 3; - int64 clanID = 4; - string clanTag = 5; - repeated int32 chatMessageCount = 6; - repeated .BattleResultsGenerated.PlayerInfo.AvatarEntry avatar = 7; - int32 profileBackground = 8; - int32 vehicleRank = 9; -} - -message TeamInfo { - string title = 1; - string icon = 2; -} - -message VehiclePublicResults { - message ExtVehAchievementsEntry { - int32 key = 1; - int32 value = 2; - } - - message ExtAccAchievementsEntry { - int32 key = 1; - int32 value = 2; - } - - int32 health = 1; - int32 credits = 2; - int32 xp = 3; - int32 shots = 4; - int32 directHits = 5; - int32 explosionHits = 6; - int32 piercings = 7; - int32 damageDealt = 8; - int32 damageAssistedRadio = 9; - int32 damageAssistedTrack = 10; - int32 damageReceived = 11; - int32 directHitsReceived = 12; - int32 noDamageDirectHitsReceived = 13; - int32 explosionHitsReceived = 14; - int32 piercingsReceived = 15; - int32 spotted = 16; - int32 damaged = 17; - int32 kills = 18; - int32 tdamageDealt = 19; - int32 tkills = 20; - int32 capturePoints = 21; - int32 droppedCapturePoints = 22; - int32 mileage = 23; - int32 lifeTime = 24; - int32 killerID = 25; - repeated int32 achievements = 26; - repeated .BattleResultsGenerated.VehiclePublicResults.ExtVehAchievementsEntry extVehAchievements = 27; - repeated .BattleResultsGenerated.VehiclePublicResults.ExtAccAchievementsEntry extAccAchievements = 28; - int32 xpDamage = 29; - int32 xpAssist = 30; - int32 xpTeamBonus = 31; - int32 wpEarned = 32; - int32 wpStolen = 33; - int32 heroCreditsBonus = 34; - int32 heroXpBonus = 35; - int64 accountDBID = 101; - int32 team = 102; - int32 serializedVehType = 103; - int32 gold = 104; - int32 deathReason = 105; - int32 camouflage = 106; - float mmr = 107; - float mmrDiff = 108; - int32 calibrationBattlesLeft = 109; - int32 healedHP = 114; - int32 wasHealedFor = 115; - int32 xpActivity = 36; - int32 customization = 116; - int32 potentialEnemyDamage = 117; - int32 rammingDamage = 118; - int32 helpedToKill = 119; -} - -message BattleResultsFinalXp { - int32 xpDamagePure = 1; - int32 xpDamagePrem = 2; - int32 xpAssistPure = 3; - int32 xpAssistPrem = 4; - int32 xpActivityPure = 5; - int32 xpActivityPrem = 6; - int32 xpTeamBonusPure = 7; - int32 xpTeamBonusPrem = 8; - int32 healingXpPure = 9; - int32 healingXpPrem = 10; - int32 heroXpBonusPure = 11; - int32 heroXpBonusPrem = 12; - int32 earnedFreeXpPure = 13; - int32 earnedFreeXpPrem = 14; - int32 earnedAvatarXpPure = 15; - int32 earnedAvatarXpPrem = 16; - int32 xpNoModifiers = 17; - int32 xpPure = 18; - int32 xpPrem = 19; - int32 totalFreeXpPure = 20; - int32 totalFreeXpPrem = 21; - int32 totalAvatarXpPure = 22; - int32 totalAvatarXpPrem = 23; -} - -message Ribbons { - int32 id = 1; - int32 grade = 2; - int32 amount = 3; - int32 value = 4; -} - -message BattleResultsUpdate { - message ExcellentBattleDataEntry { - string key = 1; - int32 value = 2; - } - - message StuffEntry { - int32 key = 1; - int32 value = 2; - } - - message RatingBattleStuffBonusEntry { - int32 key = 1; - int32 value = 2; - } - - int32 avatarXP = 1; - int32 eventCredits = 2; - int32 eventGold = 3; - int32 eventXP = 4; - int32 eventFreeXP = 5; - int32 eventAvatarXP = 6; - int32 autoRepairCost = 7; - repeated int32 autoLoadCost = 8; - repeated int32 autoEquipCost = 9; - repeated int32 autoProvCost = 10; - bool isPremium = 12; - int32 premiumXPFactor10 = 13; - int32 premiumCreditsFactor10 = 14; - int32 xpFactor10 = 15; - int32 creditsFactor10 = 16; - int32 aogasFactor10 = 17; - int32 markOfMastery = 18; - repeated .BattleResultsGenerated.BattleResultsUpdate.ExcellentBattleDataEntry excellentBattleData = 19; - bytes vehDossier = 20; - bytes accDossier = 21; - bytes vehDossierPrev = 22; - bytes accDossierPrev = 23; - int32 autoRepairDiscount = 24; - repeated int32 autoEquipDiscount = 25; - repeated int32 autoProvDiscount = 26; - repeated .BattleResultsGenerated.BattleResultsUpdate.StuffEntry stuff = 27; - int32 boosterCredits = 29; - int32 boosterXp = 30; - int32 boosterFreeXp = 31; - int32 boosterAvatarXp = 32; - int32 complimentsLimit = 33; - repeated int32 autoAbilsCost = 34; - repeated int32 autoAbilsDiscount = 35; - bool hasHealingReward = 36; - int32 healingCredits = 37; - int32 healingXp = 38; - int32 healingFreeXp = 39; - int32 healingAvatarXp = 40; - float mmr = 107; - float mmrDiff = 108; - int32 calibrationBattlesLeft = 109; - int32 ratingBattleXp = 110; - int32 ratingBattleFreeXp = 111; - int32 ratingBattleAvatarXp = 112; - repeated .BattleResultsGenerated.BattleResultsUpdate.RatingBattleStuffBonusEntry ratingBattleStuffBonus = 113; - repeated .BattleResultsGenerated.Ribbons ribbons = 114; -} - -message DropData { - message StuffEntry { - int32 key = 1; - int32 value = 2; - } - - int32 credits = 1; - int32 gold = 2; - int32 xp = 3; - int32 freeXP = 4; - int32 avatarXP = 5; - repeated .BattleResultsGenerated.DropData.StuffEntry stuff = 27; -} - -message VehicleInteractionDetails { - message DamagedModulesEntry { - int32 key = 1; - int32 value = 2; - } - - message DestroyedModulesEntry { - int32 key = 1; - int32 value = 2; - } - - bool spotted = 1; - int32 deathReason = 2; - int32 directHits = 3; - int32 directHitWithoutDamage = 4; - int32 explosionHits = 5; - int32 piercings = 6; - int32 damageDealt = 7; - int32 damageAssistedTrack = 8; - int32 damageAssistedRadio = 9; - int32 fire = 10; - repeated .BattleResultsGenerated.VehicleInteractionDetails.DamagedModulesEntry damagedModules = 11; - repeated .BattleResultsGenerated.VehicleInteractionDetails.DestroyedModulesEntry destroyedModules = 12; - int32 ricochetHitWithoutDamage = 13; -} - -message InteractionDetails { - message VehiclesEntry { - int32 key = 1; - .BattleResultsGenerated.VehicleInteractionDetails value = 2; - } - - repeated .BattleResultsGenerated.InteractionDetails.VehiclesEntry vehicles = 1; -} - -message PrebattleStats { - int32 freeXp = 1; - int32 vehicleXp = 2; -} - -message BattleResultsClient { - message QuestsProgressEntry { - string key = 1; - .BattleResultsGenerated.Int32List value = 2; - } - - message DropCategoriesEntry { - string key = 1; - .BattleResultsGenerated.DropData value = 2; - } - - message PlayersEntry { - int64 key = 1; - .BattleResultsGenerated.PlayerInfo value = 2; - } - - message VehiclesEntry { - int32 key = 1; - .BattleResultsGenerated.VehiclePublicResults value = 2; - } - - int32 arenaTypeID = 1; - int32 arenaCreateTime = 2; - int32 winnerTeam = 3; - int32 finishReason = 4; - int32 duration = 5; - int32 bonusType = 6; - int32 vehLockMode = 7; - .BattleResultsGenerated.VehiclePublicResults public = 8; - int32 gameModeID = 9; - int32 observerMode = 10; - .BattleResultsGenerated.BattleResultsFinalXp finalXp = 11; - int32 repair = 136; - int32 freeXP = 137; - int32 xpPenalty = 145; - int32 creditsPenalty = 146; - int32 creditsContributionIn = 147; - int32 creditsContributionOut = 148; - .BattleResultsGenerated.BattleResultsUpdate update = 150; - int32 originalXP = 181; - int32 originalFreeXP = 182; - int32 originalCredits = 183; - repeated .BattleResultsGenerated.BattleResultsClient.QuestsProgressEntry questsProgress = 184; - repeated .BattleResultsGenerated.BattleResultsClient.DropCategoriesEntry dropCategories = 185; - .BattleResultsGenerated.TeamInfo teamInfo = 186; - repeated .BattleResultsGenerated.BattleResultsClient.PlayersEntry players = 201; - repeated .BattleResultsGenerated.BattleResultsClient.VehiclesEntry vehicles = 301; - .BattleResultsGenerated.InteractionDetails interactionDetails = 302; - .BattleResultsGenerated.PrebattleStats prebattleStats = 303; -} - diff --git a/packages/core/protos/PlayerAvatarImage.proto b/packages/core/protos/PlayerAvatarImage.proto deleted file mode 100644 index 5778ac821..000000000 --- a/packages/core/protos/PlayerAvatarImage.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -message PlayerAvatarInfo { - uint32 id = 1; - string image = 2; - string image_retina = 3; - string grade = 4; -} diff --git a/packages/core/protos/average_definitions.proto b/packages/core/protos/raw/average_definitions.proto similarity index 100% rename from packages/core/protos/average_definitions.proto rename to packages/core/protos/raw/average_definitions.proto diff --git a/packages/core/protos/reviews.proto b/packages/core/protos/raw/reviews.proto similarity index 100% rename from packages/core/protos/reviews.proto rename to packages/core/protos/raw/reviews.proto diff --git a/packages/core/protos/raw/tank_definitions.proto b/packages/core/protos/raw/tank_definitions.proto new file mode 100644 index 000000000..dfedaa730 --- /dev/null +++ b/packages/core/protos/raw/tank_definitions.proto @@ -0,0 +1,223 @@ +syntax = "proto3"; + +package blitzkit; + +message TankDefinitions { + map tanks = 1; +} + +message TankDefinition { + uint32 id = 1; + map roles = 2; + optional string description = 3; + bool fixed_camouflage = 4; + repeated int32 camouflages = 5; + repeated int32 ancestors = 6; + repeated int32 successors = 7; + repeated Crew crew = 8; + uint32 health = 9; + string nation = 10; + string name = 11; + optional string name_full = 12; + TankType type = 13; + uint32 max_consumables = 14; + uint32 max_provisions = 15; + Tier tier = 16; + TankClass class = 17; + bool testing = 18; + bool deprecated = 19; + repeated TurretDefinition turrets = 20; + repeated EngineDefinition engines = 21; + repeated TrackDefinition tracks = 22; + TankPrice price = 23; + optional uint32 xp = 24; + float speed_forwards = 25; + float speed_backwards = 26; + float camouflage_still = 27; + float camouflage_moving = 28; + float camouflage_onFire = 29; + string equipment_preset = 30; + uint32 weight = 31; +} + +enum TankPriceType { + TYPE_UNSPECIFIED = 0; + TYPE_CREDITS = 1; + TYPE_GOLD = 2; +} + +message TankPrice { + TankPriceType type = 1; + uint32 value = 2; +} + +message TrackDefinition { + uint32 id = 1; + Tier tier = 2; + string name = 3; + uint32 weight = 4; + float traverse_speed = 5; + optional uint32 xp = 6; + float dispersion_move = 7; + float dispersion_traverse = 8; + float resistance_hard = 9; + float resistance_medium = 10; + float resistance_soft = 11; + repeated Unlock unlocks = 12; +} + +message EngineDefinition { + uint32 id = 1; + string name = 2; + optional uint32 xp = 3; + Tier tier = 4; + optional float fire_chance = 5; + uint32 power = 6; + uint32 weight = 7; + repeated Unlock unlocks = 8; +} + +message TurretDefinition { + uint32 id = 1; + uint32 health = 2; + uint32 view_range = 3; + float traverse_speed = 4; + optional uint32 xp = 5; + string name = 6; + uint32 tier = 7; + uint32 weight = 8; + repeated GunDefinition guns = 9; + repeated Unlock unlocks = 10; +} + +message GunDefinition { + oneof gun_type { + GunDefinitionRegular regular = 1; + GunDefinitionAutoLoader auto_loader = 2; + GunDefinitionAutoReloader auto_reloader = 3; + } +} + +message GunDefinitionRegular { + GunDefinitionBase gun = 1; + GunDefinitionRegularProperties regular = 2; +} + +message GunDefinitionAutoLoader { + GunDefinitionBase gun = 1; + GunDefinitionAutoLoaderProperties auto_loader = 2; +} + +message GunDefinitionAutoReloader { + GunDefinitionBase gun = 1; + GunDefinitionAutoReloaderProperties auto_reloader = 2; +} + +message GunDefinitionBase { + uint32 id = 1; + float rotation_speed = 2; + optional uint32 xp = 3; + uint32 weight = 4; + string name = 5; + uint32 tier = 6; + repeated ShellDefinition shells = 7; + float camouflage_loss = 8; + float aim_time = 9; + float dispersion_base = 10; + float dispersion_traverse = 11; + float dispersion_shot = 12; + float dispersion_damaged = 13; + repeated Unlock unlocks = 14; +} + +message ShellDefinition { + uint32 id = 1; + string name = 2; + uint32 velocity = 3; + uint32 armor_damage = 4; + uint32 module_damage = 5; + uint32 caliber = 6; + string icon = 7; + ShellPenetration penetration = 8; + ShellType type = 9; + uint32 normalization = 10; + uint32 ricochet = 11; + uint32 explosion_radius = 12; +} + +enum ShellType { + SHELL_UNSPECIFIED = 0; + SHELL_AP = 1; + SHELL_APCR = 2; + SHELL_HEAT = 3; + SHELL_HE = 4; +} + +message ShellPenetration { + uint32 near = 1; + uint32 far = 2; +} + +message Unlock { + int32 id = 1; + ModuleType type = 2; + UnlockCost cost = 3; +} + +message UnlockCost { + string type = 1; + int32 value = 2; +} + +enum ModuleType { + MODULE_UNSPECIFIED = 0; + MODULE_VEHICLE = 1; + MODULE_ENGINE = 2; + MODULE_TRACKS = 3; + MODULE_TURRET = 4; + MODULE_GUN = 5; +} + +enum TankClass { + CLASS_UNSPECIFIED = 0; + CLASS_LIGHT = 1; + CLASS_MEDIUM = 2; + CLASS_HEAVY = 3; + CLASS_TANK_DESTROYER = 4; +} + +enum Tier { + TIER_UNSPECIFIED = 0; + TIER_I = 1; + TIER_II = 2; + TIER_III = 3; + TIER_IV = 4; + TIER_V = 5; + TIER_VI = 6; + TIER_VII = 7; + TIER_VIII = 8; + TIER_IX = 9; + TIER_X = 10; +} + +enum TankType { + TYPE_UNSPECIFIED = 0; + TYPE_RESEARCHABLE = 1; + TYPE_PREMIUM = 2; + TYPE_COLLECTOR = 3; +} + +message Crew { + CrewType type = 1; + uint32 count = 2; + repeated CrewType substitute = 3; +} + +enum CrewType { + CREW_UNSPECIFIED = 0; + CREW_COMMANDER = 1; + CREW_RADIOMAN = 2; + CREW_GUNNER = 3; + CREW_DRIVER = 4; + CREW_LOADER = 5; +} \ No newline at end of file diff --git a/packages/core/src/blitzkit/fetchCdonLz4.ts b/packages/core/src/blitzkit/fetchCdonLz4.ts deleted file mode 100644 index 762631533..000000000 --- a/packages/core/src/blitzkit/fetchCdonLz4.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { superDecompress } from './superDecompress'; - -export async function fetchCdonLz4(url: string) { - return await fetch(url, { cache: 'no-store' }) - .then((response) => response.arrayBuffer()) - .then((buffer) => superDecompress(buffer)); -} diff --git a/packages/core/src/blitzkit/index.ts b/packages/core/src/blitzkit/index.ts index 964421f42..97a291acb 100644 --- a/packages/core/src/blitzkit/index.ts +++ b/packages/core/src/blitzkit/index.ts @@ -13,7 +13,6 @@ export * from './degressiveStat'; // export * from './emblemURL'; export * from './equipmentDefinitions'; export * from './eventManager'; -// export * from './fetchCdonLz4'; // export * from './flagUserActivity'; export * from './gameDefinitions'; // export * from './getArchivedLatestSeasonNumber'; @@ -36,8 +35,6 @@ export * from './resolvePenetrationCoefficient'; export * from './reviews'; export * from './skillDefinitions'; export * from './sum'; -export * from './superCompress'; -export * from './superDecompress'; export * from './tankDefinitions'; export * from './tankIcon'; export * from './tankNames'; diff --git a/packages/core/src/blitzkit/superCompress.ts b/packages/core/src/blitzkit/superCompress.ts deleted file mode 100644 index a3524a18c..000000000 --- a/packages/core/src/blitzkit/superCompress.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { compress } from 'lz4js'; -import { CdonWriteStream } from '../streams'; - -export function superCompress(object: any) { - const write = new CdonWriteStream().cdon(object); - const compressed = compress(write.uint8Array); - return Buffer.from(compressed).toString('base64'); -} diff --git a/packages/core/src/blitzkit/superDecompress.ts b/packages/core/src/blitzkit/superDecompress.ts deleted file mode 100644 index 595d75ae0..000000000 --- a/packages/core/src/blitzkit/superDecompress.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { decompress } from 'lz4js'; -import { CdonReadStream } from '../streams'; - -export function superDecompress(buffer: ArrayBuffer) { - const decompressed = decompress(new Uint8Array(buffer)).buffer as ArrayBuffer; - const read = new CdonReadStream(decompressed); - return read.cdon() as Type; -} diff --git a/packages/core/src/blitzkit/tankDefinitions/constants.ts b/packages/core/src/blitzkit/tankDefinitions/constants.ts index bbf7777c0..6c155af3a 100644 --- a/packages/core/src/blitzkit/tankDefinitions/constants.ts +++ b/packages/core/src/blitzkit/tankDefinitions/constants.ts @@ -1,10 +1,10 @@ import { - CrewMember, + CrewType, GunDefinition, ShellType, TankClass, + TankType, Tier, - TreeType, } from '.'; export const SHELL_NAMES: Record = { @@ -13,7 +13,7 @@ export const SHELL_NAMES: Record = { hc: 'HEAT', he: 'HE', }; -export const CREW_MEMBER_NAMES: Record = { +export const CREW_MEMBER_NAMES: Record = { commander: 'Commander', radioman: 'Radioman', gunner: 'Gunner', @@ -77,7 +77,7 @@ export const flags: Record = { european: '🇪🇺', other: '<:other:1218421572243558482>', }; -export const TREE_TYPE_ICONS: Record> = { +export const TREE_TYPE_ICONS: Record> = { researchable: TANK_ICONS, premium: TANK_ICONS_PREMIUM, collector: TANK_ICONS_COLLECTOR, diff --git a/packages/core/src/blitzkit/tankDefinitions/index.ts b/packages/core/src/blitzkit/tankDefinitions/index.ts index 8cfcc6c5e..970f129d0 100644 --- a/packages/core/src/blitzkit/tankDefinitions/index.ts +++ b/packages/core/src/blitzkit/tankDefinitions/index.ts @@ -1,27 +1,48 @@ import { Vector2Tuple } from 'three'; -import { TANK_CLASSES, TREE_TYPES } from '../../blitz/constants'; import { asset } from '../asset'; import { fetchCdonLz4 } from '../fetchCdonLz4'; -import { TIERS } from './constants'; -export type TankClass = (typeof TANK_CLASSES)[number]; -export type TreeType = (typeof TREE_TYPES)[number]; +export enum TankClass { + Unspecified, + Light, + Medium, + Heavy, + TankDestroyer, +} +export enum TankType { + Unspecified, + Researchable, + Premium, + Collector, +} export enum ShellType { - AP = 'ap', - APCR = 'ap_cr', - HEAT = 'hc', - HE = 'he', + Unspecified, + AP, + APCR, + HEAT, + HE, +} + +export enum CrewType { + Unspecified, + Commander, + Radioman, + Gunner, + Driver, + Loader, } -export type CrewMember = - | 'commander' - | 'radioman' - | 'gunner' - | 'driver' - | 'loader'; export type TankDefinitions = Record; -export type ModuleType = 'vehicle' | 'engine' | 'chassis' | 'turret' | 'gun'; +export enum ModuleType { + Unspecified, + Vehicle, + Engine, + Tracks, + Turret, + Gun, +} + export interface Unlock { type: ModuleType; id: number; @@ -32,9 +53,9 @@ export interface Unlock { }; } export interface Crew { - type: CrewMember; + type: CrewType; count?: number; - substitute?: CrewMember[]; + substitute?: CrewType[]; } export type ModuleDefinition = | TrackDefinition @@ -45,18 +66,18 @@ export interface TankDefinition { id: number; roles: Record; description?: string; - fixedCamouflage?: boolean; - camouflages?: number[]; - ancestors?: number[]; - successors?: number[]; + fixed_camouflage: boolean; + camouflages: number[]; + ancestors: number[]; + successors: number[]; crew: Crew[]; health: number; nation: string; name: string; nameFull?: string; - treeType: TreeType; - consumables: number; - provisions: number; + type: TankType; + max_consumables: number; + max_provisions: number; tier: Tier; class: TankClass; testing: boolean; @@ -66,16 +87,12 @@ export interface TankDefinition { tracks: TrackDefinition[]; price: TankPrice; xp?: number; - speed: { - forwards: number; - backwards: number; - }; - camouflage: { - still: number; - moving: number; - onFire: number; - }; - equipment: string; + speed_forwards: number; + speed_backwards: number; + camouflage_still: number; + camouflage_moving: number; + camouflage_onFire: number; + equipment_preset: string; weight: number; } export interface TrackDefinition { @@ -83,17 +100,13 @@ export interface TrackDefinition { tier: Tier; name: string; weight: number; - traverseSpeed: number; + traverse_speed: number; xp?: number; - dispersion: { - move: number; - traverse: number; - }; - resistance: { - hard: number; - medium: number; - soft: number; - }; + dispersion_move: number; + dispersion_traverse: number; + resistance_hard: number; + resistance_medium: number; + resistance_soft: number; unlocks?: Unlock[]; } export interface EngineDefinition { @@ -101,18 +114,24 @@ export interface EngineDefinition { name: string; xp?: number; tier: Tier; - fireChance: number; + fire_chance: number; power: number; weight: number; unlocks?: Unlock[]; } -export type TankPrice = - | { type: 'credits'; value: number } - | { type: 'gold'; value: number }; +export type TankPrice = { + type: TankPriceType; + value: number; +}; +enum TankPriceType { + Unspecified, + Credits, + Gold, +} export interface TurretDefinition { health: number; - viewRange: number; - traverseSpeed: number; + view_range: number; + traverse_speed: number; xp?: number; id: number; name: string; @@ -126,52 +145,60 @@ export type GunDefinition = | GunDefinitionAutoLoader | GunDefinitionAutoReloader; interface GunDefinitionBase { - rotationSpeed: number; + rotation_speed: number; xp?: number; weight: number; id: number; name: string; tier: Tier; shells: ShellDefinition[]; - camouflageLoss: number; - aimTime: number; - dispersion: { - base: number; - traverse: number; - shot: number; - damaged: number; - }; + camouflage_loss: number; + aim_time: number; + dispersion_base: number; + dispersion_traverse: number; + dispersion_shot: number; + dispersion_damaged: number; unlocks?: Unlock[]; } -interface GunDefinitionRegular extends GunDefinitionBase { - type: 'regular'; +interface GunDefinitionRegular { + gun: GunDefinitionBase; + regular: GunDefinitionRegularProperties; +} +interface GunDefinitionRegularProperties { reload: number; } -interface GunDefinitionAutoLoader extends GunDefinitionBase { - type: 'autoLoader'; +interface GunDefinitionAutoLoader { + gun: GunDefinitionBase; + auto_loader: GunDefinitionAutoLoaderProperties; +} +interface GunDefinitionAutoLoaderProperties { reload: number; - intraClip: number; + intra_clip: number; count: number; } -interface GunDefinitionAutoReloader extends GunDefinitionBase { - type: 'autoReloader'; +interface GunDefinitionAutoReloader { + gun: GunDefinitionBase; + auto_reloader: GunDefinitionAutoReloaderProperties; +} +interface GunDefinitionAutoReloaderProperties { reload: number[]; intraClip: number; count: number; } -export type ShellDefinition = { +export interface ShellDefinition { id: number; name: string; - speed: number; - damage: { armor: number; module: number }; + velocity: number; + armor_damage: number; + module_damage: number; caliber: number; icon: string; penetration: number | Vector2Tuple; type: ShellType; normalization?: number; ricochet?: number; - explosionRadius?: number; -}; + explosion_radius?: number; +} export const tankDefinitions = fetchCdonLz4( asset('definitions/tanks.cdon.lz4'), @@ -180,6 +207,18 @@ export const tankDefinitions = fetchCdonLz4( export const tankDefinitionsArray = tankDefinitions.then((tanks) => Object.values(tanks), ); -export type Tier = (typeof TIERS)[number]; +export enum Tier { + Unspecified, + I, + II, + III, + IV, + V, + VI, + VII, + VIII, + IX, + X, +} export * from './constants'; diff --git a/packages/core/src/protobuf/lookupProtobufType.ts b/packages/core/src/protobuf/lookupProtobufType.ts index 11008572e..880f13713 100644 --- a/packages/core/src/protobuf/lookupProtobufType.ts +++ b/packages/core/src/protobuf/lookupProtobufType.ts @@ -1,10 +1,11 @@ import protobuf from 'protobufjs'; -import average_definitions from '../../protos/average_definitions.proto?raw'; -import reviews from '../../protos/reviews.proto?raw'; +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 }; +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/streams/cdon.ts b/packages/core/src/streams/cdon.ts deleted file mode 100644 index ecf66521f..000000000 --- a/packages/core/src/streams/cdon.ts +++ /dev/null @@ -1,375 +0,0 @@ -import { times } from 'lodash-es'; -import { ReadStream, WriteStream } from './buffer'; - -enum ValueType { - Null, - Boolean, - Uint8, - Uint16, - Uint32, - Uint64, - Int8, - Int16, - Int32, - Int64, - Float32, - Float64, - String, - FastString, - Array, - Object, -} - -enum FastStringFormat { - Format8, - Format16, - Format32, -} - -export type CdonValue = - | undefined - | null - | boolean - | number - | bigint - | string - | CdonValue[] - | { [key: string]: CdonValue }; - -export class CdonReadStream extends ReadStream { - cdon() { - this.magic(); - const header = this.header(); - const body = this.body(header.fastStringFormat, header.stringTable); - return body; - } - - magic() { - const magic = this.utf8(4); - - if (magic !== 'CDON') { - throw new Error(`Invalid CDON magic number: "${magic}"`); - } - } - - header() { - const version = this.uint16(); - const fastStringFormat = this.uint8() as FastStringFormat; - - return { - version, - fastStringFormat, - stringTable: this.stringTable(fastStringFormat), - }; - } - - body( - fastStringFormat: FastStringFormat, - stringTable: Record, - ) { - return this.value(fastStringFormat, stringTable); - } - - stringTable(fastStringFormat: FastStringFormat) { - let count: number; - - switch (fastStringFormat) { - case FastStringFormat.Format8: - count = this.uint8(); - break; - - case FastStringFormat.Format16: - count = this.uint16(); - break; - - case FastStringFormat.Format32: - count = this.uint32(); - break; - } - - const strings: string[] = []; - - for (let index = 0; index < count; index++) { - strings.push(this.string()); - } - - const table: Record = {}; - times(count, (index) => (table[index] = strings[index])); - - return table; - } - - string() { - const length = this.uint32(); - const string = this.utf8(length); - return string; - } - - value( - fastStringFormat: FastStringFormat, - stringTable: Record, - ): CdonValue { - const type = this.uint8() as ValueType; - - switch (type) { - case ValueType.Null: - return null; - - case ValueType.Boolean: - return this.boolean(); - - case ValueType.Uint8: - return this.uint8(); - - case ValueType.Uint16: - return this.uint16(); - - case ValueType.Uint32: - return this.uint32(); - - case ValueType.Uint64: - return this.uint64(); - - case ValueType.Int8: - return this.int8(); - - case ValueType.Int16: - return this.int16(); - - case ValueType.Int32: - return this.int32(); - - case ValueType.Int64: - return this.int64(); - - case ValueType.Float32: - return this.float32(); - - case ValueType.Float64: - return this.float64(); - - case ValueType.String: - return this.string(); - - case ValueType.FastString: { - switch (fastStringFormat) { - case FastStringFormat.Format8: - return stringTable[this.uint8()]; - - case FastStringFormat.Format16: - return stringTable[this.uint16()]; - - case FastStringFormat.Format32: - return stringTable[this.uint32()]; - } - } - - case ValueType.Array: - return times(this.uint32(), () => - this.value(fastStringFormat, stringTable), - ); - - case ValueType.Object: { - const count = this.uint32(); - const keys = times( - count, - () => this.value(fastStringFormat, stringTable) as string, - ); - const values = times(count, () => - this.value(fastStringFormat, stringTable), - ); - const object: Record = {}; - - keys.forEach((string, index) => (object[string] = values[index])); - - return object; - } - - default: - throw new Error(`Invalid value type: ${type}`); - } - } -} - -export class CdonWriteStream extends WriteStream { - cdon(object: CdonValue) { - this.magic(); - const header = this.header(object); - this.body(header.fastStringFormat, object, header.stringTable); - return this; - } - - body( - fastStringFormat: FastStringFormat, - object: CdonValue, - stringTable: Map, - ) { - this.value(fastStringFormat, object, stringTable); - return this; - } - - value( - fastStringFormat: FastStringFormat, - object: CdonValue, - stringTable: Map, - ) { - if (object === null || object === undefined) { - this.uint8(ValueType.Null); - } else if (typeof object === 'boolean') { - this.uint8(ValueType.Boolean); - this.uint8(object ? 1 : 0); - } else if (typeof object === 'number') { - if (object % 1 === 0) { - if (object < 0) { - if (object < -0x80000000) { - this.uint8(ValueType.Int64); - this.int64(BigInt(object)); - } else if (object < -0x8000) { - this.uint8(ValueType.Int32); - this.int32(object); - } else if (object < -0x80) { - this.uint8(ValueType.Int16); - this.int16(object); - } else { - this.uint8(ValueType.Int8); - this.int8(object); - } - } else { - if (object > 0x7fffffff) { - this.uint8(ValueType.Uint64); - this.uint64(BigInt(object)); - } else if (object > 0x7fff) { - this.uint8(ValueType.Uint32); - this.uint32(object); - } else if (object > 0x7f) { - this.uint8(ValueType.Uint16); - this.uint16(object); - } else { - this.uint8(ValueType.Uint8); - this.uint8(object); - } - } - } else { - if (object < -0x80000000 || object > 0x7fffffff) { - this.uint8(ValueType.Float64); - this.float64(object); - } else { - this.uint8(ValueType.Float32); - this.float32(object); - } - } - } else if (typeof object === 'bigint') { - if (object < 0) { - this.int64(object); - } else { - this.uint64(object); - } - } else if (typeof object === 'string') { - if (stringTable.has(object)) { - this.uint8(ValueType.FastString); - const id = stringTable.get(object)!; - switch (fastStringFormat) { - case FastStringFormat.Format8: - this.uint8(id); - break; - - case FastStringFormat.Format16: - this.uint16(id); - break; - - case FastStringFormat.Format32: - this.uint32(id); - } - } else { - this.uint8(ValueType.String); - this.string(object); - } - } else if (Array.isArray(object)) { - this.uint8(ValueType.Array); - this.uint32(object.length); - object.forEach((value) => - this.value(fastStringFormat, value, stringTable), - ); - } else { - const entries = Object.entries(object).filter( - ([, value]) => value !== undefined, - ); - - this.uint8(ValueType.Object); - this.uint32(entries.length); - entries.forEach(([key]) => - this.value(fastStringFormat, key, stringTable), - ); - entries.forEach(([, value]) => - this.value(fastStringFormat, value, stringTable), - ); - } - } - - header(object: CdonValue) { - this.uint16(1); - return this.stringTable(object); - } - - stringTable(object: CdonValue) { - const stringTable = this.buildStringTable( - this.collectStringCounts(object, new Map()), - ); - let fastStringFormat: FastStringFormat; - - if (stringTable.size <= 0xff) { - fastStringFormat = FastStringFormat.Format8; - this.uint8(FastStringFormat.Format8); - this.uint8(stringTable.size); - } else if (stringTable.size <= 0xffff) { - fastStringFormat = FastStringFormat.Format16; - this.uint8(FastStringFormat.Format16); - this.uint16(stringTable.size); - } else { - fastStringFormat = FastStringFormat.Format32; - this.uint8(FastStringFormat.Format32); - this.uint32(stringTable.size); - } - - stringTable.forEach((_index, string) => this.string(string)); - - return { fastStringFormat, stringTable }; - } - - buildStringTable(stringCounts: Map) { - const stringTable = new Map(); - - stringCounts.forEach((count, string) => { - if (count > 1) stringTable.set(string, stringTable.size); - }); - - return stringTable; - } - - collectStringCounts(object: CdonValue, stringCounts: Map) { - if (typeof object === 'string') { - if (stringCounts.has(object)) { - stringCounts.set(object, stringCounts.get(object)! + 1); - } else { - stringCounts.set(object, 1); - } - } else if (object instanceof Array) { - object.forEach((value) => this.collectStringCounts(value, stringCounts)); - } else if (object instanceof Object) { - Object.entries(object).forEach((strings) => - this.collectStringCounts(strings, stringCounts), - ); - } - - return stringCounts; - } - - string(value: string) { - this.uint32(Buffer.byteLength(value)); - this.utf8(value); - } - - magic() { - this.utf8('CDON'); - } -} diff --git a/packages/core/src/streams/index.ts b/packages/core/src/streams/index.ts index a16292c7c..965bed6a8 100644 --- a/packages/core/src/streams/index.ts +++ b/packages/core/src/streams/index.ts @@ -1,6 +1,5 @@ export * from './bkrl'; export * from './buffer'; -export * from './cdon'; export * from './dds'; export * from './dids'; export * from './pvr'; diff --git a/packages/scripts/src/buildAssets/definitions.ts b/packages/scripts/src/buildAssets/definitions.ts index 852a19f3e..ee16f22d6 100644 --- a/packages/scripts/src/buildAssets/definitions.ts +++ b/packages/scripts/src/buildAssets/definitions.ts @@ -807,7 +807,7 @@ export async function definitions() { forwards: tankDefinition.root.speedLimits.forward, backwards: tankDefinition.root.speedLimits.backward, }, - equipment: + equipment_preset: typeof equipment === 'string' ? equipment : equipment.at(-1)!, consumables: tankDefinition.root.consumableSlots, provisions: tankDefinition.root.provisionSlots, @@ -888,7 +888,7 @@ export async function definitions() { id: trackId, weight: track.weight, name: strings[track.userString], - traverseSpeed: track.rotationSpeed, + traverse_speed: track.rotationSpeed, dispersion: { move: track.shotDispersionFactors.vehicleMovement, traverse: track.shotDispersionFactors.vehicleRotation, @@ -920,7 +920,7 @@ export async function definitions() { tankDefinitions[tankId].engines.push({ id: engineId, name: strings[engineListEntry.userString], - fireChance: engineListEntry.fireStartingChance, + fire_chance: engineListEntry.fireStartingChance, tier: engineListEntry.level as Tier, weight: engineListEntry.weight, power: engineListEntry.power, diff --git a/packages/scripts/src/protos.ts b/packages/scripts/src/protos.ts new file mode 100644 index 000000000..df08b44d6 --- /dev/null +++ b/packages/scripts/src/protos.ts @@ -0,0 +1,16 @@ +import { $ } from 'bun'; +import { readdir } from 'fs/promises'; + +const ROOT = 'packages/core/protos'; + +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"`, + ...files.map((file) => `${ROOT}/raw/${file}`), +]; + +console.log(`protoc ${args.join(' ')}`); + +console.log(await $`protoc ${args.join(' ')}`.text());