fix: some linting for new proto 5

This commit is contained in:
TrèsAbhi committed 2024-10-05 23:20:04 -05:00
1 parent 53a9c5f2de
commit 96310a9d63
40 files changed
+409 -367

No files matched your search

@@ -188,7 +188,7 @@ export async function renderBreakdown(
key={id} key={id}
displayType="tank" displayType="tank"
class={tankDefinition?.class} class={tankDefinition?.class}
displayType={tankDefinition?.type} type={tankDefinition?.type}
title={ title={
tankDefinition?.name ?? tankDefinition?.name ??
translate('bot.commands.breakdown.body.unknown_tank', [`${id}`]) translate('bot.commands.breakdown.body.unknown_tank', [`${id}`])
+7 -5
View File
@@ -1,11 +1,8 @@
import { import {
blitzStarsTankAverages,
calculateWN8, calculateWN8,
emblemURL, emblemURL,
getClanAccountInfo, getClanAccountInfo,
idToRegion, idToRegion,
mapDefinitions,
tankDefinitions,
tankIcon, tankIcon,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
@@ -13,7 +10,12 @@ import { clamp } from 'lodash-es';
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from '../components/CommandWrapper';
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from '../components/TitleBar';
import { iconPng } from '../core/blitzkit/iconPng'; import { iconPng } from '../core/blitzkit/iconPng';
import {
mapDefinitions,
tankDefinitions,
} from '../core/blitzkit/nonBlockingPromises';
import { RenderConfiguration } from '../core/blitzkit/renderConfiguration'; import { RenderConfiguration } from '../core/blitzkit/renderConfiguration';
import { blitzStarsTankAverages } from '../core/blitzstars/tankAverages';
import { buttonLink } from '../core/discord/buttonLink'; import { buttonLink } from '../core/discord/buttonLink';
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
import { CommandRegistry } from '../events/interactionCreate'; import { CommandRegistry } from '../events/interactionCreate';
@@ -223,7 +225,7 @@ async function playerListing(
) { ) {
const awaitedTankAverages = await blitzStarsTankAverages; const awaitedTankAverages = await blitzStarsTankAverages;
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await tankDefinitions;
const tank = awaitedTankDefinitions[player.vehicle_descr]; const tank = awaitedTankDefinitions.tanks[player.vehicle_descr];
const blockAccent = recordingPlayer ? '_amber' : ''; const blockAccent = recordingPlayer ? '_amber' : '';
const healthAccent = protagonistTeam const healthAccent = protagonistTeam
? recordingPlayer ? recordingPlayer
@@ -502,7 +504,7 @@ export const replayCommand = new Promise<CommandRegistry>((resolve) => {
replayData.protagonist_team === replayData.winner_team replayData.protagonist_team === replayData.winner_team
? 'Victory' ? 'Victory'
: 'Defeat' : 'Defeat'
} • ${awaitedMapDefinitions[replayData.map_id].name}`} } • ${awaitedMapDefinitions.maps[replayData.map_id].name}`}
/> />
<div <div
+13 -9
View File
@@ -6,7 +6,7 @@ import {
getClanAccountInfo, getClanAccountInfo,
getTankStats, getTankStats,
TANK_ICONS, TANK_ICONS,
tankDefinitions, TankType,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { escapeMarkdown, Locale } from 'discord.js'; import { escapeMarkdown, Locale } from 'discord.js';
@@ -15,6 +15,7 @@ import { TitleBar } from '../components/TitleBar';
import { resolveTankId } from '../core/blitz/resolveTankId'; import { resolveTankId } from '../core/blitz/resolveTankId';
import { buildTechTreeLine } from '../core/blitzkit/buildTechTreeLine'; import { buildTechTreeLine } from '../core/blitzkit/buildTechTreeLine';
import { iconPng } from '../core/blitzkit/iconPng'; import { iconPng } from '../core/blitzkit/iconPng';
import { tankDefinitions } from '../core/blitzkit/nonBlockingPromises';
import { resolveAncestry } from '../core/blitzkit/resolveAncestry'; import { resolveAncestry } from '../core/blitzkit/resolveAncestry';
import { tankIconPng } from '../core/blitzkit/tankIconPng'; import { tankIconPng } from '../core/blitzkit/tankIconPng';
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from '../core/discord/addUsernameChoices';
@@ -76,7 +77,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
true, true,
); );
const startingTankRaw = interaction.options.getString('starting-tank'); const startingTankRaw = interaction.options.getString('starting-tank');
const targetTank = awaitedTankDefinitions[targetTankId]; const targetTank = awaitedTankDefinitions.tanks[targetTankId];
const { id, region } = await resolvePlayerFromCommand(interaction); const { id, region } = await resolvePlayerFromCommand(interaction);
let startingTankId: number; let startingTankId: number;
const targetTankAncestry = await resolveAncestry(targetTankId); const targetTankAncestry = await resolveAncestry(targetTankId);
@@ -94,7 +95,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
]); ]);
} }
const startingTank = awaitedTankDefinitions[startingTankId]; const startingTank = awaitedTankDefinitions.tanks[startingTankId];
if (startingTank.tier > targetTank.tier) { if (startingTank.tier > targetTank.tier) {
return translate('bot.commands.research.errors.unordered', [ return translate('bot.commands.research.errors.unordered', [
@@ -111,7 +112,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
]); ]);
} }
} else { } else {
if (targetTank.treeType !== 'researchable') { if (targetTank.type !== TankType.RESEARCHABLE) {
return translate('bot.commands.research.errors.non_tech_tree', [ return translate('bot.commands.research.errors.non_tech_tree', [
escapeMarkdown(targetTank.name), escapeMarkdown(targetTank.name),
]); ]);
@@ -137,7 +138,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
const foundAncestor = targetTankAncestry.find( const foundAncestor = targetTankAncestry.find(
(id) => (id) =>
awaitedTankDefinitions[id].tier === 1 || awaitedTankDefinitions.tanks[id].tier === 1 ||
tankStats.some(({ tank_id }) => tank_id === id), tankStats.some(({ tank_id }) => tank_id === id),
); );
@@ -159,7 +160,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
const costs = await Promise.all( const costs = await Promise.all(
line.map(async (id) => { line.map(async (id) => {
const tank = awaitedTankDefinitions[id]; const tank = awaitedTankDefinitions.tanks[id];
const turretXps = new Map<number, number>(); const turretXps = new Map<number, number>();
const gunXps = new Map<number, number>(); const gunXps = new Map<number, number>();
const engineXps = new Map<number, number>(); const engineXps = new Map<number, number>();
@@ -171,8 +172,11 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
} }
turret.guns.forEach((gun) => { turret.guns.forEach((gun) => {
if (gun.xp !== undefined) { if (gun.gunType!.value.base.xp !== undefined) {
gunXps.set(gun.id, gun.xp); gunXps.set(
gun.gunType!.value.base.id,
gun.gunType!.value.base.xp,
);
} }
}); });
}); });
@@ -353,7 +357,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
{await Promise.all( {await Promise.all(
line.map(async (id, index) => { line.map(async (id, index) => {
const tank = awaitedTankDefinitions[id]; const tank = awaitedTankDefinitions.tanks[id];
return ( return (
<div <div
+1 -1
View File
@@ -1,7 +1,7 @@
import { tankDefinitions, tankNames } from '@blitzkit/core';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { go } from 'fuzzysort'; import { go } from 'fuzzysort';
import markdownEscape from 'markdown-escape'; import markdownEscape from 'markdown-escape';
import { tankNames } from '../blitzkit/nonBlockingPromises';
import { UserError } from '../blitzkit/userError'; import { UserError } from '../blitzkit/userError';
import { tankNamesTechTreeOnly } from '../discord/autocompleteTanks'; import { tankNamesTechTreeOnly } from '../discord/autocompleteTanks';
import { translator } from '../localization/translator'; import { translator } from '../localization/translator';
@@ -1,9 +1,9 @@
import { tankDefinitions } from '@blitzkit/core'; import { fetchTankDefinitions } from '@blitzkit/core';
import { resolveAncestry } from './resolveAncestry'; import { resolveAncestry } from './resolveAncestry';
export async function buildTechTreeLine(start: number, end: number) { export async function buildTechTreeLine(start: number, end: number) {
const awaitedTankDefinitions = await tankDefinitions; const tankDefinitions = await fetchTankDefinitions();
const endTank = awaitedTankDefinitions[end]; const endTank = tankDefinitions.tanks[end];
if (!endTank.ancestors) throw new Error('End tank has no ancestors'); if (!endTank.ancestors) throw new Error('End tank has no ancestors');
const line = [end]; const line = [end];
@@ -1,30 +1,30 @@
import { import {
StatFilters, fetchTankDefinitions,
tankDefinitions,
Tier, Tier,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { StatFilters } from '../blitzstars/filterStats';
import { translator } from '../localization/translator'; import { translator } from '../localization/translator';
export async function filtersToDescription( export async function filtersToDescription(
{ nation, tier, tankType, treeType, tank }: StatFilters, { nation, tier, type, class: tankClass, tank }: StatFilters,
locale: Locale, locale: Locale,
) { ) {
const { translate } = translator(locale); const { translate } = translator(locale);
const awaitedTankDefinitions = await tankDefinitions; const awaitedTankDefinitions = await fetchTankDefinitions();
const info: string[] = []; const info: string[] = [];
// TODO: somehow localize tank names? // TODO: somehow localize tank names?
if (tank) return awaitedTankDefinitions[tank].name; if (tank) return awaitedTankDefinitions.tanks[tank].name;
if (nation) info.push(translate(`common.nations.${nation}`)); if (nation) info.push(translate(`common.nations.${nation}`));
if (tier) { if (tier) {
info.push( info.push(
translate('bot.common.filters.tier', [TIER_ROMAN_NUMERALS[tier as Tier]]), translate('bot.common.filters.tier', [TIER_ROMAN_NUMERALS[tier as Tier]]),
); );
} }
if (tankType) info.push(translate(`common.tank_class_short.${tankType}`)); if (tankClass) info.push(translate(`common.tank_class_short.${tankClass}`));
if (treeType) info.push(translate(`common.tree_type.${treeType}`)); if (type) info.push(translate(`common.tree_type.${type}`));
return info.length === 0 return info.length === 0
? translate('bot.common.filters.none') ? translate('bot.common.filters.none')
@@ -1,4 +1,11 @@
import { fetchGameDefinitions, fetchTankDefinitions } from '@blitzkit/core'; import {
fetchGameDefinitions,
fetchMapDefinitions,
fetchTankDefinitions,
fetchTankNames,
} from '@blitzkit/core';
export const tankDefinitions = fetchTankDefinitions(); export const tankDefinitions = fetchTankDefinitions();
export const gameDefinitions = fetchGameDefinitions(); export const gameDefinitions = fetchGameDefinitions();
export const tankNames = fetchTankNames();
export const mapDefinitions = fetchMapDefinitions();
@@ -1,8 +1,8 @@
import { tankDefinitions } from '@blitzkit/core'; import { fetchTankDefinitions } from '@blitzkit/core';
export async function resolveAncestry(id: number) { export async function resolveAncestry(id: number) {
const awaitedTankDefinitions = await tankDefinitions; const tankDefinitions = await fetchTankDefinitions();
const tank = awaitedTankDefinitions[id]; const tank = tankDefinitions.tanks[id];
const ancestors: number[] = []; const ancestors: number[] = [];
if (tank.ancestors) { if (tank.ancestors) {
@@ -20,6 +20,6 @@ export async function resolveAncestry(id: number) {
} }
return ancestors.sort( return ancestors.sort(
(a, b) => awaitedTankDefinitions[b].tier - awaitedTankDefinitions[a].tier, (a, b) => tankDefinitions.tanks[b].tier - tankDefinitions.tanks[a].tier,
); );
} }
@@ -1,4 +1,4 @@
import { tankNames } from '@blitzkit/core'; import { fetchTankNames, TankType } from '@blitzkit/core';
import { import {
ApplicationCommandOptionChoiceData, ApplicationCommandOptionChoiceData,
AutocompleteInteraction, AutocompleteInteraction,
@@ -9,9 +9,10 @@ import {
DISCORD_CHOICES_MAX_NAME_SIZE, DISCORD_CHOICES_MAX_NAME_SIZE,
OVERFLOW_SUFFIX, OVERFLOW_SUFFIX,
} from './autocompleteClan/constants'; } from './autocompleteClan/constants';
import { tankNames } from '../blitzkit/nonBlockingPromises';
export const tankNamesTechTreeOnly = tankNames.then((names) => export const tankNamesTechTreeOnly = fetchTankNames().then((names) =>
names.filter((tank) => tank.treeType === 'researchable'), names.filter((tank) => tank.treeType === TankType.RESEARCHABLE),
); );
export async function autocompleteTanks( export async function autocompleteTanks(
+1 -1
View File
@@ -1,5 +1,5 @@
import { type ShellDefinition, ShellType } from '@blitzkit/core'; import { type ShellDefinition, ShellType } from '@blitzkit/core';
export function canSplash(type: ShellDefinition['type']): type is ShellType.HE { export function canSplash(type: ShellDefinition['type']): type is ShellType.HE {
return type === ShellType.SHELL_TYPE_HE; return type === ShellType.HE;
} }
+12 -11
View File
@@ -1,15 +1,16 @@
import { Vector3Tuple } from 'three'; import { Vector3Tuple } from 'three';
import { Tier } from '../blitzkit'; import { Tier } from '../protos';
export const equipmentPriceMatrix: Record<Tier, Vector3Tuple> = { export const equipmentPriceMatrix: Record<Tier, Vector3Tuple> = {
1: [100, 200, 300], [Tier.I]: [100, 200, 300],
2: [200, 300, 400], [Tier.II]: [200, 300, 400],
3: [400, 500, 600], [Tier.III]: [400, 500, 600],
4: [4000, 5000, 6000], [Tier.IV]: [4000, 5000, 6000],
5: [40_000, 50_000, 60_000], [Tier.V]: [40_000, 50_000, 60_000],
6: [100_000, 120_000, 140_000], [Tier.VI]: [100_000, 120_000, 140_000],
7: [150_000, 170_000, 190_000], [Tier.VII]: [150_000, 170_000, 190_000],
8: [200_000, 225_000, 250_000], [Tier.VIII]: [200_000, 225_000, 250_000],
9: [250_000, 275_000, 300_000], [Tier.IX]: [250_000, 275_000, 300_000],
10: [300_000, 350_000, 400_000], [Tier.X]: [300_000, 350_000, 400_000],
[Tier.UNRECOGNIZED]: [0, 0, 0],
}; };
@@ -1,6 +1,9 @@
import { ProvisionDefinitions } from '@blitzkit/core'; import {
GunDefinition,
ProvisionDefinitions,
TankDefinition,
} from '@blitzkit/core';
import { checkConsumableProvisionInclusivity } from './checkConsumableProvisionInclusivity'; import { checkConsumableProvisionInclusivity } from './checkConsumableProvisionInclusivity';
import { GunDefinition, TankDefinition } from './tankDefinitions';
export function availableProvisions( export function availableProvisions(
tank: TankDefinition, tank: TankDefinition,
@@ -1,5 +1,5 @@
import { Samples } from '.';
import { emptyAllStats } from '../../blitz/constants'; import { emptyAllStats } from '../../blitz/constants';
import { Samples } from '../../protos';
import { BlitzkitStats } from '../../statistics'; import { BlitzkitStats } from '../../statistics';
export const emptyAverageDefinitionsAllStats: BlitzkitStats = { export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
@@ -12,11 +12,11 @@ export const averageDefinitionsAllStatsKeys = Object.keys(
) as (keyof BlitzkitStats)[]; ) as (keyof BlitzkitStats)[];
export const emptySamples: Samples = { export const emptySamples: Samples = {
d_1: 0, d1: 0,
d_7: 0, d7: 0,
d_30: 0, d30: 0,
d_60: 0, d60: 0,
d_90: 0, d90: 0,
d_120: 0, d120: 0,
total: 0, total: 0,
}; };
@@ -1,53 +1,64 @@
import { ConsumableEntry, ProvisionEntry } from '@blitzkit/core'; import {
import { GunDefinition, TankDefinition } from './tankDefinitions'; Consumable,
ConsumableTankCategoryFilterCategory,
GunDefinition,
Provision,
TankDefinition,
} from '../protos';
export function checkConsumableProvisionInclusivity( export function checkConsumableProvisionInclusivity(
consumableProvision: ConsumableEntry | ProvisionEntry, consumableProvision: Consumable | Provision,
tank: TankDefinition, tank: TankDefinition,
gun: GunDefinition, gun: GunDefinition,
) { ) {
const included = const included =
!consumableProvision.gameMode && !consumableProvision.gameModeExclusive &&
consumableProvision.include?.every((rule) => { consumableProvision.include?.every((rule) => {
switch (rule.type) { switch (rule.filterType!.$case) {
case 'tier': case 'tiers':
return rule.min <= tank.tier && tank.tier <= rule.max; return (
rule.filterType!.value.min <= tank.tier &&
tank.tier <= rule.filterType!.value.max
);
case 'ids': case 'ids':
return rule.ids.includes(tank.id); return rule.filterType!.value.ids.includes(tank.id);
case 'nation': case 'nations':
return rule.nations.includes(tank.nation); return rule.filterType!.value.nations.includes(tank.nation);
case 'category': case 'categories':
throw new SyntaxError('Category filtering found in include rule'); throw new SyntaxError('Category filtering found in include rule');
} }
}); });
const excluded = const excluded =
consumableProvision.gameMode || consumableProvision.gameModeExclusive ||
consumableProvision.exclude?.some((rule) => { consumableProvision.exclude?.some((rule) => {
switch (rule.type) { switch (rule.filterType!.$case) {
case 'tier': case 'tiers':
return rule.min <= tank.tier && tank.tier <= rule.max; return (
rule.filterType!.value.min <= tank.tier &&
tank.tier <= rule.filterType!.value.max
);
case 'ids': case 'ids':
return rule.ids.includes(tank.id); return rule.filterType!.value.ids.includes(tank.id);
case 'nation': case 'nations':
return rule.nations.includes(tank.nation); return rule.filterType!.value.nations.includes(tank.nation);
case 'category': case 'categories':
return rule.categories.some((category) => { return rule.filterType!.value.categories.some((category) => {
switch (category) { switch (category) {
case 'clip': case ConsumableTankCategoryFilterCategory.CLIP:
return gun.type !== 'regular'; return gun.gunType!.$case !== 'regular';
} }
}); });
} }
}); });
return ( return (
!consumableProvision.gameMode && !consumableProvision.gameModeExclusive &&
consumableProvision.include?.length > 0 && consumableProvision.include?.length > 0 &&
included && included &&
!excluded !excluded
@@ -5,7 +5,7 @@ export function createDefaultSkills(skillDefinitions: SkillDefinitions) {
const skills: Record<string, number> = {}; const skills: Record<string, number> = {};
Object.values(skillDefinitions.classes).forEach((tankSkills) => { Object.values(skillDefinitions.classes).forEach((tankSkills) => {
tankSkills.forEach((skill) => { tankSkills.skills.forEach((skill) => {
skills[skill] = permanentSkills.includes(skill) ? 7 : 0; skills[skill] = permanentSkills.includes(skill) ? 7 : 0;
}); });
}); });
@@ -1,30 +1,30 @@
import { RatingInfo, Region, asset, superDecompress } from '@blitzkit/core'; // import { RatingInfo, Region, asset } from '@blitzkit/core';
const cache: Record< // const cache: Record<
Region, // Region,
Record< // Record<
number, // number,
RatingInfo & { // RatingInfo & {
detail: undefined; // detail: undefined;
} // }
> // >
> = { // > = {
com: {}, // com: {},
eu: {}, // eu: {},
asia: {}, // asia: {},
}; // };
export async function getArchivedRatingInfo(region: Region, season: number) { // export async function getArchivedRatingInfo(region: Region, season: number) {
if (!cache[region][season]) { // if (!cache[region][season]) {
const info = await fetch( // const info = await fetch(
asset(`regions/${region}/rating/${season}/info.cdon.lz4`), // asset(`regions/${region}/rating/${season}/info.cdon.lz4`),
) // )
.then((response) => response.arrayBuffer()) // .then((response) => response.arrayBuffer())
.then((buffer) => // .then((buffer) =>
superDecompress<RatingInfo & { detail: undefined }>(buffer), // superDecompress<RatingInfo & { detail: undefined }>(buffer),
); // );
cache[region][season] = info; // cache[region][season] = info;
} // }
return cache[region][season]; // return cache[region][season];
} // }
+2 -3
View File
@@ -10,10 +10,9 @@ export * from './consumableDefinitions';
export * from './createDefaultSkills'; export * from './createDefaultSkills';
export * from './degressiveStat'; export * from './degressiveStat';
export * from './discoveredIdDefinitions'; export * from './discoveredIdDefinitions';
// export * from './emblemURL'; export * from './emblemURL';
export * from './equipmentDefinitions'; export * from './equipmentDefinitions';
export * from './eventManager'; export * from './eventManager';
export * from './resolveGun';
// export * from './flagUserActivity'; // export * from './flagUserActivity';
export * from './gameDefinitions'; export * from './gameDefinitions';
// export * from './getArchivedLatestSeasonNumber'; // export * from './getArchivedLatestSeasonNumber';
@@ -23,7 +22,7 @@ export * from './gameDefinitions';
// export * from './getTimeDaysAgo'; // export * from './getTimeDaysAgo';
export * from './isExplosive'; export * from './isExplosive';
// export * from './linkBlitzAndDiscord'; // export * from './linkBlitzAndDiscord';
// export * from './mapDefinitions'; export * from './mapDefinitions';
export * from './modelDefinitions'; export * from './modelDefinitions';
export * from './normalizeBoundingBox'; export * from './normalizeBoundingBox';
// export * from './parseBkni'; // export * from './parseBkni';
@@ -1,8 +1,9 @@
import { BoundingBox } from '@blitzkit/core'; import { BoundingBox, Vector3 } from '@blitzkit/core';
import { Vector3Tuple } from 'three';
export function normalizeBoundingBox(boundingBox: BoundingBox) { export function normalizeBoundingBox(boundingBox: BoundingBox) {
return boundingBox.max.map( return {
(max, index) => max - boundingBox.min[index], x: boundingBox.max.x - boundingBox.min.x,
) as Vector3Tuple; y: boundingBox.max.y - boundingBox.min.y,
z: boundingBox.max.z - boundingBox.min.z,
} satisfies Vector3;
} }
+32 -20
View File
@@ -1,4 +1,8 @@
import { GunDefinition, ShellDefinition } from './tankDefinitions'; import {
GunDefinition,
GunDefinitionAutoReloaderProperties,
ShellDefinition,
} from '../protos';
export function resolveDpm( export function resolveDpm(
gun: GunDefinition, gun: GunDefinition,
@@ -7,30 +11,38 @@ export function resolveDpm(
reloadCoefficient = 1, reloadCoefficient = 1,
intraClipCoefficient = 1, intraClipCoefficient = 1,
) { ) {
const alpha = shell.damage.armor * damageCoefficient; const alpha = shell.armorDamage * damageCoefficient;
let dps: number; let dps: number;
if (gun.type === 'regular') { if (gun.gunType!.$case === 'regular') {
dps = alpha / (reloadCoefficient * gun.reload); dps = alpha / (reloadCoefficient * gun.gunType!.value.extension.reload);
} else if (gun.type === 'autoLoader') { } else if (gun.gunType!.$case === 'autoLoader') {
dps = dps =
(alpha * gun.count) / (alpha * gun.gunType!.value.extension.shellCount) /
(gun.reload * reloadCoefficient + (gun.gunType!.value.extension.clipReload * reloadCoefficient +
(gun.count - 1) * gun.intraClip * intraClipCoefficient); (gun.gunType!.value.extension.shellCount - 1) *
gun.gunType!.value.extension.intraClip *
intraClipCoefficient);
} else { } else {
const mostOptimalShell = gun.reload.reduce<null | { const mostOptimalShell =
index: number; gun.gunType!.value.extension.shellReloads.reduce<null | {
reload: number; index: number;
}>((current, reloadRaw, index) => { reload: number;
const reload = }>((current, reloadRaw, index) => {
reloadRaw * reloadCoefficient + const reload =
(index > 0 ? gun.intraClip * intraClipCoefficient : 0); reloadRaw * reloadCoefficient +
(index > 0
? (
gun.gunType!.value
.extension as GunDefinitionAutoReloaderProperties
).intraClip * intraClipCoefficient
: 0);
if (current === null || reload < current.reload) { if (current === null || reload < current.reload) {
return { index, reload }; return { index, reload };
} }
return current; return current;
}, null)!; }, null)!;
dps = alpha / mostOptimalShell?.reload; dps = alpha / mostOptimalShell?.reload;
} }
-9
View File
@@ -1,9 +0,0 @@
import { GunDefinition } from '../protos';
export function resolveGun(gun: GunDefinition) {
if (gun.regular) return gun.regular;
else if (gun.autoLoader) return gun.autoLoader;
else if (gun.autoReloader) return gun.autoReloader;
throw new Error('Could not resolve gun');
}
@@ -1,4 +1,4 @@
import { ShellType } from '../blitzkit/tankDefinitions'; import { ShellType } from '../protos';
export function resolvePenetrationCoefficient( export function resolvePenetrationCoefficient(
calibratedShells: boolean, calibratedShells: boolean,
@@ -6,11 +6,11 @@ export function resolvePenetrationCoefficient(
) { ) {
if (!calibratedShells) return 1; if (!calibratedShells) return 1;
return type === 'ap' return type === ShellType.AP
? 1.08 ? 1.08
: type === 'ap_cr' : type === ShellType.APCR
? 1.05 ? 1.05
: type === 'hc' : type === ShellType.HEAT
? 1.13 ? 1.13
: 1.08; : 1.08;
} }
+1
View File
@@ -9,3 +9,4 @@ export * from './protos';
export * from './statistics'; export * from './statistics';
export * from './streams'; export * from './streams';
export * from './types'; export * from './types';
@@ -12,7 +12,7 @@ message Consumable {
required uint32 id = 1; required uint32 id = 1;
required string name = 2; required string name = 2;
required uint32 cooldown = 3; required uint32 cooldown = 3;
optional uint32 duration = 4; optional float duration = 4;
required bool game_mode_exclusive = 5; required bool game_mode_exclusive = 5;
repeated ConsumableTankFilter include = 6; repeated ConsumableTankFilter include = 6;
repeated ConsumableTankFilter exclude = 7; repeated ConsumableTankFilter exclude = 7;
@@ -16,7 +16,7 @@ message ModelDefinition {
} }
message Armor { message Armor {
map<uint32, uint32> thickness = 1; map<uint32, float> thickness = 1;
repeated uint32 spaced = 2; repeated uint32 spaced = 2;
} }
@@ -52,13 +52,13 @@ message BoundingBox {
} }
message TrackModelDefinition { message TrackModelDefinition {
required uint32 thickness = 1; required float thickness = 1;
required Vector3 origin = 2; required Vector3 origin = 2;
} }
message GunModelDefinition { message GunModelDefinition {
required Armor armor = 1; required Armor armor = 1;
required uint32 thickness = 2; required float thickness = 2;
required uint32 model_id = 3; required uint32 model_id = 3;
required PitchLimits pitch = 4; required PitchLimits pitch = 4;
optional float mask = 5; optional float mask = 5;
+23 -11
View File
@@ -30,7 +30,7 @@ message TankDefinition {
repeated EngineDefinition engines = 21; repeated EngineDefinition engines = 21;
repeated TrackDefinition tracks = 22; repeated TrackDefinition tracks = 22;
required TankPrice price = 23; required TankPrice price = 23;
optional uint32 xp = 24; optional ResearchCost research_cost = 24;
required float speed_forwards = 25; required float speed_forwards = 25;
required float speed_backwards = 26; required float speed_backwards = 26;
required float camouflage_still = 27; required float camouflage_still = 27;
@@ -40,6 +40,18 @@ message TankDefinition {
required uint32 weight = 31; required uint32 weight = 31;
} }
message ResearchCost {
oneof research_cost_type {
uint32 xp = 1;
ResearchCostSeasonalTokens seasonal_tokens = 2;
}
}
message ResearchCostSeasonalTokens {
required uint32 season = 1;
required uint32 tokens = 2;
}
enum TankPriceType { enum TankPriceType {
TANK_PRICE_TYPE_CREDITS = 0; TANK_PRICE_TYPE_CREDITS = 0;
TANK_PRICE_TYPE_GOLD = 1; TANK_PRICE_TYPE_GOLD = 1;
@@ -56,7 +68,7 @@ message TrackDefinition {
required string name = 3; required string name = 3;
required uint32 weight = 4; required uint32 weight = 4;
required float traverse_speed = 5; required float traverse_speed = 5;
optional uint32 xp = 6; optional ResearchCost research_cost = 6;
required float dispersion_move = 7; required float dispersion_move = 7;
required float dispersion_traverse = 8; required float dispersion_traverse = 8;
required float resistance_hard = 9; required float resistance_hard = 9;
@@ -68,7 +80,7 @@ message TrackDefinition {
message EngineDefinition { message EngineDefinition {
required uint32 id = 1; required uint32 id = 1;
required string name = 2; required string name = 2;
optional uint32 xp = 3; optional ResearchCost research_cost = 3;
required Tier tier = 4; required Tier tier = 4;
required float fire_chance = 5; required float fire_chance = 5;
required uint32 power = 6; required uint32 power = 6;
@@ -81,7 +93,7 @@ message TurretDefinition {
required uint32 health = 2; required uint32 health = 2;
required uint32 view_range = 3; required uint32 view_range = 3;
required float traverse_speed = 4; required float traverse_speed = 4;
optional uint32 xp = 5; optional ResearchCost research_cost = 5;
required string name = 6; required string name = 6;
required Tier tier = 7; required Tier tier = 7;
required uint32 weight = 8; required uint32 weight = 8;
@@ -131,7 +143,7 @@ message GunDefinitionAutoReloaderProperties {
message GunDefinitionBase { message GunDefinitionBase {
required uint32 id = 1; required uint32 id = 1;
required float rotation_speed = 2; required float rotation_speed = 2;
optional uint32 xp = 3; optional ResearchCost research_cost = 3;
required uint32 weight = 4; required uint32 weight = 4;
required string name = 5; required string name = 5;
required Tier tier = 6; required Tier tier = 6;
@@ -151,13 +163,13 @@ message ShellDefinition {
required uint32 velocity = 3; required uint32 velocity = 3;
required uint32 armor_damage = 4; required uint32 armor_damage = 4;
required uint32 module_damage = 5; required uint32 module_damage = 5;
required uint32 caliber = 6; required float caliber = 6;
required string icon = 7; required string icon = 7;
required ShellPenetration penetration = 8; required ShellPenetration penetration = 8;
required ShellType type = 9; required ShellType type = 9;
required uint32 normalization = 10; optional float normalization = 10;
required uint32 ricochet = 11; optional float ricochet = 11;
required uint32 explosion_radius = 12; optional float explosion_radius = 12;
} }
enum ShellType { enum ShellType {
@@ -168,8 +180,8 @@ enum ShellType {
} }
message ShellPenetration { message ShellPenetration {
required uint32 near = 1; required float near = 1;
required uint32 far = 2; required float far = 2;
} }
message Unlock { message Unlock {
@@ -1,15 +1,16 @@
import { tankDefinitions, Tier } from '../blitzkit/tankDefinitions'; import { fetchTankDefinitions } from '../blitzkit';
import { Tier } from '../protos';
import { BlitzStats } from './compositeStats/constants'; import { BlitzStats } from './compositeStats/constants';
export async function getTierWeights( export async function getTierWeights(
stats: Record<number, BlitzStats>, stats: Record<number, BlitzStats>,
order: number[] = Object.keys(stats).map(parseInt), order: number[] = Object.keys(stats).map(parseInt),
) { ) {
const awaitedTankDefinitions = await tankDefinitions; const tankDefinitions = await fetchTankDefinitions();
const tierWeights: TierWeightsRecord = {}; const tierWeights: TierWeightsRecord = {};
order.forEach((id) => { order.forEach((id) => {
const entry = awaitedTankDefinitions[id]; const entry = tankDefinitions.tanks[id];
if (!entry) return; if (!entry) return;
if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0; if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0;
+154 -117
View File
@@ -12,11 +12,13 @@ import {
EquipmentSlot, EquipmentSlot,
GameDefinitions, GameDefinitions,
GunDefinition, GunDefinition,
GunDefinitionBase,
MapDefinitions, MapDefinitions,
ModelDefinitions, ModelDefinitions,
ModuleType, ModuleType,
Provision, Provision,
ProvisionDefinitions, ProvisionDefinitions,
ResearchCost,
ShellType, ShellType,
SkillDefinitions, SkillDefinitions,
TankClass, TankClass,
@@ -41,6 +43,24 @@ import { DATA } from './constants';
import { Avatar } from './skillIcons'; import { Avatar } from './skillIcons';
import { TankParameters } from './tankIcons'; import { TankParameters } from './tankIcons';
function parseResearchCost(raw: number | string) {
if (typeof raw === 'number') {
return {
researchCostType: { $case: 'xp', value: raw },
} satisfies ResearchCost;
} else {
return {
researchCostType: {
$case: 'seasonalTokens',
value: {
season: Number(/prx_season_(\d+):\d+/.exec(raw)![1]),
tokens: Number(/prx_season_\d+:(\d+)/.exec(raw)![1]),
},
},
} satisfies ResearchCost;
}
}
type BlitzTankFilterDefinitionCategory = 'clip'; type BlitzTankFilterDefinitionCategory = 'clip';
const blitzTankFilterDefinitionCategoryToBlitzkit: Record< const blitzTankFilterDefinitionCategoryToBlitzkit: Record<
BlitzTankFilterDefinitionCategory, BlitzTankFilterDefinitionCategory,
@@ -75,8 +95,8 @@ type ShellDefinitionsList = Record<
kind: ShellKind; kind: ShellKind;
caliber: number; caliber: number;
damage: { armor: number; devices: number }; damage: { armor: number; devices: number };
normalizationAngle: number; normalizationAngle?: number;
ricochetAngle: number; ricochetAngle?: number;
explosionRadius?: number; explosionRadius?: number;
} }
> & { > & {
@@ -593,7 +613,7 @@ export async function definitions() {
`${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`, `${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`,
); );
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml.dvpl`); const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml.dvpl`);
const tankXps = new Map<number, number>(); const tankXps = new Map<number, ResearchCost>();
const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>( const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>(
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml.dvpl`, `${DATA}/XML/item_defs/vehicles/common/camouflages.xml.dvpl`,
); );
@@ -726,10 +746,10 @@ export async function definitions() {
for (const tankKey in tankList.root) { for (const tankKey in tankList.root) {
if (botPattern.test(tankKey)) continue; if (botPattern.test(tankKey)) continue;
const gunXps = new Map<number, number>(); const gunXps = new Map<number, ResearchCost>();
const turretXps = new Map<number, number>(); const turretXps = new Map<number, ResearchCost>();
const engineXps = new Map<number, number>(); const engineXps = new Map<number, ResearchCost>();
const trackXps = new Map<number, number>(); const trackXps = new Map<number, ResearchCost>();
const tank = tankList.root[tankKey]; const tank = tankList.root[tankKey];
let tankPrice: TankPrice; let tankPrice: TankPrice;
const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>( const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>(
@@ -794,6 +814,7 @@ export async function definitions() {
({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey, ({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey,
); );
if (index === -1) { if (index === -1) {
if (crewKey === '#text') return;
entry = { entry = {
type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType], type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType],
count: 1, count: 1,
@@ -808,12 +829,9 @@ export async function definitions() {
entry.count++; entry.count++;
if (value !== '') { if (value !== '') {
entry.substitute = value entry.substitute = value.split(/\n| /).map((member) => {
.split('\n') return blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType];
.map( });
(member) =>
blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType],
);
} }
} else { } else {
if (entry.count === undefined) { if (entry.count === undefined) {
@@ -1091,14 +1109,9 @@ export async function definitions() {
? 'autoReloader' ? 'autoReloader'
: 'autoLoader' : 'autoLoader'
: 'regular'; : 'regular';
const gunReload = // const gunReload = gun.reloadTime;
gunType === 'autoReloader' // const shellReloads =
? gun.pumpGunReloadTimes!.split(' ').map(Number) const gunClipCount = gunType === 'regular' ? 1 : gun.clip!.count;
: gun.reloadTime;
const gunClipCount =
gunType === 'regular' ? undefined : gun.clip!.count;
const gunIntraClip =
gunType === 'regular' ? undefined : 60 / gun.clip!.rate;
const front = gun.extraPitchLimits?.front const front = gun.extraPitchLimits?.front
? gun.extraPitchLimits.front.split(' ').map(Number) ? gun.extraPitchLimits.front.split(' ').map(Number)
: undefined; : undefined;
@@ -1144,32 +1157,62 @@ export async function definitions() {
} }
}); });
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({ const base = {
id: gunId, id: gunId,
weight: gunListEntry.weight, weight: gunListEntry.weight,
rotationSpeed: gunListEntry.rotationSpeed, rotationSpeed: gunListEntry.rotationSpeed,
name: gunName, name: gunName,
tier: gunListEntry.level as Tier, tier: gunListEntry.level as Tier,
shells: [], shells: [],
type: gunType,
reload: gunReload,
count: gunClipCount,
intraClip: gunIntraClip,
camouflageLoss: camouflageLoss:
typeof gun.invisibilityFactorAtShot === 'number' typeof gun.invisibilityFactorAtShot === 'number'
? gun.invisibilityFactorAtShot ? gun.invisibilityFactorAtShot
: gun.invisibilityFactorAtShot.at(-1)!, : gun.invisibilityFactorAtShot.at(-1)!,
aimTime: gun.aimingTime ?? gunListEntry.aimingTime, aimTime: gun.aimingTime ?? gunListEntry.aimingTime,
dispersion: { dispersionBase:
base: gun.shotDispersionRadius ?? gunListEntry.shotDispersionRadius,
gun.shotDispersionRadius ?? dispersionDamaged: shotDispersionFactors.whileGunDamaged,
gunListEntry.shotDispersionRadius, dispersionShot: shotDispersionFactors.afterShot,
damaged: shotDispersionFactors.whileGunDamaged, dispersionTraverse: shotDispersionFactors.turretRotation,
shot: shotDispersionFactors.afterShot,
traverse: shotDispersionFactors.turretRotation,
},
unlocks: resolveUnlocks(gun.unlocks), unlocks: resolveUnlocks(gun.unlocks),
} as GunDefinition); } satisfies GunDefinitionBase;
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({
gunType:
gunType === 'regular'
? {
$case: 'regular',
value: {
base,
extension: { reload: gun.reloadTime },
},
}
: gunType === 'autoReloader'
? {
$case: 'autoReloader',
value: {
base,
extension: {
intraClip: 60 / gun.clip!.rate,
shellCount: gunClipCount,
shellReloads: gun
.pumpGunReloadTimes!.split(' ')
.map(Number),
},
},
}
: {
$case: 'autoLoader',
value: {
base,
extension: {
intraClip: 60 / gun.clip!.rate,
clipReload: gun.reloadTime,
shellCount: gunClipCount,
},
},
},
} satisfies GunDefinition);
modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = { modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = {
armor: gunArmor, armor: gunArmor,
@@ -1214,33 +1257,27 @@ export async function definitions() {
.filter((penetrationString) => penetrationString !== '') .filter((penetrationString) => penetrationString !== '')
.map(Number); .map(Number);
Object.values( tankDefinitions.tanks[tankId].turrets[turretIndex].guns[
tankDefinitions.tanks[tankId].turrets[turretIndex].guns[ gunIndex
gunIndex ].gunType!.value.base.shells.push({
], id: shellId,
).forEach((gun) => { name: shellName,
gun.shells.push({ velocity: gunShellEntry.speed,
id: shellId, armorDamage: shell.damage.armor,
name: shellName, moduleDamage: shell.damage.devices,
speed: gunShellEntry.speed, caliber: shell.caliber,
damage: { normalization: shell.normalizationAngle,
armor: shell.damage.armor, ricochet: shell.ricochetAngle,
module: shell.damage.devices, type: blitzShellKindToBlitzkit[shell.kind],
}, explosionRadius:
caliber: shell.caliber, shell.kind === 'HIGH_EXPLOSIVE'
normalization: shell.normalizationAngle, ? (shell.explosionRadius ?? 0)
ricochet: shell.ricochetAngle, : undefined,
type: blitzShellKindToBlitzkit[shell.kind], icon: shell.icon,
explosionRadius: penetration: {
shell.kind === 'HIGH_EXPLOSIVE' near: penetrationRaw[0],
? (shell.explosionRadius ?? 0) far: penetrationRaw[1],
: undefined, },
icon: shell.icon,
penetration:
penetrationRaw[0] === penetrationRaw[1]
? penetrationRaw[0]
: [penetrationRaw[0], penetrationRaw[1]],
});
}); });
}); });
}); });
@@ -1258,7 +1295,7 @@ export async function definitions() {
const currentTank = tankDefinitions.tanks[tankId]; const currentTank = tankDefinitions.tanks[tankId];
const successorId = toUniqueId(nation, tankListEntry.id); const successorId = toUniqueId(nation, tankListEntry.id);
tankXps.set(successorId, vehicle.cost as number); tankXps.set(successorId, parseResearchCost(vehicle.cost));
if (currentTank.successors === undefined) { if (currentTank.successors === undefined) {
currentTank.successors = []; currentTank.successors = [];
@@ -1272,7 +1309,7 @@ export async function definitions() {
case 'gun': { case 'gun': {
gunXps.set( gunXps.set(
toUniqueId(nation, gunList.root.ids[vehicle['#text']]), toUniqueId(nation, gunList.root.ids[vehicle['#text']]),
vehicle.cost as number, parseResearchCost(vehicle.cost),
); );
break; break;
} }
@@ -1280,7 +1317,7 @@ export async function definitions() {
case 'turret': { case 'turret': {
turretXps.set( turretXps.set(
toUniqueId(nation, turretList.root.ids[vehicle['#text']]), toUniqueId(nation, turretList.root.ids[vehicle['#text']]),
vehicle.cost as number, parseResearchCost(vehicle.cost),
); );
break; break;
} }
@@ -1288,7 +1325,7 @@ export async function definitions() {
case 'engine': { case 'engine': {
engineXps.set( engineXps.set(
toUniqueId(nation, enginesList.root.ids[vehicle['#text']]), toUniqueId(nation, enginesList.root.ids[vehicle['#text']]),
vehicle.cost as number, parseResearchCost(vehicle.cost),
); );
break; break;
} }
@@ -1296,7 +1333,7 @@ export async function definitions() {
case 'chassis': { case 'chassis': {
trackXps.set( trackXps.set(
toUniqueId(nation, chassisList.root.ids[vehicle['#text']]), toUniqueId(nation, chassisList.root.ids[vehicle['#text']]),
vehicle.cost as number, parseResearchCost(vehicle.cost),
); );
break; break;
} }
@@ -1307,31 +1344,31 @@ export async function definitions() {
Object.values(tankDefinitions.tanks[tankId].turrets).forEach( Object.values(tankDefinitions.tanks[tankId].turrets).forEach(
(turret) => { (turret) => {
turret.xp = turretXps.get(turret.id); turret.researchCost = turretXps.get(turret.id);
Object.values(turret.guns).forEach((gunRaw) => { Object.values(turret.guns).forEach((gunRaw) => {
Object.values(gunRaw).forEach((gun) => { gunRaw.gunType!.value.base.researchCost = gunXps.get(
gun.xp = gunXps.get(gun.id); gunRaw.gunType!.value.base.id,
}); );
}); });
}, },
); );
Object.values(tankDefinitions.tanks[tankId].engines).forEach( Object.values(tankDefinitions.tanks[tankId].engines).forEach(
(engine) => { (engine) => {
engine.xp = engineXps.get(engine.id); engine.researchCost = engineXps.get(engine.id);
}, },
); );
Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => { Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => {
track.xp = trackXps.get(track.id); track.researchCost = trackXps.get(track.id);
}); });
} }
}), }),
); );
Object.values(tankDefinitions.tanks).forEach((tank) => { Object.values(tankDefinitions.tanks).forEach((tank) => {
tank.xp = tankXps.get(tank.id); tank.researchCost = tankXps.get(tank.id);
}); });
Object.values(tankDefinitions.tanks).forEach((tank) => { Object.values(tankDefinitions.tanks).forEach((tank) => {
@@ -1357,18 +1394,18 @@ export async function definitions() {
([optionalDeviceSlotKey, optionalDeviceSlotEntry]) => { ([optionalDeviceSlotKey, optionalDeviceSlotEntry]) => {
if (optionalDeviceSlotKey === 'emptyPreset') return; if (optionalDeviceSlotKey === 'emptyPreset') return;
equipmentDefinitions.presets[optionalDeviceSlotKey].slots = Object.values( equipmentDefinitions.presets[optionalDeviceSlotKey] = {
optionalDeviceSlotEntry, slots: Object.values(optionalDeviceSlotEntry)
) .map((level) => {
.map((level) => { return Object.values(level).map((options) => {
return Object.values(level).map((options) => { return {
return { left: optionalDevices.root[options.device0].id,
left: optionalDevices.root[options.device0].id, right: optionalDevices.root[options.device1].id,
right: optionalDevices.root[options.device1].id, } satisfies EquipmentSlot;
} satisfies EquipmentSlot; });
}); })
}) .flat(),
.flat(); };
}, },
); );
@@ -1400,17 +1437,17 @@ export async function definitions() {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'tiers', $case: 'tiers',
tiers: { min: includeRaw.minLevel, max: includeRaw.maxLevel }, value: { min: includeRaw.minLevel, max: includeRaw.maxLevel },
}, },
}); });
} else if ('name' in includeRaw) { } else if ('name' in includeRaw) {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'ids', $case: 'ids',
ids: { value: {
ids: includeRaw.name ids: includeRaw.name.split(/ +/).map((key) => {
.split(' ') return tankStringIdMap[key];
.map((key) => tankStringIdMap[key]), }),
}, },
}, },
}); });
@@ -1420,7 +1457,7 @@ export async function definitions() {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'nations', $case: 'nations',
nations: { value: {
nations: consumable.vehicleFilter.include.nations.split(' '), nations: consumable.vehicleFilter.include.nations.split(' '),
}, },
}, },
@@ -1435,10 +1472,10 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'ids', $case: 'ids',
ids: { value: {
ids: excludeRaw.name ids: excludeRaw.name.split(/ +/).map((key) => {
.split(' ') return tankStringIdMap[key];
.map((key) => tankStringIdMap[key]), }),
}, },
}, },
}); });
@@ -1446,7 +1483,7 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'categories', $case: 'categories',
categories: { value: {
categories: excludeRaw.extendedTags categories: excludeRaw.extendedTags
.split(' ') .split(' ')
.map( .map(
@@ -1464,7 +1501,7 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'nations', $case: 'nations',
nations: { value: {
nations: consumable.vehicleFilter.exclude.nations.split(' '), nations: consumable.vehicleFilter.exclude.nations.split(' '),
}, },
}, },
@@ -1500,7 +1537,7 @@ export async function definitions() {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'tiers', $case: 'tiers',
tiers: { value: {
min: includeRaw.minLevel, min: includeRaw.minLevel,
max: includeRaw.maxLevel, max: includeRaw.maxLevel,
}, },
@@ -1510,10 +1547,10 @@ export async function definitions() {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'ids', $case: 'ids',
ids: { value: {
ids: includeRaw.name ids: includeRaw.name.split(/ +/).map((key) => {
.split(' ') return tankStringIdMap[key];
.map((key) => tankStringIdMap[key]), }),
}, },
}, },
}); });
@@ -1523,7 +1560,7 @@ export async function definitions() {
entry.include.push({ entry.include.push({
filterType: { filterType: {
$case: 'nations', $case: 'nations',
nations: { value: {
nations: provision.vehicleFilter.include.nations.split(' '), nations: provision.vehicleFilter.include.nations.split(' '),
}, },
}, },
@@ -1538,9 +1575,9 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'ids', $case: 'ids',
ids: { value: {
ids: excludeRaw.name ids: excludeRaw.name
.split(' ') .split(/ +/)
.map((key) => tankStringIdMap[key]), .map((key) => tankStringIdMap[key]),
}, },
}, },
@@ -1549,7 +1586,7 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'categories', $case: 'categories',
categories: { value: {
categories: excludeRaw.extendedTags categories: excludeRaw.extendedTags
.split(' ') .split(' ')
.map( .map(
@@ -1567,7 +1604,7 @@ export async function definitions() {
entry.exclude!.push({ entry.exclude!.push({
filterType: { filterType: {
$case: 'nations', $case: 'nations',
nations: { value: {
nations: provision.vehicleFilter.exclude.nations.split(' '), nations: provision.vehicleFilter.exclude.nations.split(' '),
}, },
}, },
@@ -1617,47 +1654,47 @@ export async function definitions() {
{ {
content: encodePB64(GameDefinitions, gameDefinitions), content: encodePB64(GameDefinitions, gameDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/game.cdon.lz4', path: 'definitions/game.pb',
}, },
{ {
content: encodePB64(TankDefinitions, tankDefinitions), content: encodePB64(TankDefinitions, tankDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/tanks.cdon.lz4', path: 'definitions/tanks.pb',
}, },
{ {
content: encodePB64(ModelDefinitions, modelDefinitions), content: encodePB64(ModelDefinitions, modelDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/models.cdon.lz4', path: 'definitions/models.pb',
}, },
{ {
content: encodePB64(EquipmentDefinitions, equipmentDefinitions), content: encodePB64(EquipmentDefinitions, equipmentDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/equipment.cdon.lz4', path: 'definitions/equipment.pb',
}, },
{ {
content: encodePB64(ConsumableDefinitions, consumableDefinitions), content: encodePB64(ConsumableDefinitions, consumableDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/consumables.cdon.lz4', path: 'definitions/consumables.pb',
}, },
{ {
content: encodePB64(ProvisionDefinitions, provisionDefinitions), content: encodePB64(ProvisionDefinitions, provisionDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/provisions.cdon.lz4', path: 'definitions/provisions.pb',
}, },
{ {
content: encodePB64(SkillDefinitions, skillDefinitions), content: encodePB64(SkillDefinitions, skillDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/skills.cdon.lz4', path: 'definitions/skills.pb',
}, },
{ {
content: encodePB64(MapDefinitions, mapDefinitions), content: encodePB64(MapDefinitions, mapDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/maps.cdon.lz4', path: 'definitions/maps.pb',
}, },
{ {
content: encodePB64(CamouflageDefinitions, camouflageDefinitions), content: encodePB64(CamouflageDefinitions, camouflageDefinitions),
encoding: 'base64', encoding: 'base64',
path: 'definitions/camouflages.cdon.lz4', path: 'definitions/camouflages.pb',
}, },
]); ]);
} }
+2 -1
View File
@@ -48,7 +48,8 @@ for (const method of methods) {
try { try {
await method(); await method();
} catch (error) { } catch (error) {
console.warn(`Failed method ${method.name}; skipping...`, error); console.warn(`Failed method ${method.name}; skipping...`);
console.error(error);
} }
} }
} }
@@ -9,9 +9,7 @@ export async function moduleIcons() {
console.log('Building module icons...'); console.log('Building module icons...');
const changes = await Promise.all( const changes = await Promise.all(
( (await readdir(`${DATA}/Gfx/UI/ModulesTechTree`))
await readdir(`${DATA}/Gfx/UI/ModulesTechTree`)
)
.filter( .filter(
(file) => (file) =>
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'), !file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
+3 -3
View File
@@ -1,12 +1,12 @@
import { tankDefinitions } from '@blitzkit/core'; import { fetchTankDefinitions } from '@blitzkit/core';
// random vercel bug forces require import // random vercel bug forces require import
const { writeFileSync } = require('fs'); const { writeFileSync } = require('fs');
console.log('Building sitemap...'); console.log('Building sitemap...');
const awaitedTankDefinitions = await tankDefinitions; const tankDefinitions = await fetchTankDefinitions();
const values = Object.values(awaitedTankDefinitions); const values = Object.values(tankDefinitions);
const txt = values const txt = values
.map((tank) => `https://blitzkit.app/tools/tankopedia/${tank.id}/`) .map((tank) => `https://blitzkit.app/tools/tankopedia/${tank.id}/`)
.join('\n'); .join('\n');
@@ -1,22 +1,9 @@
import { import { createDefaultSkills } from '@blitzkit/core';
createDefaultSkills,
equipmentDefinitions,
modelDefinitions,
provisionDefinitions,
skillDefinitions,
tankDefinitions,
} from '@blitzkit/core';
import { PlusIcon } from '@radix-ui/react-icons'; import { PlusIcon } from '@radix-ui/react-icons';
import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes'; import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { use, useCallback, useEffect, useMemo, useState } from 'react'; import { use, useCallback, useEffect, useMemo, useState } from 'react';
import { CompareControls } from '../../../../../website/src/components/Controls';
import { DamageWarning } from '../../../../../website/src/components/DamageWarning';
import { PageWrapper } from '../../../components/PageWrapper';
import { tankCharacteristics } from '../../../core/blitzkit/tankCharacteristics';
import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember';
import * as CompareEphemeral from '../../../stores/compareEphemeral'; import * as CompareEphemeral from '../../../stores/compareEphemeral';
import { CompareTable } from '../../../../../website/src/components/Compare/CompareTable';
export default function Page() { export default function Page() {
const pathname = usePathname(); const pathname = usePathname();
@@ -1,11 +1,6 @@
import { averageDefinitionsArray, tankDefinitions } from '@blitzkit/core';
import { Table } from '@radix-ui/themes'; import { Table } from '@radix-ui/themes';
import { times } from 'lodash-es'; import { times } from 'lodash-es';
import { Suspense, use, useEffect, useMemo, useState } from 'react'; import { Suspense, use, useEffect, useMemo, useState } from 'react';
import { filterTank } from '../../../../core/blitzkit/filterTank';
import * as TankFilters from '../../../../stores/tankFilters';
import * as TankPerformancePersistent from '../../../../stores/tankPerformancePersistent';
import * as TankPerformanceSort from '../../../../stores/tankPerformanceSort';
import { RowLoader } from './RowLoader'; import { RowLoader } from './RowLoader';
import { TankRow } from './TankRow'; import { TankRow } from './TankRow';
import { Total } from './Total'; import { Total } from './Total';
@@ -1,9 +1,7 @@
import { import {
averageDefinitionsArray,
formatCompact, formatCompact,
TANK_CLASSES, TANK_CLASSES,
TankClass, TankClass,
tankDefinitions,
Tier, Tier,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
@@ -6,8 +6,8 @@ import {
STAT_NAMES, STAT_NAMES,
Stat, Stat,
UNLOCALIZED_REGION_NAMES_SHORT, UNLOCALIZED_REGION_NAMES_SHORT,
blitzStarsTankAverages,
deltaTankStats, deltaTankStats,
fetchTankDefinitions,
generateStats, generateStats,
getAccountInfo, getAccountInfo,
getTankStats, getTankStats,
@@ -15,7 +15,6 @@ import {
prettifyStats, prettifyStats,
searchPlayersAcrossRegions, searchPlayersAcrossRegions,
sumBlitzStarsStats, sumBlitzStarsStats,
tankDefinitions,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { import {
ArrowDownIcon, ArrowDownIcon,
@@ -37,9 +36,8 @@ import {
} from '@radix-ui/themes'; } from '@radix-ui/themes';
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
import { use, useEffect, useMemo, useRef, useState } from 'react'; import { use, useEffect, useMemo, useRef, useState } from 'react';
import { PageWrapper } from '../../../components/PageWrapper';
import { TankRowHeaderCell } from '../../../components/TankRowHeaderCell'; const awaitedTankDefinitions = await fetchTankDefinitions();
import * as Session from '../../../stores/session';
export default function Page({ export default function Page({
searchParams, searchParams,
@@ -47,8 +45,6 @@ export default function Page({
searchParams: { id?: string }; searchParams: { id?: string };
}) { }) {
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedTankAvearges = use(blitzStarsTankAverages);
const [showSearch, setShowSearch] = useState(false); const [showSearch, setShowSearch] = useState(false);
const [searching, setSearching] = useState(false); const [searching, setSearching] = useState(false);
const [searchResults, setSearchResults] = useState<AccountListWithServer>([]); const [searchResults, setSearchResults] = useState<AccountListWithServer>([]);
@@ -1,21 +1,21 @@
import { import {
modelDefinitions, fetchModelDefinitions,
provisionDefinitions, fetchTankDefinitions,
tankDefinitions,
tankDefinitionsArray,
tankIcon, tankIcon,
TIER_ROMAN_NUMERALS, TIER_ROMAN_NUMERALS,
} from '@blitzkit/core'; } from '@blitzkit/core';
import strings from '@blitzkit/core/lang/en-US.json'; import strings from '@blitzkit/core/lang/en-US.json';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import * as Duel from '../../../../stores/duel';
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
export async function generateStaticParams() { export async function generateStaticParams() {
const tanks = await tankDefinitionsArray; const tankDefinitions = await fetchTankDefinitions();
const tanks = Object.values(tankDefinitions.tanks);
return tanks.map((tank) => ({ id: `${tank.id}` })); return tanks.map((tank) => ({ id: `${tank.id}` }));
} }
const tankDefinitions = await fetchTankDefinitions();
const definitions = await fetchModelDefinitions();
export default async function Layout({ export default async function Layout({
children, children,
params, params,
@@ -24,11 +24,9 @@ export default async function Layout({
params: { id: string }; params: { id: string };
}) { }) {
const id = Number(params.id); const id = Number(params.id);
const awaitedTankDefinitions = await tankDefinitions; const tankModelDefinition = definitions[id];
const awaitedModelDefinitions = await modelDefinitions;
const tankModelDefinition = awaitedModelDefinitions[id];
const awaitedProvisionDefinitions = await provisionDefinitions; const awaitedProvisionDefinitions = await provisionDefinitions;
const tank = awaitedTankDefinitions[id]; const tank = tankDefinitions[id];
const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${ const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${
(strings.common.nations_adjectives as Record<string, string>)[tank.nation] (strings.common.nations_adjectives as Record<string, string>)[tank.nation]
} ${strings.common.tank_class_short[tank.class]}`; } ${strings.common.tank_class_short[tank.class]}`;
@@ -38,7 +36,7 @@ export default async function Layout({
<TankopediaEphemeral.Provider data={tankModelDefinition}> <TankopediaEphemeral.Provider data={tankModelDefinition}>
<Duel.Provider <Duel.Provider
data={{ data={{
tank: awaitedTankDefinitions[id], tank: tankDefinitions[id],
provisionDefinitions: awaitedProvisionDefinitions, provisionDefinitions: awaitedProvisionDefinitions,
}} }}
> >
+1 -12
View File
@@ -7,16 +7,5 @@
} }
] ]
}, },
"include": [ "include": ["src/**/*", ".next/types/**/*.ts"]
"src/**/*",
".next/types/**/*.ts",
"../website/src/components/TankSearch/components/FilterControl.tsx",
"../website/src/components/Tankopedia/HeroSection/index.tsx",
"../website/src/components/Tankopedia/GameModeSection.tsx",
"../website/src/components/Tankopedia/CharacteristicsSection.tsx",
"../website/src/components/Tankopedia/MetaSection",
"../website/src/components/Tankopedia/HistorySection.tsx",
"../website/src/components/Tankopedia/CalloutsSection.tsx",
"../website/src/components/Tankopedia/ShotDisplaySection.tsx"
, "../website/src/components/Tankopedia/CharacteristicsSection/components/ConfigurationChildWrapper.tsx", "../website/src/components/Tankopedia/VideoSection.tsx", "../website/src/components/DamageWarning.tsx", "../website/src/components/Controls.tsx", "../website/src/components/Compare/CompareTable.tsx" ]
} }
@@ -1,20 +1,19 @@
import { compositeStatsKeys, tankDefinitionsArray } from '@blitzkit/core'; import { compositeStatsKeys, fetchTankDefinitions } from '@blitzkit/core';
import strings from '@blitzkit/core/lang/en-US.json'; import strings from '@blitzkit/core/lang/en-US.json';
import { use } from 'react'; import { breakdownConfig } from '../../constants/embeds';
import { import { useEmbedStateCurry } from '../../stores/embedState/utilities';
BreakdownEmbedCard, import { BreakdownEmbedCard, BreakdownEmbedWrapper } from '../TanksEmbed';
BreakdownEmbedWrapper,
} from '../../../../components/TanksEmbed';
import { breakdownConfig } from '../../../../../../website/src/constants/embeds';
import { useEmbedStateCurry } from '../../../../stores/embedState/utilities';
export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({ export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
label: strings.common.composite_stats[value], label: strings.common.composite_stats[value],
value, value,
})); }));
const tanks = await fetchTankDefinitions().then((tanks) =>
Object.values(tanks.tanks),
);
export function BreakdownPreview() { export function BreakdownPreview() {
const tanks = use(tankDefinitionsArray);
const { useState } = useEmbedStateCurry<typeof breakdownConfig>(); const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
return ( return (
@@ -6,7 +6,6 @@ import {
fetchTankNames, fetchTankNames,
normalizeBoundingBox, normalizeBoundingBox,
resolveDpm, resolveDpm,
resolveGun,
unionBoundingBox, unionBoundingBox,
type TankDefinition, type TankDefinition,
} from '@blitzkit/core'; } from '@blitzkit/core';
@@ -115,10 +114,10 @@ export const TankSearch = memo<TankSearchProps>(
sorted = filtered.sort( sorted = filtered.sort(
(a, b) => (a, b) =>
a.camouflageStill * a.camouflageStill *
resolveGun(a.turrets.at(-1)!.guns.at(-1)!).gun! a.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base
.camouflageLoss - .camouflageLoss -
b.camouflageStill * b.camouflageStill *
resolveGun(b.turrets.at(-1)!.guns.at(-1)!).gun! b.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base
.camouflageLoss, .camouflageLoss,
); );
break; break;
@@ -143,8 +142,8 @@ export const TankSearch = memo<TankSearchProps>(
bTurretModelDefinition.boundingBox, bTurretModelDefinition.boundingBox,
), ),
); );
const aVolume = aSize[0] * aSize[1] * aSize[2]; const aVolume = aSize.x * aSize.y * aSize.z;
const bVolume = bSize[0] * bSize[1] * bSize[2]; const bVolume = bSize.x * bSize.y * bSize.z;
return aVolume - bVolume; return aVolume - bVolume;
}); });
@@ -170,8 +169,8 @@ export const TankSearch = memo<TankSearchProps>(
bTurretModelDefinition.boundingBox, bTurretModelDefinition.boundingBox,
), ),
); );
const aLength = Math.max(aSize[0], aSize[1], aSize[2]); const aLength = Math.max(aSize.x, aSize.y, aSize.z);
const bLength = Math.max(bSize[0], bSize[1], bSize[2]); const bLength = Math.max(bSize.x, bSize.y, bSize.z);
return aLength - bLength; return aLength - bLength;
}); });
@@ -1,4 +1,4 @@
import { resolveNearPenetration, tankDefinitions } from '@blitzkit/core'; import { fetchTankDefinitions, TankType } from '@blitzkit/core';
import { Box, Flex, Heading, Text } from '@radix-ui/themes'; import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import { Suspense, useEffect, useMemo, useRef } from 'react'; import { Suspense, useEffect, useMemo, useRef } from 'react';
import { NAVBAR_HEIGHT } from '../../../constants/navbar'; import { NAVBAR_HEIGHT } from '../../../constants/navbar';
@@ -11,7 +11,7 @@ import { Options } from './components/Options';
import { TankSandbox } from './components/TankSandbox'; import { TankSandbox } from './components/TankSandbox';
import { TankSandboxLoader } from './components/TankSandboxLoader'; import { TankSandboxLoader } from './components/TankSandboxLoader';
const awaitedTankDefinitions = await tankDefinitions; const tankDefinitions = await fetchTankDefinitions();
export function HeroSection() { export function HeroSection() {
const canvas = useRef<HTMLCanvasElement>(null); const canvas = useRef<HTMLCanvasElement>(null);
@@ -20,13 +20,13 @@ export function HeroSection() {
const Icon = classIcons[protagonist.class]; const Icon = classIcons[protagonist.class];
// const [dummyLoader, setDummyLoader] = useState(true); // const [dummyLoader, setDummyLoader] = useState(true);
const treeColor = const treeColor =
protagonist.treeType === 'collector' protagonist.type === TankType.COLLECTOR
? 'blue' ? 'blue'
: protagonist.treeType === 'premium' : protagonist.type === TankType.PREMIUM
? 'amber' ? 'amber'
: undefined; : undefined;
const thicknessRange = useMemo(() => { const thicknessRange = useMemo(() => {
const entries = Object.values(awaitedTankDefinitions); const entries = Object.values(tankDefinitions.tanks);
const filtered = entries.filter( const filtered = entries.filter(
(thisTank) => thisTank.tier === protagonist.tier, (thisTank) => thisTank.tier === protagonist.tier,
); );
@@ -34,9 +34,8 @@ export function HeroSection() {
(filtered.reduce((accumulator, thisTank) => { (filtered.reduce((accumulator, thisTank) => {
return ( return (
accumulator + accumulator +
resolveNearPenetration( thisTank.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base.shells[0]
thisTank.turrets.at(-1)!.guns.at(-1)!.shells[0].penetration, .penetration.near
)
); );
}, 0) / }, 0) /
filtered.length) * filtered.length) *
+2 -2
View File
@@ -1,10 +1,10 @@
import type { CompositeStatsKey } from '@blitzkit/core'; import { type CompositeStatsKey } from '@blitzkit/core';
import { grayA, grayDark, grayDarkA } from '@radix-ui/colors'; import { grayA, grayDark, grayDarkA } from '@radix-ui/colors';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { import {
BreakdownPreview, BreakdownPreview,
compositeStatsKeysOptions, compositeStatsKeysOptions,
} from '../../../website-legacy/src/app/tools/embed/configurations/breakdown'; } from '../components/Embeds/breakdown';
import type { import type {
EmbedConfig, EmbedConfig,
ExtractEmbedConfigTypes, ExtractEmbedConfigTypes,