mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22f42117df | ||
|
|
788edf5bdf | ||
|
|
d0170d53e4 | ||
|
|
ae5e38139b | ||
|
|
e38713f365 | ||
|
|
5903b8130b | ||
|
|
179ce62a55 | ||
|
|
a2f1593a0e | ||
|
|
6305db7ad6 | ||
|
|
5082e1b82b |
No files matched your search
+1
-1
@@ -22,7 +22,7 @@ depots
|
||||
public/sitemap*
|
||||
/firebase.json
|
||||
target
|
||||
# packages/core/src/protos/*.ts
|
||||
# *.ts
|
||||
/.vercel
|
||||
/.astro
|
||||
.vercel
|
||||
|
||||
Vendored
+6
@@ -33,6 +33,7 @@
|
||||
"blitzkit",
|
||||
"blitzrinth",
|
||||
"blitzstars",
|
||||
"bufbuild",
|
||||
"cacheable",
|
||||
"Callouts",
|
||||
"Camo",
|
||||
@@ -75,6 +76,7 @@
|
||||
"dxgi",
|
||||
"echarts",
|
||||
"Everytime",
|
||||
"FABLEGEAR",
|
||||
"FASTNAME",
|
||||
"flexdirection",
|
||||
"FOURCC",
|
||||
@@ -108,6 +110,7 @@
|
||||
"Maddoxkkm",
|
||||
"malum",
|
||||
"mantlets",
|
||||
"MECHA",
|
||||
"metallicness",
|
||||
"metalness",
|
||||
"minitelrose",
|
||||
@@ -145,9 +148,11 @@
|
||||
"POSITIVEY",
|
||||
"POSITIVEZ",
|
||||
"precompute",
|
||||
"PROGRESSTON",
|
||||
"Promisable",
|
||||
"proto",
|
||||
"protobuf",
|
||||
"protoc",
|
||||
"protos",
|
||||
"Pyogenics",
|
||||
"ratingleaderboard",
|
||||
@@ -203,6 +208,7 @@
|
||||
"vitepress",
|
||||
"Vovko",
|
||||
"wargaming",
|
||||
"WARHAMMER",
|
||||
"webp",
|
||||
"whitespaces",
|
||||
"WHSS",
|
||||
|
||||
+11
-2
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "blitzkit",
|
||||
"name": "@blitzkit",
|
||||
"private": true,
|
||||
"version": "1.27.11",
|
||||
"description": "🎉 Tools for everything World of Tanks Blitz",
|
||||
"type": "module",
|
||||
"types": "./types.d.ts",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
"packages/*",
|
||||
"submodules/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build:assets": "cd packages/scripts && bun run build:assets",
|
||||
@@ -41,15 +42,23 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"googleapis": "^144.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"protobufjs": "^7.5.2",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"quicklime": "^1.2.0",
|
||||
"sharp": "^0.33.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/react": "^4.3.0",
|
||||
"@types/bun": "latest",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/react": "^19.1.5",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@types/node": "^22.14.1",
|
||||
"astro": "^5.8.0",
|
||||
"prettier": "^3.5.3",
|
||||
"prisma": "^6.6.0",
|
||||
"typescript": "^5.8.3"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"satori": "^0.10.14",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"discord.js": "^14.16.3",
|
||||
"react": "^18.3.1",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"fuzzysort": "^2.0.4",
|
||||
"bepaint": "^0.1.0-beta.3",
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*", "../core/src/blitzkit/supportedLocales.ts", "../i18n/src/unwrapper.ts"]
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"../core/src/blitzkit/supportedLocales.ts",
|
||||
"../i18n/src/unwrapper.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "../../"
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"dependencies": {
|
||||
"@blitzkit/closed": "workspace:*",
|
||||
"@octokit/plugin-throttling": "^8.2.0",
|
||||
"@octokit/rest": "^20.1.1",
|
||||
"@prisma/client": "^6.6.0",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { CatalogItem } from '@protos/blitz_items';
|
||||
import { Any } from '@protos/google/protobuf/any';
|
||||
import { MessageFns } from '../protos';
|
||||
|
||||
export class CatalogItemAccessor {
|
||||
private components: Record<string, Any> = {};
|
||||
|
||||
constructor(item: CatalogItem) {
|
||||
for (const component of item.components) {
|
||||
if (
|
||||
component.value === undefined ||
|
||||
component.value.component === undefined
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.components[component.key] = component.value.component;
|
||||
}
|
||||
}
|
||||
|
||||
get<Type>(Message: MessageFns<Type>, component: string) {
|
||||
if (component in this.components) {
|
||||
return Message.decode(this.components[component].value);
|
||||
}
|
||||
|
||||
throw new Error(`Unknown component: ${component}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export function entityName(entity: string) {
|
||||
const [_, ...name] = entity.split('.');
|
||||
return name.join('.');
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
export * from './canSplash';
|
||||
export * from './catalogItemAccessor';
|
||||
export * from './clans';
|
||||
export * from './classes';
|
||||
export * from './constants';
|
||||
export * from './entityName';
|
||||
export * from './equipmentPrice';
|
||||
export * from './fetchBlitz';
|
||||
export * from './fetchGlossary';
|
||||
@@ -18,6 +20,7 @@ export * from './getTankStats';
|
||||
export * from './idToRegion';
|
||||
export * from './isOnGoingRatingSeason';
|
||||
export * from './isValidBlitzId';
|
||||
export * from './metadataAccessor';
|
||||
export * from './nations';
|
||||
export * from './normalizeExtra';
|
||||
export * from './normalizeIds';
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { CatalogItem } from '@protos/blitz_items';
|
||||
import { Metadata } from '@protos/blitz_metadata';
|
||||
import { CatalogItemAccessor } from './catalogItemAccessor';
|
||||
|
||||
export class UnpackedMetadataAccessor {
|
||||
private items: Record<string, CatalogItemAccessor> = {};
|
||||
|
||||
constructor(metadata: Metadata) {
|
||||
for (const item of metadata.catalog_items) {
|
||||
if (item.catalog_id in this.items) {
|
||||
throw new Error(`Duplicate catalog ID: ${item.catalog_id}`);
|
||||
}
|
||||
|
||||
this.items[item.catalog_id] = new CatalogItemAccessor(item);
|
||||
}
|
||||
}
|
||||
|
||||
get(item: string) {
|
||||
if (item in this.items) return this.items[item];
|
||||
|
||||
throw new Error(`Unknown catalog ID: ${item}`);
|
||||
}
|
||||
}
|
||||
|
||||
export class DiscreteMetadataAccessor {
|
||||
constructor(private base: string) {}
|
||||
|
||||
async get(item: string) {
|
||||
const response = await fetch(`${this.base}/${item}.pb`);
|
||||
|
||||
if (!response.ok) throw new Error(`Unknown catalog ID: ${item}`);
|
||||
|
||||
const buffer = await response.arrayBuffer();
|
||||
const catalogItem = CatalogItem.decode(new Uint8Array(buffer));
|
||||
|
||||
return new CatalogItemAccessor(catalogItem);
|
||||
}
|
||||
}
|
||||
@@ -46,4 +46,5 @@ export * from './gallery';
|
||||
export * from './metaSortTank';
|
||||
export * from './popularTanks';
|
||||
export * from './romanize';
|
||||
export * from './slugify';
|
||||
export * from './youtubers';
|
||||
@@ -0,0 +1,16 @@
|
||||
import { deburr } from 'lodash-es';
|
||||
|
||||
const nonAlphanumericRegex = /[^a-z0-9]/g;
|
||||
const multipleDashesRegex = /--+/g;
|
||||
const trailingDashRegex = /-$/g;
|
||||
const leadingDashRegex = /^-/g;
|
||||
|
||||
export function slugify(name: string) {
|
||||
let slug = deburr(name).toLowerCase();
|
||||
slug = slug.replaceAll(nonAlphanumericRegex, '-');
|
||||
slug = slug.replaceAll(multipleDashesRegex, '-');
|
||||
slug = slug.replaceAll(trailingDashRegex, '');
|
||||
slug = slug.replaceAll(leadingDashRegex, '');
|
||||
|
||||
return slug;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { deburr } from 'lodash-es';
|
||||
import { SUPPORTED_LOCALES } from '../../../i18n/src/strings';
|
||||
import { I18nString } from '../protos';
|
||||
import { fetchCamouflageDefinitions } from './camouflageDefinitions';
|
||||
import { fetchTankDefinitions } from './tankDefinitions';
|
||||
@@ -26,8 +26,8 @@ export async function fetchTankNames() {
|
||||
searchableNameDeburr,
|
||||
camouflages: tank.camouflages
|
||||
?.map((id) =>
|
||||
SUPPORTED_LOCALES.map(
|
||||
(locale) =>
|
||||
locales.supported.map(
|
||||
({ locale }) =>
|
||||
camouflageDefinitions.camouflages[id]?.name.locales[locale],
|
||||
),
|
||||
)
|
||||
@@ -42,9 +42,11 @@ export async function fetchTankNames() {
|
||||
}
|
||||
|
||||
export const SEARCH_KEYS = [
|
||||
...SUPPORTED_LOCALES.map((locale) => [
|
||||
`searchableName.locales.${locale}`,
|
||||
`searchableNameDeburr.locales.${locale}`,
|
||||
]).flat(),
|
||||
...locales.supported
|
||||
.map(({ locale }) => [
|
||||
`searchableName.locales.${locale}`,
|
||||
`searchableNameDeburr.locales.${locale}`,
|
||||
])
|
||||
.flat(),
|
||||
'camouflages',
|
||||
];
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/average_definitions.proto
|
||||
// source: average_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message CamouflageDefinitions {
|
||||
map<uint32, Camouflage> camouflages = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/camouflage_definitions.proto
|
||||
// source: camouflage_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message ConsumableDefinitions {
|
||||
map<uint32, Consumable> consumables = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/consumable_definitions.proto
|
||||
// source: consumable_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
@@ -11,14 +11,14 @@ import { createBaseI18nString, I18nString } from "./i18n";
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
export enum ConsumableTankCategoryFilterCategory {
|
||||
CLIP = 0,
|
||||
CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP = 0,
|
||||
}
|
||||
|
||||
export function consumableTankCategoryFilterCategoryFromJSON(object: any): ConsumableTankCategoryFilterCategory {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP":
|
||||
return ConsumableTankCategoryFilterCategory.CLIP;
|
||||
return ConsumableTankCategoryFilterCategory.CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP;
|
||||
default:
|
||||
throw new globalThis.Error(
|
||||
"Unrecognized enum value " + object + " for enum ConsumableTankCategoryFilterCategory",
|
||||
@@ -28,7 +28,7 @@ export function consumableTankCategoryFilterCategoryFromJSON(object: any): Consu
|
||||
|
||||
export function consumableTankCategoryFilterCategoryToJSON(object: ConsumableTankCategoryFilterCategory): string {
|
||||
switch (object) {
|
||||
case ConsumableTankCategoryFilterCategory.CLIP:
|
||||
case ConsumableTankCategoryFilterCategory.CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP:
|
||||
return "CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP";
|
||||
default:
|
||||
throw new globalThis.Error(
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message EquipmentDefinitions {
|
||||
map<string, EquipmentPreset> presets = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/equipment_definitions.proto
|
||||
// source: equipment_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message Gallery {
|
||||
repeated Avatar avatars = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/gallery.proto
|
||||
// source: gallery.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message GameDefinitions {
|
||||
required string version = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/game_definitions.proto
|
||||
// source: game_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/i18n.proto
|
||||
// source: i18n.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message MapDefinitions {
|
||||
map<int32, MapDefinition> maps = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/map_definitions.proto
|
||||
// source: map_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/model_definitions.proto
|
||||
// source: model_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/popular_tanks.proto
|
||||
// source: popular_tanks.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,8 +2,8 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/consumable_definitions.proto";
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "consumable_definitions.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message ProvisionDefinitions {
|
||||
map<uint32, Provision> provisions = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/provision_definitions.proto
|
||||
// source: provision_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/rating_leaderboard.proto
|
||||
// source: rating_leaderboard.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/reviews.proto
|
||||
// source: reviews.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/skill_definitions.proto
|
||||
// source: skill_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
package blitzkit;
|
||||
|
||||
import "packages/core/src/protos/i18n.proto";
|
||||
import "i18n.proto";
|
||||
|
||||
message TankDefinitions {
|
||||
map<uint32, TankDefinition> tanks = 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.2
|
||||
// protoc v5.28.2
|
||||
// source: packages/core/src/protos/tank_definitions.proto
|
||||
// source: tank_definitions.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
@@ -11,18 +11,18 @@ import { createBaseI18nString, I18nString } from "./i18n";
|
||||
export const protobufPackage = "blitzkit";
|
||||
|
||||
export enum TankPriceType {
|
||||
CREDITS = 0,
|
||||
GOLD = 1,
|
||||
TANK_PRICE_TYPE_CREDITS = 0,
|
||||
TANK_PRICE_TYPE_GOLD = 1,
|
||||
}
|
||||
|
||||
export function tankPriceTypeFromJSON(object: any): TankPriceType {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "TANK_PRICE_TYPE_CREDITS":
|
||||
return TankPriceType.CREDITS;
|
||||
return TankPriceType.TANK_PRICE_TYPE_CREDITS;
|
||||
case 1:
|
||||
case "TANK_PRICE_TYPE_GOLD":
|
||||
return TankPriceType.GOLD;
|
||||
return TankPriceType.TANK_PRICE_TYPE_GOLD;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankPriceType");
|
||||
}
|
||||
@@ -30,9 +30,9 @@ export function tankPriceTypeFromJSON(object: any): TankPriceType {
|
||||
|
||||
export function tankPriceTypeToJSON(object: TankPriceType): string {
|
||||
switch (object) {
|
||||
case TankPriceType.CREDITS:
|
||||
case TankPriceType.TANK_PRICE_TYPE_CREDITS:
|
||||
return "TANK_PRICE_TYPE_CREDITS";
|
||||
case TankPriceType.GOLD:
|
||||
case TankPriceType.TANK_PRICE_TYPE_GOLD:
|
||||
return "TANK_PRICE_TYPE_GOLD";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankPriceType");
|
||||
@@ -40,26 +40,26 @@ export function tankPriceTypeToJSON(object: TankPriceType): string {
|
||||
}
|
||||
|
||||
export enum ShellType {
|
||||
AP = 0,
|
||||
APCR = 1,
|
||||
HEAT = 2,
|
||||
HE = 3,
|
||||
SHELL_TYPE_AP = 0,
|
||||
SHELL_TYPE_APCR = 1,
|
||||
SHELL_TYPE_HEAT = 2,
|
||||
SHELL_TYPE_HE = 3,
|
||||
}
|
||||
|
||||
export function shellTypeFromJSON(object: any): ShellType {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "SHELL_TYPE_AP":
|
||||
return ShellType.AP;
|
||||
return ShellType.SHELL_TYPE_AP;
|
||||
case 1:
|
||||
case "SHELL_TYPE_APCR":
|
||||
return ShellType.APCR;
|
||||
return ShellType.SHELL_TYPE_APCR;
|
||||
case 2:
|
||||
case "SHELL_TYPE_HEAT":
|
||||
return ShellType.HEAT;
|
||||
return ShellType.SHELL_TYPE_HEAT;
|
||||
case 3:
|
||||
case "SHELL_TYPE_HE":
|
||||
return ShellType.HE;
|
||||
return ShellType.SHELL_TYPE_HE;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum ShellType");
|
||||
}
|
||||
@@ -67,13 +67,13 @@ export function shellTypeFromJSON(object: any): ShellType {
|
||||
|
||||
export function shellTypeToJSON(object: ShellType): string {
|
||||
switch (object) {
|
||||
case ShellType.AP:
|
||||
case ShellType.SHELL_TYPE_AP:
|
||||
return "SHELL_TYPE_AP";
|
||||
case ShellType.APCR:
|
||||
case ShellType.SHELL_TYPE_APCR:
|
||||
return "SHELL_TYPE_APCR";
|
||||
case ShellType.HEAT:
|
||||
case ShellType.SHELL_TYPE_HEAT:
|
||||
return "SHELL_TYPE_HEAT";
|
||||
case ShellType.HE:
|
||||
case ShellType.SHELL_TYPE_HE:
|
||||
return "SHELL_TYPE_HE";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum ShellType");
|
||||
@@ -81,30 +81,30 @@ export function shellTypeToJSON(object: ShellType): string {
|
||||
}
|
||||
|
||||
export enum ModuleType {
|
||||
VEHICLE = 0,
|
||||
ENGINE = 1,
|
||||
TRACKS = 2,
|
||||
TURRET = 3,
|
||||
GUN = 4,
|
||||
MODULE_TYPE_VEHICLE = 0,
|
||||
MODULE_TYPE_ENGINE = 1,
|
||||
MODULE_TYPE_TRACKS = 2,
|
||||
MODULE_TYPE_TURRET = 3,
|
||||
MODULE_TYPE_GUN = 4,
|
||||
}
|
||||
|
||||
export function moduleTypeFromJSON(object: any): ModuleType {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "MODULE_TYPE_VEHICLE":
|
||||
return ModuleType.VEHICLE;
|
||||
return ModuleType.MODULE_TYPE_VEHICLE;
|
||||
case 1:
|
||||
case "MODULE_TYPE_ENGINE":
|
||||
return ModuleType.ENGINE;
|
||||
return ModuleType.MODULE_TYPE_ENGINE;
|
||||
case 2:
|
||||
case "MODULE_TYPE_TRACKS":
|
||||
return ModuleType.TRACKS;
|
||||
return ModuleType.MODULE_TYPE_TRACKS;
|
||||
case 3:
|
||||
case "MODULE_TYPE_TURRET":
|
||||
return ModuleType.TURRET;
|
||||
return ModuleType.MODULE_TYPE_TURRET;
|
||||
case 4:
|
||||
case "MODULE_TYPE_GUN":
|
||||
return ModuleType.GUN;
|
||||
return ModuleType.MODULE_TYPE_GUN;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum ModuleType");
|
||||
}
|
||||
@@ -112,15 +112,15 @@ export function moduleTypeFromJSON(object: any): ModuleType {
|
||||
|
||||
export function moduleTypeToJSON(object: ModuleType): string {
|
||||
switch (object) {
|
||||
case ModuleType.VEHICLE:
|
||||
case ModuleType.MODULE_TYPE_VEHICLE:
|
||||
return "MODULE_TYPE_VEHICLE";
|
||||
case ModuleType.ENGINE:
|
||||
case ModuleType.MODULE_TYPE_ENGINE:
|
||||
return "MODULE_TYPE_ENGINE";
|
||||
case ModuleType.TRACKS:
|
||||
case ModuleType.MODULE_TYPE_TRACKS:
|
||||
return "MODULE_TYPE_TRACKS";
|
||||
case ModuleType.TURRET:
|
||||
case ModuleType.MODULE_TYPE_TURRET:
|
||||
return "MODULE_TYPE_TURRET";
|
||||
case ModuleType.GUN:
|
||||
case ModuleType.MODULE_TYPE_GUN:
|
||||
return "MODULE_TYPE_GUN";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum ModuleType");
|
||||
@@ -128,26 +128,26 @@ export function moduleTypeToJSON(object: ModuleType): string {
|
||||
}
|
||||
|
||||
export enum TankClass {
|
||||
LIGHT = 0,
|
||||
MEDIUM = 1,
|
||||
HEAVY = 2,
|
||||
TANK_DESTROYER = 3,
|
||||
TANK_CLASS_LIGHT = 0,
|
||||
TANK_CLASS_MEDIUM = 1,
|
||||
TANK_CLASS_HEAVY = 2,
|
||||
TANK_CLASS_TANK_DESTROYER = 3,
|
||||
}
|
||||
|
||||
export function tankClassFromJSON(object: any): TankClass {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "TANK_CLASS_LIGHT":
|
||||
return TankClass.LIGHT;
|
||||
return TankClass.TANK_CLASS_LIGHT;
|
||||
case 1:
|
||||
case "TANK_CLASS_MEDIUM":
|
||||
return TankClass.MEDIUM;
|
||||
return TankClass.TANK_CLASS_MEDIUM;
|
||||
case 2:
|
||||
case "TANK_CLASS_HEAVY":
|
||||
return TankClass.HEAVY;
|
||||
return TankClass.TANK_CLASS_HEAVY;
|
||||
case 3:
|
||||
case "TANK_CLASS_TANK_DESTROYER":
|
||||
return TankClass.TANK_DESTROYER;
|
||||
return TankClass.TANK_CLASS_TANK_DESTROYER;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankClass");
|
||||
}
|
||||
@@ -155,13 +155,13 @@ export function tankClassFromJSON(object: any): TankClass {
|
||||
|
||||
export function tankClassToJSON(object: TankClass): string {
|
||||
switch (object) {
|
||||
case TankClass.LIGHT:
|
||||
case TankClass.TANK_CLASS_LIGHT:
|
||||
return "TANK_CLASS_LIGHT";
|
||||
case TankClass.MEDIUM:
|
||||
case TankClass.TANK_CLASS_MEDIUM:
|
||||
return "TANK_CLASS_MEDIUM";
|
||||
case TankClass.HEAVY:
|
||||
case TankClass.TANK_CLASS_HEAVY:
|
||||
return "TANK_CLASS_HEAVY";
|
||||
case TankClass.TANK_DESTROYER:
|
||||
case TankClass.TANK_CLASS_TANK_DESTROYER:
|
||||
return "TANK_CLASS_TANK_DESTROYER";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankClass");
|
||||
@@ -169,22 +169,22 @@ export function tankClassToJSON(object: TankClass): string {
|
||||
}
|
||||
|
||||
export enum TankType {
|
||||
RESEARCHABLE = 0,
|
||||
PREMIUM = 1,
|
||||
COLLECTOR = 2,
|
||||
TANK_TYPE_RESEARCHABLE = 0,
|
||||
TANK_TYPE_PREMIUM = 1,
|
||||
TANK_TYPE_COLLECTOR = 2,
|
||||
}
|
||||
|
||||
export function tankTypeFromJSON(object: any): TankType {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "TANK_TYPE_RESEARCHABLE":
|
||||
return TankType.RESEARCHABLE;
|
||||
return TankType.TANK_TYPE_RESEARCHABLE;
|
||||
case 1:
|
||||
case "TANK_TYPE_PREMIUM":
|
||||
return TankType.PREMIUM;
|
||||
return TankType.TANK_TYPE_PREMIUM;
|
||||
case 2:
|
||||
case "TANK_TYPE_COLLECTOR":
|
||||
return TankType.COLLECTOR;
|
||||
return TankType.TANK_TYPE_COLLECTOR;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankType");
|
||||
}
|
||||
@@ -192,11 +192,11 @@ export function tankTypeFromJSON(object: any): TankType {
|
||||
|
||||
export function tankTypeToJSON(object: TankType): string {
|
||||
switch (object) {
|
||||
case TankType.RESEARCHABLE:
|
||||
case TankType.TANK_TYPE_RESEARCHABLE:
|
||||
return "TANK_TYPE_RESEARCHABLE";
|
||||
case TankType.PREMIUM:
|
||||
case TankType.TANK_TYPE_PREMIUM:
|
||||
return "TANK_TYPE_PREMIUM";
|
||||
case TankType.COLLECTOR:
|
||||
case TankType.TANK_TYPE_COLLECTOR:
|
||||
return "TANK_TYPE_COLLECTOR";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankType");
|
||||
@@ -204,30 +204,30 @@ export function tankTypeToJSON(object: TankType): string {
|
||||
}
|
||||
|
||||
export enum CrewType {
|
||||
COMMANDER = 0,
|
||||
RADIOMAN = 1,
|
||||
GUNNER = 2,
|
||||
DRIVER = 3,
|
||||
LOADER = 4,
|
||||
CREW_TYPE_COMMANDER = 0,
|
||||
CREW_TYPE_RADIOMAN = 1,
|
||||
CREW_TYPE_GUNNER = 2,
|
||||
CREW_TYPE_DRIVER = 3,
|
||||
CREW_TYPE_LOADER = 4,
|
||||
}
|
||||
|
||||
export function crewTypeFromJSON(object: any): CrewType {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "CREW_TYPE_COMMANDER":
|
||||
return CrewType.COMMANDER;
|
||||
return CrewType.CREW_TYPE_COMMANDER;
|
||||
case 1:
|
||||
case "CREW_TYPE_RADIOMAN":
|
||||
return CrewType.RADIOMAN;
|
||||
return CrewType.CREW_TYPE_RADIOMAN;
|
||||
case 2:
|
||||
case "CREW_TYPE_GUNNER":
|
||||
return CrewType.GUNNER;
|
||||
return CrewType.CREW_TYPE_GUNNER;
|
||||
case 3:
|
||||
case "CREW_TYPE_DRIVER":
|
||||
return CrewType.DRIVER;
|
||||
return CrewType.CREW_TYPE_DRIVER;
|
||||
case 4:
|
||||
case "CREW_TYPE_LOADER":
|
||||
return CrewType.LOADER;
|
||||
return CrewType.CREW_TYPE_LOADER;
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType");
|
||||
}
|
||||
@@ -235,15 +235,15 @@ export function crewTypeFromJSON(object: any): CrewType {
|
||||
|
||||
export function crewTypeToJSON(object: CrewType): string {
|
||||
switch (object) {
|
||||
case CrewType.COMMANDER:
|
||||
case CrewType.CREW_TYPE_COMMANDER:
|
||||
return "CREW_TYPE_COMMANDER";
|
||||
case CrewType.RADIOMAN:
|
||||
case CrewType.CREW_TYPE_RADIOMAN:
|
||||
return "CREW_TYPE_RADIOMAN";
|
||||
case CrewType.GUNNER:
|
||||
case CrewType.CREW_TYPE_GUNNER:
|
||||
return "CREW_TYPE_GUNNER";
|
||||
case CrewType.DRIVER:
|
||||
case CrewType.CREW_TYPE_DRIVER:
|
||||
return "CREW_TYPE_DRIVER";
|
||||
case CrewType.LOADER:
|
||||
case CrewType.CREW_TYPE_LOADER:
|
||||
return "CREW_TYPE_LOADER";
|
||||
default:
|
||||
throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType");
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*", "../i18n/src/strings.ts"]
|
||||
"include": ["src/**/*", "../i18n/src/strings.ts"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "../../"
|
||||
}
|
||||
}
|
||||
@@ -1,89 +1,8 @@
|
||||
import { merge } from 'ts-deepmerge';
|
||||
import en from '../strings/en.json';
|
||||
import es from '../strings/es.json';
|
||||
import fr from '../strings/fr.json';
|
||||
import ja from '../strings/ja.json';
|
||||
import pl from '../strings/pl.json';
|
||||
import pt from '../strings/pt.json';
|
||||
import ru from '../strings/ru.json';
|
||||
import uk from '../strings/uk.json';
|
||||
import zh from '../strings/zh.json';
|
||||
import type en from '../strings/en.json';
|
||||
|
||||
export type BlitzKitStrings = typeof en;
|
||||
|
||||
const stringsRaw = { en, es, fr, ja, pl, pt, ru, uk, zh };
|
||||
|
||||
export const SUPPORTED_LOCALES = Object.keys(stringsRaw) as SupportedLocale[];
|
||||
|
||||
export const DEFAULT_LOCALE = SUPPORTED_LOCALES[0];
|
||||
|
||||
function redact(string: string) {
|
||||
const matches = [...string.matchAll(/%s\d+/g)];
|
||||
const characters = string
|
||||
.split('')
|
||||
.map((char) => (char === ' ' ? ' ' : '█')) as string[];
|
||||
|
||||
matches.forEach((match) => {
|
||||
const start = match.index;
|
||||
const matchText = match[0];
|
||||
for (let i = 0; i < matchText.length; i++) {
|
||||
characters[start + i] = matchText[i];
|
||||
}
|
||||
});
|
||||
|
||||
return characters.join('');
|
||||
}
|
||||
|
||||
function nuke(object: TranslationTree) {
|
||||
for (const key in object) {
|
||||
const typedKey = key as keyof typeof object;
|
||||
|
||||
if (typeof object[typedKey] === 'string') {
|
||||
const value = object[typedKey];
|
||||
object[typedKey] = redact(value as string);
|
||||
} else nuke(object[typedKey] as TranslationTree);
|
||||
}
|
||||
}
|
||||
|
||||
const stringsPartial: Partial<Record<SupportedLocale, TranslationTree>> = {};
|
||||
|
||||
for (const locale in stringsRaw) {
|
||||
if (locale === DEFAULT_LOCALE) {
|
||||
stringsPartial[DEFAULT_LOCALE] = stringsRaw[DEFAULT_LOCALE];
|
||||
continue;
|
||||
}
|
||||
|
||||
const localeStrings = stringsRaw[locale as SupportedLocale];
|
||||
stringsPartial[locale as SupportedLocale] = merge(
|
||||
stringsRaw[DEFAULT_LOCALE],
|
||||
localeStrings,
|
||||
);
|
||||
|
||||
if (import.meta.env.PUBLIC_DEBUG_MISSING_I18N === 'true') {
|
||||
nuke(stringsPartial[locale as SupportedLocale]!);
|
||||
}
|
||||
}
|
||||
|
||||
export const STRINGS = stringsPartial as Record<
|
||||
SupportedLocale,
|
||||
BlitzKitStrings
|
||||
>;
|
||||
|
||||
export type SupportedLocale = keyof typeof stringsRaw;
|
||||
|
||||
export const SUPPORTED_LOCALE_BLITZ_MAP: Record<SupportedLocale, string> = {
|
||||
en: 'en',
|
||||
es: 'es',
|
||||
fr: 'fr',
|
||||
ja: 'ja',
|
||||
pt: 'pt',
|
||||
ru: 'ru',
|
||||
uk: 'uk',
|
||||
zh: 'zh-Hans',
|
||||
pl: 'pl',
|
||||
};
|
||||
|
||||
export const SUPPORTED_LOCALE_FLAGS: Record<SupportedLocale, string> = {
|
||||
export const SUPPORTED_LOCALE_FLAGS: Record<string, string> = {
|
||||
en: '🇺🇸',
|
||||
es: '🇪🇸',
|
||||
fr: '🇫🇷',
|
||||
@@ -94,7 +13,3 @@ export const SUPPORTED_LOCALE_FLAGS: Record<SupportedLocale, string> = {
|
||||
zh: '🇨🇳',
|
||||
pl: '🇵🇱',
|
||||
};
|
||||
|
||||
export type TranslationTree = { [key: string]: TranslationNode };
|
||||
|
||||
export type TranslationNode = string | TranslationTree;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { I18nString } from '@blitzkit/core';
|
||||
import { DEFAULT_LOCALE } from './strings';
|
||||
import locales from '../locales.json' with { type: 'json' };
|
||||
|
||||
export function unwrapper(locale: string) {
|
||||
return function (i18nString: I18nString) {
|
||||
@@ -7,6 +7,6 @@ export function unwrapper(locale: string) {
|
||||
return i18nString.locales[locale];
|
||||
}
|
||||
|
||||
return i18nString.locales[DEFAULT_LOCALE];
|
||||
return i18nString.locales[locales.default];
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,18 @@
|
||||
},
|
||||
|
||||
"common": {
|
||||
"tiers": {
|
||||
"0": "Unknown tier",
|
||||
"1": "I",
|
||||
"2": "II",
|
||||
"3": "III",
|
||||
"4": "IV",
|
||||
"5": "V",
|
||||
"6": "VI",
|
||||
"7": "VII",
|
||||
"8": "Vintage"
|
||||
},
|
||||
|
||||
"units": {
|
||||
"m": "%s1m",
|
||||
"mm": "%s1mm",
|
||||
@@ -86,15 +98,44 @@
|
||||
},
|
||||
|
||||
"nations": {
|
||||
"ussr": "U.S.S.R.",
|
||||
"germany": "Germany",
|
||||
"usa": "U.S.A.",
|
||||
"china": "China",
|
||||
"uk": "U.K.",
|
||||
"france": "France",
|
||||
"japan": "Japan",
|
||||
"european": "European Nation",
|
||||
"other": "Hybrid Nation"
|
||||
"0": "Unknown nation",
|
||||
"1": "U.S.S.R.",
|
||||
"2": "Germany",
|
||||
"3": "U.S.A.",
|
||||
"4": "China",
|
||||
"5": "France",
|
||||
"6": "U.K.",
|
||||
"7": "Japan",
|
||||
"8": "Europe",
|
||||
"9": "Poland",
|
||||
"10": "Australia",
|
||||
"11": "Canada",
|
||||
"12": "Italy",
|
||||
"13": "Finland",
|
||||
"14": "Czech",
|
||||
"15": "Hybrid Nation",
|
||||
"16": "GDR",
|
||||
"17": "Ireland",
|
||||
"18": "Scotland",
|
||||
"19": "Sweden",
|
||||
"20": "Argo Coalition",
|
||||
"21": "Titan Lab",
|
||||
"22": "Defender",
|
||||
"23": "Progresston",
|
||||
"24": "Wasteland",
|
||||
"25": "Hunters Moon",
|
||||
"26": "Cold Front",
|
||||
"27": "The Explorer",
|
||||
"28": "Fablegear",
|
||||
"29": "Outlaws",
|
||||
"30": "GUP",
|
||||
"31": "Dune",
|
||||
"32": "Terminator",
|
||||
"33": "Warhammer",
|
||||
"34": "Valkirya Chronicles",
|
||||
"35": "Mecha",
|
||||
"36": "TMNT",
|
||||
"37": "Star Trek"
|
||||
},
|
||||
|
||||
"nations_adjectives": {
|
||||
@@ -109,6 +150,14 @@
|
||||
"other": "Hybrid"
|
||||
},
|
||||
|
||||
"tank_class": {
|
||||
"0": "Unknown Class",
|
||||
"1": "Heavy",
|
||||
"2": "Light",
|
||||
"3": "Medium",
|
||||
"4": "Tank destroyer"
|
||||
},
|
||||
|
||||
"tank_class_short": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Light",
|
||||
@@ -133,10 +182,10 @@
|
||||
},
|
||||
|
||||
"tree_type": {
|
||||
"-1": "unrecognized",
|
||||
"0": "Tech tree",
|
||||
"1": "Premium",
|
||||
"2": "Collector"
|
||||
"0": "Unknown tree type",
|
||||
"1": "Common",
|
||||
"2": "Premium",
|
||||
"3": "Collector"
|
||||
},
|
||||
|
||||
"regions": {
|
||||
@@ -988,6 +1037,8 @@
|
||||
},
|
||||
|
||||
"meta": {
|
||||
"compensation": "Compensation",
|
||||
"free": "Free",
|
||||
"back": "Back",
|
||||
"compare": "Compare",
|
||||
"swap": {
|
||||
@@ -1001,11 +1052,12 @@
|
||||
"class": "Class",
|
||||
"tier": "Tier",
|
||||
"type": "Type",
|
||||
"dev_id": "DEV: ID",
|
||||
"id": "ID",
|
||||
"purchase": "Purchase price",
|
||||
"restoration": "Restoration price",
|
||||
"sale": "Sale price",
|
||||
"research": "Research XP"
|
||||
"set": "Set",
|
||||
"price": "Price"
|
||||
},
|
||||
|
||||
"tech_tree": {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { mkdir, writeFile } from 'fs/promises';
|
||||
import { parse as parsePath } from 'path';
|
||||
import ProgressBar from 'progress';
|
||||
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
||||
import { dvp } from '../../../submodules/blitzkit-closed/src/dvp';
|
||||
import { dvp } from '../../../submodules/blitzkit-closed/src/dava/dvp';
|
||||
import { readStringDVPL } from '../src/core/blitz/readStringDVPL';
|
||||
import { DATA } from './buildAssets/constants';
|
||||
import { readYAMLDVPL } from './core/blitz/readYAMLDVPL';
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
ResearchCost,
|
||||
ShellType,
|
||||
SkillDefinitions,
|
||||
slugify,
|
||||
TankClass,
|
||||
TankDefinitions,
|
||||
TankPrice,
|
||||
@@ -37,7 +38,6 @@ import {
|
||||
SUPPORTED_LOCALES,
|
||||
} from '@blitzkit/i18n';
|
||||
import { readdir } from 'fs/promises';
|
||||
import { deburr } from 'lodash-es';
|
||||
import { parse as parsePath } from 'path';
|
||||
import { Vector3Tuple } from 'three';
|
||||
import { parse as parseYaml } from 'yaml';
|
||||
@@ -49,11 +49,6 @@ import { DATA } from './constants';
|
||||
import { Avatar } from './skillIcons';
|
||||
import { TankParameters } from './tankIcons';
|
||||
|
||||
const nonAlphanumericRegex = /[^a-z0-9]/g;
|
||||
const multipleDashesRegex = /--+/g;
|
||||
const trailingDashRegex = /-$/g;
|
||||
const leadingDashRegex = /^-/g;
|
||||
|
||||
const nationSlugDiscriminators = {
|
||||
china: 'cn',
|
||||
european: 'eu',
|
||||
@@ -740,12 +735,7 @@ export async function definitions() {
|
||||
? getString(tank.shortUserString)
|
||||
: undefined) ?? getString(tank.userString)
|
||||
).locales.en;
|
||||
|
||||
let slug = deburr(name).toLowerCase();
|
||||
slug = slug.replaceAll(nonAlphanumericRegex, '-');
|
||||
slug = slug.replaceAll(multipleDashesRegex, '-');
|
||||
slug = slug.replaceAll(trailingDashRegex, '');
|
||||
slug = slug.replaceAll(leadingDashRegex, '');
|
||||
const slug = slugify(name);
|
||||
|
||||
idToNation[tankId] = nation;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Avatar, encodePBBuffer, fetchGlossary, Gallery } from '@blitzkit/core';
|
||||
import locales from '@blitzkit/i18n/locales.json';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { extname } from 'path';
|
||||
import ProgressBar from 'progress';
|
||||
import { commitAssets } from '../core/github/commitAssets';
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { exec as execSync } from 'child_process';
|
||||
import { existsSync } from 'fs';
|
||||
import { readdir, rm, writeFile } from 'fs/promises';
|
||||
import { chunk } from 'lodash-es';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const ROOT = 'packages/core/src/protos';
|
||||
|
||||
const exec = promisify(execSync);
|
||||
|
||||
let executableFileExtension: string;
|
||||
@@ -15,33 +14,42 @@ if (existsSync('node_modules/.bin/protoc-gen-ts_proto.exe')) {
|
||||
executableFileExtension = '';
|
||||
}
|
||||
|
||||
const filesRaw = await readdir(`${ROOT}`);
|
||||
await Promise.all(
|
||||
filesRaw.map(async (file) => {
|
||||
if (!file.endsWith('.proto')) {
|
||||
await rm(`${ROOT}/${file}`);
|
||||
}
|
||||
}),
|
||||
);
|
||||
await compile('packages/core/src/protos');
|
||||
await compile('submodules/blitzkit-closed/src/protos');
|
||||
|
||||
const files = filesRaw.filter((file) => file.endsWith('.proto'));
|
||||
const args = [
|
||||
`--plugin=./node_modules/.bin/protoc-gen-ts_proto${executableFileExtension}`,
|
||||
'--ts_proto_opt=esModuleInterop=true',
|
||||
'--ts_proto_opt=oneof=unions-value',
|
||||
'--ts_proto_opt=removeEnumPrefix=true',
|
||||
'--ts_proto_opt=unrecognizedEnum=false',
|
||||
'--ts_proto_opt=snakeToCamel=false',
|
||||
'--ts_proto_out=.',
|
||||
...files.map((file) => `${ROOT}/${file}`),
|
||||
];
|
||||
async function compile(root: string) {
|
||||
const filesRaw = await readdir(root);
|
||||
|
||||
await exec(`protoc ${args.join(' ')}`);
|
||||
await writeFile(
|
||||
`${ROOT}/index.ts`,
|
||||
'// @ts-nocheck\n' +
|
||||
files
|
||||
.map((file) => file.replace('.proto', ''))
|
||||
.map((file) => `export * from './${file}.ts';`)
|
||||
.join('\n'),
|
||||
);
|
||||
for (const file of filesRaw) {
|
||||
if (!file.endsWith('.ts')) continue;
|
||||
await rm(`${root}/${file}`);
|
||||
}
|
||||
|
||||
const allFiles = filesRaw.filter((file) => file.endsWith('.proto'));
|
||||
|
||||
for (const files of chunk(allFiles, 32)) {
|
||||
const args = [
|
||||
`-I=${root}`,
|
||||
`--plugin=./node_modules/.bin/protoc-gen-ts_proto${executableFileExtension}`,
|
||||
'--ts_proto_opt=esModuleInterop=true',
|
||||
'--ts_proto_opt=oneof=unions-value',
|
||||
// '--ts_proto_opt=removeEnumPrefix=true',
|
||||
'--ts_proto_opt=unrecognizedEnum=false',
|
||||
'--ts_proto_opt=snakeToCamel=false',
|
||||
`--ts_proto_out=${root}`,
|
||||
...files.map((file) => `${root}/${file}`),
|
||||
];
|
||||
|
||||
await exec(`protoc ${args.join(' ')}`);
|
||||
}
|
||||
|
||||
await writeFile(
|
||||
`${root}/index.ts`,
|
||||
'// @ts-nocheck\n' +
|
||||
allFiles
|
||||
.sort()
|
||||
.map((file) => file.replace('.proto', ''))
|
||||
.map((file) => `export * from './${file}.ts';`)
|
||||
.join('\n'),
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src/**/*"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "../../"
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,13 @@
|
||||
import partytown from '@astrojs/partytown';
|
||||
import react from '@astrojs/react';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
import { SUPPORTED_LOCALES } from '@blitzkit/i18n';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: [...SUPPORTED_LOCALES],
|
||||
defaultLocale: locales.default,
|
||||
locales: locales.supported.map(({ locale }) => locale),
|
||||
routing: {
|
||||
prefixDefaultLocale: false,
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@astrojs/partytown": "^2.1.4",
|
||||
"@astrolib/seo": "^1.0.0-beta.8",
|
||||
"@blitzkit/closed": "workspace:*",
|
||||
"@blitzkit/core": "workspace:*",
|
||||
"@blitzkit/i18n": "workspace:*",
|
||||
"@fontsource/inter": "^5.2.5",
|
||||
@@ -20,10 +21,10 @@
|
||||
"@nivo/bar": "^0.87.0",
|
||||
"@nivo/line": "^0.88.0",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/themes": "^3.1.4",
|
||||
"@react-three/drei": "^9.115.0",
|
||||
"@react-three/fiber": "^8.17.10",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@radix-ui/themes": "^3.2.1",
|
||||
"@react-three/drei": "^10.0.8",
|
||||
"@react-three/fiber": "^9.1.2",
|
||||
"compare-versions": "^6.1.1",
|
||||
"echarts": "^5.5.1",
|
||||
"immer": "^10.1.1",
|
||||
@@ -31,9 +32,7 @@
|
||||
"markdown-to-jsx": "^7.5.0",
|
||||
"nanostores": "^0.11.3",
|
||||
"quicklime": "^1.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-promise-suspense": "^0.3.4",
|
||||
"three": "^0.169.0",
|
||||
"urlon": "^3.1.0",
|
||||
@@ -46,10 +45,7 @@
|
||||
"@playform/compress": "^0.1.9",
|
||||
"@playform/inline": "^0.1.2",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@types/three": "^0.160.0",
|
||||
"astro": "^4.16.7",
|
||||
"astro-compressor": "^1.0.0"
|
||||
"astro": "^4.16.7"
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,16 +1,29 @@
|
||||
import { TankClass } from '@blitzkit/core';
|
||||
import { TankClass as TankClass_dava } from '@blitzkit/core';
|
||||
import { TankClass } from '@protos/blitz_static_tank_component';
|
||||
import { QuestionMarkIcon } from '@radix-ui/react-icons';
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
import { ClassHeavy } from './components/ClassHeavy';
|
||||
import { ClassLight } from './components/ClassLight';
|
||||
import { ClassMedium } from './components/ClassMedium';
|
||||
import { ClassTankDestroyer } from './components/ClassTankDestroyer';
|
||||
|
||||
export const classIcons: Record<
|
||||
export const classIcons_ue: Record<
|
||||
TankClass,
|
||||
((props: ComponentProps<'svg'>) => ReactNode) | typeof QuestionMarkIcon
|
||||
> = {
|
||||
[TankClass.TANK_CLASS_UNSPECIFIED]: QuestionMarkIcon,
|
||||
[TankClass.TANK_CLASS_TANK_DESTROYER]: ClassTankDestroyer,
|
||||
[TankClass.TANK_CLASS_HEAVY]: ClassHeavy,
|
||||
[TankClass.TANK_CLASS_LIGHT]: ClassLight,
|
||||
[TankClass.TANK_CLASS_MEDIUM]: ClassMedium,
|
||||
};
|
||||
|
||||
export const classIcons: Record<
|
||||
TankClass_dava,
|
||||
(props: ComponentProps<'svg'>) => ReactNode
|
||||
> = {
|
||||
[TankClass.TANK_DESTROYER]: ClassTankDestroyer,
|
||||
[TankClass.HEAVY]: ClassHeavy,
|
||||
[TankClass.LIGHT]: ClassLight,
|
||||
[TankClass.MEDIUM]: ClassMedium,
|
||||
[TankClass_dava.TANK_CLASS_TANK_DESTROYER]: ClassTankDestroyer,
|
||||
[TankClass_dava.TANK_CLASS_HEAVY]: ClassHeavy,
|
||||
[TankClass_dava.TANK_CLASS_LIGHT]: ClassLight,
|
||||
[TankClass_dava.TANK_CLASS_MEDIUM]: ClassMedium,
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { RewardCurrency } from '@protos/blitz_static_reward_currency';
|
||||
import { Flex, Text, type TextProps } from '@radix-ui/themes';
|
||||
import { entityName } from 'packages/core/src';
|
||||
import { useLocale } from '../hooks/useLocale';
|
||||
|
||||
type CurrencyProps = TextProps & {
|
||||
reward: RewardCurrency;
|
||||
};
|
||||
|
||||
export function Currency({ reward, ...props }: CurrencyProps) {
|
||||
const { locale } = useLocale();
|
||||
|
||||
return (
|
||||
<Text {...props}>
|
||||
<Flex align="center" gap="1">
|
||||
{reward.amount.toLocaleString(locale)}
|
||||
<img
|
||||
src={`/api/currencies/${entityName(reward.currency_catalog_id)}.webp`}
|
||||
/>
|
||||
</Flex>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import locales from '@blitzkit/i18n/locales.json';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { literals } from '@blitzkit/i18n/src/literals';
|
||||
import { Flex, Text } from '@radix-ui/themes';
|
||||
import fuzzysort from 'fuzzysort';
|
||||
|
||||
@@ -3,11 +3,16 @@ import { Code, Flex, Heading, Text } from '@radix-ui/themes';
|
||||
import { resolveBranchName } from '../core/blitzkit/branches';
|
||||
import { getStrings } from '../core/i18n/getStrings';
|
||||
import { literals } from '@blitzkit/i18n/src/literals';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
|
||||
const { locale } = Astro.params;
|
||||
interface Props {
|
||||
locale: string;
|
||||
}
|
||||
|
||||
const { locale } = Astro.props;
|
||||
const strings = await getStrings(locale);
|
||||
const branchName = resolveBranchName(locale);
|
||||
const isBranchNamed = branchName !== undefined;
|
||||
const strings = getStrings(locale);
|
||||
---
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { DEFAULT_LOCALE } from '@blitzkit/i18n';
|
||||
import { Link, type LinkProps } from '@radix-ui/themes';
|
||||
import type { LocaleAcceptorProps } from '../hooks/useLocale';
|
||||
|
||||
type LinkI18nProps = LinkProps & LocaleAcceptorProps;
|
||||
type LinkI18nProps = LinkProps & {
|
||||
locale: string;
|
||||
};
|
||||
|
||||
export function LinkI18n({ locale, href, ...props }: LinkI18nProps) {
|
||||
const prefix =
|
||||
locale === undefined || locale === DEFAULT_LOCALE ? '' : `/${locale}`;
|
||||
const prefix = locale === DEFAULT_LOCALE ? '' : `/${locale}`;
|
||||
|
||||
return (
|
||||
<Link href={href?.startsWith('/') ? `${prefix}${href}` : href} {...props} />
|
||||
|
||||
@@ -15,11 +15,11 @@ import { LinkI18n } from './LinkI18n';
|
||||
|
||||
export interface Props {
|
||||
integrated?: boolean;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
const { integrated } = Astro.props;
|
||||
const { integrated, locale } = Astro.props;
|
||||
const toolsFiltered = TOOLS.filter((tool) => !('href' in tool));
|
||||
const { locale } = Astro.params;
|
||||
const branchName = resolveBranchName(locale);
|
||||
const isBranchNamed = branchName !== undefined;
|
||||
const strings = getStrings(locale);
|
||||
|
||||
@@ -13,7 +13,9 @@ export function Listing({ label, ...props }: ListingProps) {
|
||||
gap="4"
|
||||
style={{ borderBottom: `1px solid ${Var('gray-a9')}` }}
|
||||
>
|
||||
<Text size="4">{label}</Text>
|
||||
<Text size="4" wrap="nowrap">
|
||||
{label}
|
||||
</Text>
|
||||
<Text align="right" size="4" weight="medium" {...props} />
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
import { Nation, TankType } from '@protos/blitz_static_tank_component';
|
||||
import { Box, Code, Flex } from '@radix-ui/themes';
|
||||
import { asset, TIER_ROMAN_NUMERALS } from 'packages/core/src';
|
||||
import { Var } from '../../core/radix/var';
|
||||
import { useLocale } from '../../hooks/useLocale';
|
||||
import { TankopediaEphemeral_ue } from '../../stores/tankopediaEphemeral_ue';
|
||||
import { classIcons_ue } from '../ClassIcon';
|
||||
import { Currency } from '../Currency';
|
||||
import { Listing } from '../Tankopedia/MetaSection/components/Listing';
|
||||
|
||||
const NATIONAL_BANNER_POSITION_OVERRIDES: Partial<Record<Nation, string>> = {
|
||||
[Nation.NATION_GERMANY]: '50% 35%',
|
||||
[Nation.NATION_FRANCE]: '50% 35%',
|
||||
[Nation.NATION_OTHER]: '50% 35%',
|
||||
};
|
||||
|
||||
export function MetaSection() {
|
||||
const tank = TankopediaEphemeral_ue.use((state) => state.tank);
|
||||
const entity = TankopediaEphemeral_ue.use((state) => state.entity);
|
||||
const set = TankopediaEphemeral_ue.use((state) => state.set);
|
||||
const compensation = TankopediaEphemeral_ue.use(
|
||||
(state) => state.compensation,
|
||||
);
|
||||
const catalogueId = TankopediaEphemeral_ue.use((state) => state.entity);
|
||||
const ClassIcon = classIcons_ue[tank.tank_class];
|
||||
const { locale, strings, gameStrings } = useLocale();
|
||||
const reward = set.tank_set_rewards.find(
|
||||
(reward) =>
|
||||
reward.tank_set_reward_on_level &&
|
||||
reward.tank_set_reward_on_level.reward_list.some(
|
||||
(rewardOnLevel) =>
|
||||
rewardOnLevel.tank_reward &&
|
||||
rewardOnLevel.tank_reward.tank_catalog_id === catalogueId,
|
||||
),
|
||||
)!;
|
||||
const price =
|
||||
reward.tank_set_reward_price?.price_list[0].currency_price!.amount;
|
||||
|
||||
return (
|
||||
<Flex justify="center" mt="-9">
|
||||
<Box
|
||||
style={{
|
||||
background: `url(/assets/images/national-wallpapers/${tank.nation}.jpg)`,
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition:
|
||||
NATIONAL_BANNER_POSITION_OVERRIDES[tank.nation] ?? 'center',
|
||||
}}
|
||||
flexGrow="1"
|
||||
maxWidth="120rem"
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
background: `url(${asset(`flags/scratched/${tank.nation}.webp`)})`,
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: 'min(53rem, 80vw)',
|
||||
backgroundPosition: '-8rem 50%',
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
justify="center"
|
||||
align="center"
|
||||
py="6rem"
|
||||
style={{
|
||||
background: `linear-gradient(${Var('black-a8')}, ${Var('black-a8')}, ${Var('gray-1')})`,
|
||||
}}
|
||||
>
|
||||
<Flex direction="column" align="center" gap="6">
|
||||
<Flex
|
||||
gap={{ initial: '2', sm: '8' }}
|
||||
direction={{ initial: 'column', sm: 'row' }}
|
||||
>
|
||||
<Flex direction="column" width="100%" gap="2">
|
||||
<Listing label={strings.website.tools.tankopedia.meta.nation}>
|
||||
<Flex align="center" gap="1">
|
||||
<img
|
||||
style={{ width: '1em', height: '1em' }}
|
||||
alt={Nation[tank.nation]}
|
||||
src={asset(`flags/circle/${tank.nation}.webp`)}
|
||||
/>
|
||||
{strings.common.nations[tank.nation]}
|
||||
</Flex>
|
||||
</Listing>
|
||||
<Listing label={strings.website.tools.tankopedia.meta.class}>
|
||||
<Flex align="center" gap="1">
|
||||
<ClassIcon width="1em" height="1em" />
|
||||
{strings.common.tank_class[tank.tank_class]}
|
||||
</Flex>
|
||||
</Listing>
|
||||
|
||||
<Listing label={strings.website.tools.tankopedia.meta.tier}>
|
||||
{TIER_ROMAN_NUMERALS[tank.tier]}
|
||||
</Listing>
|
||||
|
||||
<Listing
|
||||
label={strings.website.tools.tankopedia.meta.type}
|
||||
color={
|
||||
tank.tank_type === TankType.TANK_TYPE_COLLECTIBLE
|
||||
? 'blue'
|
||||
: tank.tank_type === TankType.TANK_TYPE_PREMIUM
|
||||
? 'amber'
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{strings.common.tree_type[tank.tank_type]}
|
||||
</Listing>
|
||||
|
||||
<Listing label={strings.website.tools.tankopedia.meta.id}>
|
||||
<Code variant="ghost">
|
||||
{entity.replace('TankEntity.', '')}
|
||||
</Code>
|
||||
</Listing>
|
||||
</Flex>
|
||||
|
||||
<Flex direction="column" width="100%" gap="2">
|
||||
<Listing label={strings.website.tools.tankopedia.meta.set}>
|
||||
{gameStrings[set.tank_set_ui!.tank_set_displayed_name]}
|
||||
</Listing>
|
||||
|
||||
<Listing label={strings.website.tools.tankopedia.meta.price}>
|
||||
<Flex align="center" gap="1">
|
||||
{reward.tank_set_reward_price === undefined ? (
|
||||
strings.website.tools.tankopedia.meta.free
|
||||
) : (
|
||||
<>
|
||||
{price?.toLocaleString(locale)}
|
||||
|
||||
<img
|
||||
style={{ width: '1em', height: '1em' }}
|
||||
alt="xp"
|
||||
src={
|
||||
'https://wotblitz-gc.gcdn.co/dlc/ultra_test2_25abc2385a5/assets/Medusa/Currency/T_UI_Currency_Silver_S.webp'
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Listing>
|
||||
|
||||
{compensation.compensation?.currency_reward && (
|
||||
<Listing
|
||||
label={strings.website.tools.tankopedia.meta.compensation}
|
||||
>
|
||||
<Currency
|
||||
reward={compensation.compensation.currency_reward}
|
||||
/>
|
||||
</Listing>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
type CompositeStats,
|
||||
type CompositeStatsKey,
|
||||
} from '@blitzkit/core';
|
||||
import strings from '@blitzkit/i18n/strings/en.json';
|
||||
import { amberDark, blueDark } from '@radix-ui/colors';
|
||||
import { Flex, Text, type FlexProps } from '@radix-ui/themes';
|
||||
import { times } from 'lodash-es';
|
||||
@@ -53,7 +52,7 @@ export function BreakdownEmbedCard({
|
||||
}: BreakdownEmbedCardProps) {
|
||||
const { useEmbedState, useRichText } =
|
||||
useEmbedStateCurry<typeof breakdownConfig>();
|
||||
const { unwrap } = useLocale();
|
||||
const { unwrap, strings } = useLocale();
|
||||
|
||||
return (
|
||||
<Flex
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export function TestComponent({ data }: { data: any }) {
|
||||
useEffect(() => {
|
||||
console.log(data);
|
||||
}, []);
|
||||
|
||||
return 'TestComponent';
|
||||
}
|
||||
@@ -2,20 +2,20 @@
|
||||
import { assertSecret } from '@blitzkit/core';
|
||||
import { CaretRightIcon } from '@radix-ui/react-icons';
|
||||
import { Box, Button, Code, Flex, Heading, Text } from '@radix-ui/themes';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
import type { Tool } from '../constants/tools';
|
||||
import { getStrings } from '../core/i18n/getStrings';
|
||||
import { LinkI18n } from './LinkI18n';
|
||||
|
||||
interface Props {
|
||||
tool: Tool;
|
||||
strings: BlitzKitStrings;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
const { tool } = Astro.props;
|
||||
const { tool, strings, locale } = Astro.props;
|
||||
const disabled = tool.branches?.every(
|
||||
(branch) => branch !== assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH),
|
||||
);
|
||||
const { locale } = Astro.params;
|
||||
const strings = getStrings(locale);
|
||||
const toolStrings =
|
||||
strings.website.tools[
|
||||
(tool.stringsId ?? tool.id) as keyof typeof strings.website.tools
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import { DiscreteMetadataAccessor } from 'packages/core/src';
|
||||
|
||||
export const discreteMetadata = new DiscreteMetadataAccessor('/api/catalog');
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { TankSetCatalogComponent } from '@protos/blitz_static_tank_set_component';
|
||||
import type { MetadataAccessor } from 'submodules/blitzkit-closed/src';
|
||||
|
||||
export async function tankToSet(metadata: MetadataAccessor, tank: string) {
|
||||
for (const [id] of metadata.items) {
|
||||
if (!id.startsWith('TankSetEntity')) continue;
|
||||
|
||||
const components = await metadata.get(id);
|
||||
const set = await components.get<TankSetCatalogComponent>(
|
||||
'tankSetCatalogComponent',
|
||||
);
|
||||
|
||||
for (const reward of set.tank_set_rewards) {
|
||||
if (!reward.tank_set_reward_on_level) continue;
|
||||
|
||||
for (const rewardOnLevel of reward.tank_set_reward_on_level.reward_list) {
|
||||
if (!rewardOnLevel.tank_reward) continue;
|
||||
|
||||
if (rewardOnLevel.tank_reward.tank_catalog_id === tank) {
|
||||
return set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Tank ${tank} not found in any set`);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { requestAutoProxyClient, unpackMetadata } from '@blitzkit/closed';
|
||||
import type { GetPackedMetadataAsyncResponse } from '@blitzkit/closed/src/unreal/protos/auto_legacy_proxy_client';
|
||||
import { UnpackedMetadataAccessor } from 'packages/core/src';
|
||||
|
||||
export const unpackedMetadata = new UnpackedMetadataAccessor(
|
||||
await requestAutoProxyClient<GetPackedMetadataAsyncResponse>(
|
||||
'GetPackedMetadataAsyncRequest',
|
||||
).then(unpackMetadata),
|
||||
);
|
||||
@@ -1,6 +1,8 @@
|
||||
import { DEFAULT_LOCALE, STRINGS, type SupportedLocale } from '@blitzkit/i18n';
|
||||
import en from '@strings/en.json' with { type: 'json' };
|
||||
import { merge } from 'lodash-es';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
|
||||
export function getStrings(locale: string = DEFAULT_LOCALE) {
|
||||
if (locale in STRINGS) return STRINGS[locale as SupportedLocale];
|
||||
throw new Error(`Unsupported locale: ${locale}`);
|
||||
export async function getStrings(locale: string) {
|
||||
const strings = await import(`../../../../i18n/strings/${locale}.json`);
|
||||
return merge({}, en, strings) as BlitzKitStrings;
|
||||
}
|
||||
@@ -1,39 +1,30 @@
|
||||
import { DEFAULT_LOCALE, unwrapper } from '@blitzkit/i18n';
|
||||
import { createContext, useContext, type ReactNode } from 'react';
|
||||
import { getStrings } from '../core/i18n/getStrings';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
import { createContext, use, useContext } from 'react';
|
||||
const LocaleContext = createContext<string | null>(null);
|
||||
|
||||
const LocaleContext = createContext<{
|
||||
interface LocaleProviderProps {
|
||||
locale: string;
|
||||
localeRaw: string | undefined;
|
||||
} | null>(null);
|
||||
|
||||
interface LocaleProviderProps extends LocaleAcceptorProps {
|
||||
children: ReactNode;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function LocaleProvider({ locale, children }: LocaleProviderProps) {
|
||||
const isSupported = locales.supported.some(
|
||||
(supported) => supported.locale === locale,
|
||||
);
|
||||
|
||||
if (!isSupported) throw new Error(`Unsupported locale: ${locale}`);
|
||||
|
||||
return (
|
||||
<LocaleContext.Provider
|
||||
value={{ locale: locale ?? DEFAULT_LOCALE, localeRaw: locale }}
|
||||
>
|
||||
{children}
|
||||
</LocaleContext.Provider>
|
||||
<LocaleContext.Provider value={locale}>{children}</LocaleContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useLocale() {
|
||||
const context = useContext(LocaleContext);
|
||||
const locale = useContext(LocaleContext);
|
||||
const strings = use<BlitzKitStrings>(
|
||||
fetch(`/api/strings/${locale}.json`).then((response) => response.json()),
|
||||
);
|
||||
|
||||
if (!context) {
|
||||
throw new Error('useLocale must be used within a LocaleProvider');
|
||||
}
|
||||
|
||||
const strings = getStrings(context.locale);
|
||||
const unwrap = unwrapper(context.locale);
|
||||
|
||||
return { locale: context.locale, strings, unwrap };
|
||||
}
|
||||
|
||||
export interface LocaleAcceptorProps {
|
||||
locale: string | undefined;
|
||||
return { locale, strings };
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
import '@fontsource/inter';
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { BlitzKitTheme } from '../components/BlitzKitTheme';
|
||||
import { Checks } from '../components/Checks';
|
||||
@@ -7,16 +6,18 @@ import Footer from '../components/Footer.astro';
|
||||
import Navbar from '../components/Navbar.astro';
|
||||
import Party3 from '../components/Party3.astro';
|
||||
import './base.css';
|
||||
import { DEFAULT_LOCALE } from '@blitzkit/i18n';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
import { getStrings } from '../core/i18n/getStrings';
|
||||
|
||||
export interface Props {
|
||||
noFooter?: boolean;
|
||||
noNavbar?: boolean;
|
||||
integrated?: boolean;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
const { noFooter, noNavbar, integrated } = Astro.props;
|
||||
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
||||
const { noFooter, noNavbar, integrated, locale } = Astro.props;
|
||||
const strings = await getStrings(locale);
|
||||
---
|
||||
|
||||
<html lang={locale}>
|
||||
@@ -30,25 +31,26 @@ const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
||||
<Party3 />
|
||||
|
||||
<script>
|
||||
import { SUPPORTED_LOCALES } from '@blitzkit/i18n';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { getBestLocale } from '../core/i18n/getBestLocale';
|
||||
const isAPI = window.location.pathname.startsWith('/api');
|
||||
const isI18nPath = SUPPORTED_LOCALES.some((locale) =>
|
||||
const isI18nPath = locales.supported.some(({ locale }) =>
|
||||
window.location.pathname.startsWith(`/${locale}`),
|
||||
);
|
||||
const bestLocale = getBestLocale();
|
||||
const currentPathLocale = SUPPORTED_LOCALES.find((locale) =>
|
||||
const currentPathLocale = locales.supported.find(({ locale }) =>
|
||||
window.location.pathname.startsWith(`/${locale}`),
|
||||
);
|
||||
|
||||
if (
|
||||
!isAPI && // not an api, duh!
|
||||
localStorage.getItem('preferred-locale') !== null && // no preference, so probably google's crawler
|
||||
bestLocale !== currentPathLocale // we need to redirect
|
||||
currentPathLocale &&
|
||||
bestLocale !== currentPathLocale.locale // we need to redirect
|
||||
) {
|
||||
window.location.pathname = isI18nPath
|
||||
? window.location.pathname.replace(
|
||||
`/${currentPathLocale}`,
|
||||
`/${currentPathLocale.locale}`,
|
||||
bestLocale === undefined ? '' : `/${bestLocale}`,
|
||||
)
|
||||
: `/${bestLocale}${window.location.pathname}`;
|
||||
@@ -61,9 +63,9 @@ const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
||||
<body class={noNavbar ? 'no-navbar' : ''}>
|
||||
<BlitzKitTheme>
|
||||
<Flex direction="column" minHeight="100vh">
|
||||
<Navbar {integrated} />
|
||||
<Navbar {locale} {integrated} />
|
||||
|
||||
<Checks {locale} client:only="react" />
|
||||
<Checks localeContext={{ locale, strings }} client:only="react" />
|
||||
|
||||
<slot />
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
@import '@radix-ui/themes/styles.css';
|
||||
|
||||
.radix-themes {
|
||||
--default-font-family: 'Inter';
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
---
|
||||
import { AstroSeo } from '@astrolib/seo';
|
||||
import { assertSecret } from '@blitzkit/core';
|
||||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@blitzkit/i18n';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import { literals } from '@blitzkit/i18n/src/literals';
|
||||
import { Box, Flex, Heading, Link } from '@radix-ui/themes';
|
||||
import type { GetStaticPaths } from 'astro';
|
||||
import { AesonPlug } from '../../components/AesonPlug';
|
||||
import HomeHero from '../../components/HomeHero.astro';
|
||||
import { HomePageHotTanks } from '../../components/HomePageHotTanks';
|
||||
import { Plugs } from '../../components/Plugs';
|
||||
import ToolCard from '../../components/ToolCard.astro';
|
||||
import {
|
||||
@@ -25,17 +24,16 @@ import { getStrings } from '../../core/i18n/getStrings';
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
|
||||
const PUBLIC_ASSET_BRANCH = assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH);
|
||||
const MODE = assertSecret(import.meta.env.MODE);
|
||||
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
|
||||
const strings = getStrings(Astro.params.locale);
|
||||
const { locale } = Astro.props;
|
||||
const strings = await getStrings(locale);
|
||||
|
||||
export const getStaticPaths = (() => {
|
||||
return [
|
||||
...SUPPORTED_LOCALES.filter((locale) => locale !== DEFAULT_LOCALE).map(
|
||||
(locale) => ({ params: { locale } }),
|
||||
),
|
||||
{ params: { locale: undefined } },
|
||||
];
|
||||
return locales.supported.map(({ locale, blitz }) => {
|
||||
return {
|
||||
params: { locale: locale === locales.default ? undefined : locale },
|
||||
props: { locale, blitzLocale: blitz ?? locale },
|
||||
};
|
||||
});
|
||||
}) satisfies GetStaticPaths;
|
||||
---
|
||||
|
||||
@@ -52,8 +50,8 @@ export const getStaticPaths = (() => {
|
||||
twitter={{ cardType: 'summary_large_image' }}
|
||||
/>
|
||||
|
||||
<BaseLayout>
|
||||
<HomeHero />
|
||||
<BaseLayout {locale}>
|
||||
<HomeHero {locale} />
|
||||
|
||||
<!-- <Flex justify="center" py="6" px="4" justify="center">
|
||||
<Flex
|
||||
@@ -72,7 +70,7 @@ export const getStaticPaths = (() => {
|
||||
</Flex> -->
|
||||
|
||||
{
|
||||
locale !== DEFAULT_LOCALE && (
|
||||
locale !== locales.default && (
|
||||
<Flex justify="center" mb="4">
|
||||
<Link
|
||||
href="https://crowdin.com/project/blitzkrieg"
|
||||
@@ -81,7 +79,9 @@ export const getStaticPaths = (() => {
|
||||
>
|
||||
{literals(strings.website.home.help_translate, [
|
||||
'BlitzKit',
|
||||
strings.common.locales[locale],
|
||||
strings.common.locales[
|
||||
locale as keyof typeof strings.common.locales
|
||||
],
|
||||
])}
|
||||
</Link>
|
||||
</Flex>
|
||||
@@ -100,29 +100,29 @@ export const getStaticPaths = (() => {
|
||||
|
||||
<Flex p="4" justify="center" gap="4" mt="3">
|
||||
<Flex maxWidth="80rem" flexGrow="1" gap="4" direction="column">
|
||||
<ToolCard tool={tankopediaTool} />
|
||||
<ToolCard {locale} {strings} tool={tankopediaTool} />
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
{/* <ToolCard tool={playerStatsTool} /> */}
|
||||
<ToolCard tool={compareTool} />
|
||||
<ToolCard tool={performanceTool} />
|
||||
{/* <ToolCard {locale} {strings} tool={playerStatsTool} /> */}
|
||||
<ToolCard {locale} {strings} tool={compareTool} />
|
||||
<ToolCard {locale} {strings} tool={performanceTool} />
|
||||
</Flex>
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<!-- <ToolCard tool={chartsTool} /> -->
|
||||
<!-- <ToolCard tool={guessTool} /> -->
|
||||
<ToolCard tool={galleryTool} />
|
||||
<ToolCard tool={sessionTool} />
|
||||
<!-- <ToolCard {locale} {strings} tool={chartsTool} /> -->
|
||||
<!-- <ToolCard {locale} {strings} tool={guessTool} /> -->
|
||||
<ToolCard {locale} {strings} tool={galleryTool} />
|
||||
<ToolCard {locale} {strings} tool={sessionTool} />
|
||||
</Flex>
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard tool={discordTool} />
|
||||
<ToolCard tool={tierListTool} />
|
||||
<ToolCard {locale} {strings} tool={discordTool} />
|
||||
<ToolCard {locale} {strings} tool={tierListTool} />
|
||||
</Flex>
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard tool={embedTool} />
|
||||
<ToolCard tool={moreTool} />
|
||||
<ToolCard {locale} {strings} tool={embedTool} />
|
||||
<ToolCard {locale} {strings} tool={moreTool} />
|
||||
</Flex>
|
||||
|
||||
<Flex gap="4" direction={{ initial: 'column', sm: 'row' }}>
|
||||
@@ -135,6 +135,8 @@ export const getStaticPaths = (() => {
|
||||
|
||||
<Flex gap="4" mb="6" direction={{ initial: 'column', sm: 'row' }}>
|
||||
<ToolCard
|
||||
{locale}
|
||||
{strings}
|
||||
tool={{
|
||||
button: { color: 'blue' },
|
||||
id: 'blitz-analysis',
|
||||
@@ -143,6 +145,8 @@ export const getStaticPaths = (() => {
|
||||
}}
|
||||
/>
|
||||
<ToolCard
|
||||
{locale}
|
||||
{strings}
|
||||
tool={{
|
||||
button: { color: 'purple', highContrast: true },
|
||||
id: 'blitz-insider',
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { PageWrapper } from 'packages/website/src/components/PageWrapper';
|
||||
import { MetaSection } from 'packages/website/src/components/Tankopedia_ue/MetaSection';
|
||||
import {
|
||||
LocaleProvider,
|
||||
type LocaleAcceptorProps,
|
||||
} from 'packages/website/src/hooks/useLocale';
|
||||
import { App } from 'packages/website/src/stores/app';
|
||||
import { TankopediaEphemeral_ue } from 'packages/website/src/stores/tankopediaEphemeral_ue';
|
||||
|
||||
interface PageProps extends LocaleAcceptorProps {
|
||||
tankContext: TankopediaEphemeral_ue;
|
||||
}
|
||||
|
||||
export function Page({ localeContext, tankContext }: PageProps) {
|
||||
return (
|
||||
<LocaleProvider data={localeContext}>
|
||||
<App.Provider>
|
||||
<TankopediaEphemeral_ue.Provider data={tankContext}>
|
||||
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
|
||||
<MetaSection />
|
||||
</PageWrapper>
|
||||
</TankopediaEphemeral_ue.Provider>
|
||||
</App.Provider>
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
import type {
|
||||
CatalogItemsComponent,
|
||||
CompensationComponent,
|
||||
TankCatalogComponent,
|
||||
} from '@blitzkit/closed/src/unreal/protos';
|
||||
import { slugify } from '@blitzkit/core';
|
||||
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
|
||||
import type { GetStaticPaths } from 'astro';
|
||||
import { tankToSet } from 'packages/website/src/core/blitz/tankToSet';
|
||||
import type { TankopediaEphemeral_ue } from 'packages/website/src/stores/tankopediaEphemeral_ue';
|
||||
import { unpackedMetadata } from '../../../../core/blitz/unpackedMetadata';
|
||||
import BaseLayout from '../../../../layouts/BaseLayout.astro';
|
||||
import { getStaticPaths as parentGetStaticPaths } from '../index.astro';
|
||||
import { Page } from './_index';
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const tanks = await unpackedMetadata.getComponent<CatalogItemsComponent>(
|
||||
'CatalogItemsGroupEntity.all_tanks',
|
||||
'catalogItemsGroupComponent',
|
||||
);
|
||||
const gameStringsDefault = await unpackedMetadata.stringsSubset(
|
||||
locales.default,
|
||||
['TankEntity'],
|
||||
);
|
||||
const parentPaths = parentGetStaticPaths();
|
||||
|
||||
return (
|
||||
await Promise.all(
|
||||
tanks.catalog_items.map(async (item) => {
|
||||
const tank = await unpackedMetadata.get(item).then((components) => {
|
||||
return components.get<TankCatalogComponent>('tankCatalogComponent');
|
||||
});
|
||||
const nameEn = gameStringsDefault[tank.name!.value];
|
||||
const slug = slugify(nameEn) || item.replace('TankEntity.', '');
|
||||
|
||||
return parentPaths.map((parent) => {
|
||||
return {
|
||||
params: { ...parent.params, slug },
|
||||
props: { ...parent.props, entity: item },
|
||||
};
|
||||
});
|
||||
}),
|
||||
)
|
||||
).flat();
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const { entity, locale, strings, blitzLocale } = Astro.props;
|
||||
const set = await tankToSet(unpackedMetadata, entity);
|
||||
const gameStrings = await unpackedMetadata.stringsSubset(blitzLocale, [
|
||||
set.tank_set_ui!.tank_set_displayed_name,
|
||||
]);
|
||||
const tankEntity = await unpackedMetadata.get(entity);
|
||||
const tank = await tankEntity.get<TankCatalogComponent>('tankCatalogComponent');
|
||||
const compensation = await tankEntity.get<CompensationComponent>(
|
||||
'compensationComponent',
|
||||
);
|
||||
const tankContext: TankopediaEphemeral_ue = { tank, set, compensation, entity };
|
||||
---
|
||||
|
||||
<BaseLayout {locale} {strings}>
|
||||
<Page
|
||||
client:load
|
||||
{tankContext}
|
||||
localeContext={{ locale, strings, gameStrings }}
|
||||
/>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
||||
import { Link } from '@radix-ui/themes';
|
||||
import { PageWrapper } from 'packages/website/src/components/PageWrapper';
|
||||
import { unpackedMetadata } from 'packages/website/src/core/blitz/unpackedMetadata';
|
||||
import BaseLayout from 'packages/website/src/layouts/BaseLayout.astro';
|
||||
|
||||
export { getStaticPaths } from '../index.astro';
|
||||
|
||||
const { locale } = Astro.props;
|
||||
|
||||
const allTanks = unpackedMetadata
|
||||
.get('CatalogItemsGroupEntity.all_tanks')
|
||||
.get(CatalogItemsComponent, 'catalogItemsGroupComponent');
|
||||
---
|
||||
|
||||
<BaseLayout {locale}>
|
||||
<PageWrapper>
|
||||
{allTanks.catalog_items.map((tank) => <Link>{tank}</Link>)}
|
||||
</PageWrapper>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
||||
import { TestComponent } from 'packages/website/src/components/TestComponent';
|
||||
import { unpackedMetadata } from 'packages/website/src/core/blitz/unpackedMetadata';
|
||||
import { getStrings } from 'packages/website/src/core/i18n/getStrings';
|
||||
|
||||
export { getStaticPaths } from '../index.astro';
|
||||
|
||||
const { locale } = Astro.props;
|
||||
const strings = await getStrings(locale);
|
||||
|
||||
const allTanks = unpackedMetadata
|
||||
.get('CatalogItemsGroupEntity.all_tanks')
|
||||
.get(CatalogItemsComponent, 'catalogItemsGroupComponent');
|
||||
---
|
||||
|
||||
<TestComponent client:load data={allTanks} />
|
||||
@@ -1,43 +0,0 @@
|
||||
import { TankSandbox } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox';
|
||||
import { awaitableModelDefinitions } from '../../../../../core/awaitables/modelDefinitions';
|
||||
import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions';
|
||||
import { awaitableTankDefinitions } from '../../../../../core/awaitables/tankDefinitions';
|
||||
import { LocaleProvider } from '../../../../../hooks/useLocale';
|
||||
import { App } from '../../../../../stores/app';
|
||||
import { Duel } from '../../../../../stores/duel';
|
||||
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
||||
import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent';
|
||||
|
||||
const [provisionDefinitions, tankDefinitions, modelDefinitions] =
|
||||
await Promise.all([
|
||||
awaitableProvisionDefinitions,
|
||||
awaitableTankDefinitions,
|
||||
awaitableModelDefinitions,
|
||||
]);
|
||||
|
||||
interface PageProps {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function Page({ id }: PageProps) {
|
||||
const tank = tankDefinitions.tanks[id];
|
||||
const model = modelDefinitions.models[id];
|
||||
|
||||
return (
|
||||
<LocaleProvider locale="en">
|
||||
<App.Provider>
|
||||
<TankopediaPersistent.Provider>
|
||||
<Duel.Provider data={{ provisionDefinitions, model, tank }}>
|
||||
<TankopediaEphemeral.Provider data={model}>
|
||||
<Content />
|
||||
</TankopediaEphemeral.Provider>
|
||||
</Duel.Provider>
|
||||
</TankopediaPersistent.Provider>
|
||||
</App.Provider>
|
||||
</LocaleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function Content() {
|
||||
return <TankSandbox naked thicknessRange={{ value: 0 }} />;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
import { assertSecret } from '@blitzkit/core';
|
||||
import type { GetStaticPaths } from 'astro';
|
||||
import { getStaticPaths as tankopediaGetStaticPaths } from '../../../../[...locale]/tools/tankopedia/[id]/index.astro';
|
||||
import { Page } from './_index';
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
if (assertSecret(import.meta.env.MODE) === 'development') {
|
||||
return await tankopediaGetStaticPaths();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const { id } = Astro.params;
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<style is:global>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Page {id} client:load />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
import en from '@blitzkit/i18n/strings/en.json';
|
||||
import en from '@blitzkit/i18n/strings/en.json' with { type: 'json' };
|
||||
import type { TankPerformanceSortType } from '.';
|
||||
|
||||
export const TankPerformanceSortTypeNamesArray = Object.keys(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type en from '@blitzkit/i18n/strings/en.json';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
import { create } from 'zustand';
|
||||
import { createContextualStore } from '../../core/zustand/createContextualStore';
|
||||
|
||||
export type TankPerformanceSortType =
|
||||
keyof typeof en.website.tools.performance.table.stats;
|
||||
keyof BlitzKitStrings['website']['tools']['performance']['table']['stats'];
|
||||
|
||||
export interface TankPerformanceSort {
|
||||
type: TankPerformanceSortType;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { CompensationComponent } from '@protos/blitz_static_compensation_component';
|
||||
import type { TankCatalogComponent } from '@protos/blitz_static_tank_component';
|
||||
import type { TankSetCatalogComponent } from '@protos/blitz_static_tank_set_component';
|
||||
import { create } from 'zustand';
|
||||
import { subscribeWithSelector } from 'zustand/middleware';
|
||||
import { createContextualStore } from '../core/zustand/createContextualStore';
|
||||
|
||||
export interface TankopediaEphemeral_ue {
|
||||
tank: TankCatalogComponent;
|
||||
compensation: CompensationComponent;
|
||||
set: TankSetCatalogComponent;
|
||||
entity: string;
|
||||
}
|
||||
|
||||
export const TankopediaEphemeral_ue = createContextualStore(
|
||||
(data: TankopediaEphemeral_ue) => {
|
||||
return create<TankopediaEphemeral_ue>()(
|
||||
subscribeWithSelector<TankopediaEphemeral_ue>(() => data),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1,10 +1,11 @@
|
||||
import type en from '@blitzkit/i18n/strings/en.json';
|
||||
import * as lodash from 'lodash-es';
|
||||
import type { BlitzKitStrings } from 'packages/i18n/src';
|
||||
import { create } from 'zustand';
|
||||
import { persist, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { createContextualStore } from '../../core/zustand/createContextualStore';
|
||||
|
||||
export type TankopediaSortBy = keyof typeof en.website.common.tank_search.sort;
|
||||
export type TankopediaSortBy =
|
||||
keyof BlitzKitStrings['website']['common']['tank_search']['sort'];
|
||||
export type TankopediaSortDirection = 'ascending' | 'descending';
|
||||
export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react",
|
||||
"types": ["vite/client"]
|
||||
"types": ["vite/client"],
|
||||
"baseUrl": "../../"
|
||||
}
|
||||
}
|
||||
Submodule submodules/blitzkit-closed updated: 31937a9f1e...accc9ee26b.
+8
-1
@@ -14,11 +14,18 @@
|
||||
"allowJs": true,
|
||||
"incremental": true,
|
||||
"isolatedModules": true,
|
||||
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@protos/*": ["submodules/blitzkit-closed/src/unreal/protos/*"],
|
||||
"@strings/*": ["packages/i18n/strings/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules/**/*", "dist", ".next"]
|
||||
}
|
||||
Reference in new issue
Block a user