diff --git a/bun.lockb b/bun.lockb
index cc1b8bdf8..e945d6256 100644
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 8b4a6cc52..53ba6a734 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"license": "MIT",
"dependencies": {
"googleapis": "^144.0.0",
+ "js-yaml": "^4.1.0",
"lodash-es": "^4.17.21",
"protobufjs": "^7.5.2",
"quicklime": "^1.2.0",
@@ -49,6 +50,7 @@
},
"devDependencies": {
"@types/bun": "latest",
+ "@types/js-yaml": "^4.0.9",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.14.1",
"prettier": "^3.5.3",
diff --git a/packages/core/package.json b/packages/core/package.json
index 8ad88467a..396849b5f 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -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",
diff --git a/packages/core/src/blitz/entityName.ts b/packages/core/src/blitz/entityName.ts
new file mode 100644
index 000000000..12d390720
--- /dev/null
+++ b/packages/core/src/blitz/entityName.ts
@@ -0,0 +1,4 @@
+export function entityName(entity: string) {
+ const [_, ...name] = entity.split('.');
+ return name.join('.');
+}
diff --git a/packages/core/src/blitz/index.ts b/packages/core/src/blitz/index.ts
index d1bd1b37d..e6695539c 100644
--- a/packages/core/src/blitz/index.ts
+++ b/packages/core/src/blitz/index.ts
@@ -2,6 +2,7 @@ export * from './canSplash';
export * from './clans';
export * from './classes';
export * from './constants';
+export * from './entityName';
export * from './equipmentPrice';
export * from './fetchBlitz';
export * from './fetchGlossary';
@@ -18,6 +19,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';
diff --git a/packages/core/src/blitz/metadataAccessor.ts b/packages/core/src/blitz/metadataAccessor.ts
new file mode 100644
index 000000000..8a07c2c8d
--- /dev/null
+++ b/packages/core/src/blitz/metadataAccessor.ts
@@ -0,0 +1,10 @@
+import { Metadata } from '@protos/blitz_metadata';
+
+export class MetadataAccessor {
+ constructor() {}
+
+ loadMetadata(metadata: Metadata) {
+ for (const catalogItem of metadata.catalog_items) {
+ }
+ }
+}
diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json
index a4ffec20f..d509f5f5f 100644
--- a/packages/i18n/strings/en.json
+++ b/packages/i18n/strings/en.json
@@ -1037,6 +1037,7 @@
},
"meta": {
+ "compensation": "Compensation",
"free": "Free",
"back": "Back",
"compare": "Compare",
@@ -1051,7 +1052,7 @@
"class": "Class",
"tier": "Tier",
"type": "Type",
- "dev_id": "DEV: ID",
+ "id": "ID",
"purchase": "Purchase price",
"restoration": "Restoration price",
"sale": "Sale price",
diff --git a/packages/website/src/components/Currency.tsx b/packages/website/src/components/Currency.tsx
new file mode 100644
index 000000000..52edd0b62
--- /dev/null
+++ b/packages/website/src/components/Currency.tsx
@@ -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 (
+
+
+ {reward.amount.toLocaleString(locale)}
+
+
+
+ );
+}
diff --git a/packages/website/src/components/Tankopedia_ue/MetaSection.tsx b/packages/website/src/components/Tankopedia_ue/MetaSection.tsx
index 8c71fe66b..c39be5159 100644
--- a/packages/website/src/components/Tankopedia_ue/MetaSection.tsx
+++ b/packages/website/src/components/Tankopedia_ue/MetaSection.tsx
@@ -3,9 +3,9 @@ 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 { App } from '../../stores/app';
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> = {
@@ -15,12 +15,15 @@ const NATIONAL_BANNER_POSITION_OVERRIDES: Partial> = {
};
export function MetaSection() {
- const developerMode = App.useDeferred((state) => state.developerMode, false);
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 catalogueId = TankopediaEphemeral_ue.use((state) => state.catalogueId);
+ 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 } = useLocale();
+ const { locale, strings, gameStrings } = useLocale();
const reward = set.tank_set_rewards.find(
(reward) =>
reward.tank_set_reward_on_level &&
@@ -84,9 +87,11 @@ export function MetaSection() {
{strings.common.tank_class[tank.tank_class]}
+
{TIER_ROMAN_NUMERALS[tank.tier]}
+
{strings.common.tree_type[tank.tank_type]}
+
+
+
+ {entity.replace('TankEntity.', '')}
+
+
- {developerMode && (
-
- TANK_ID
-
- )}
- {tank.tank_type === TankType.TANK_TYPE_PREMIUM && (
-
-
- {(9999999999).toLocaleString(locale)}
-
-
-
- )}
-
-
- {(999999999).toLocaleString(locale)}
-
-
-
-
-
- {(999999999).toLocaleString(locale)}
-
-
-
- {set.tank_set_ui!.tank_set_displayed_name}
+ {gameStrings[set.tank_set_ui!.tank_set_displayed_name]}
+
{reward.tank_set_reward_price === undefined ? (
@@ -183,6 +136,16 @@ export function MetaSection() {
)}
+
+ {compensation.compensation?.currency_reward && (
+
+
+
+ )}
diff --git a/packages/website/src/components/TestComponent.tsx b/packages/website/src/components/TestComponent.tsx
new file mode 100644
index 000000000..31941b5bf
--- /dev/null
+++ b/packages/website/src/components/TestComponent.tsx
@@ -0,0 +1,3 @@
+export function TestComponent({ data }: { data: any }) {
+ return 'TestComponent';
+}
diff --git a/packages/website/src/hooks/useLocale.tsx b/packages/website/src/hooks/useLocale.tsx
index 7a96108ba..a7189ad3b 100644
--- a/packages/website/src/hooks/useLocale.tsx
+++ b/packages/website/src/hooks/useLocale.tsx
@@ -1,24 +1,26 @@
import { type BlitzKitStrings } from '@blitzkit/i18n';
import { createContext, useContext, type ReactNode } from 'react';
-const LocaleContext = createContext<{
+interface LocaleContextContent {
locale: string;
strings: BlitzKitStrings;
-} | null>(null);
+ gameStrings: Record;
+}
+
+type LocaleContextData = Omit & {
+ gameStrings?: Record;
+};
+
+const LocaleContext = createContext(null);
interface LocaleProviderProps {
- locale: string;
- strings: BlitzKitStrings;
+ data: LocaleContextData;
children: ReactNode;
}
-export function LocaleProvider({
- locale,
- strings,
- children,
-}: LocaleProviderProps) {
+export function LocaleProvider({ data, children }: LocaleProviderProps) {
return (
-
+
{children}
);
@@ -31,11 +33,9 @@ export function useLocale() {
throw new Error('useLocale must be used within a LocaleProvider');
}
- const { locale, strings } = context;
-
- return { locale, strings };
+ return context;
}
export interface LocaleAcceptorProps {
- localeContext: { locale: string; strings: BlitzKitStrings };
+ localeContext: LocaleContextContent;
}
diff --git a/packages/website/src/pages/[...locale]/index.astro b/packages/website/src/pages/[...locale]/index.astro
index c4bfd8a63..e27a6973a 100644
--- a/packages/website/src/pages/[...locale]/index.astro
+++ b/packages/website/src/pages/[...locale]/index.astro
@@ -30,7 +30,6 @@ export const getStaticPaths = (() => {
return locales.supported.map(({ locale, blitz }) => {
return {
params: { locale: locale === locales.default ? undefined : locale },
-
props: {
locale,
strings: STRINGS[locale as SupportedLocale],
diff --git a/packages/website/src/pages/[...locale]/tanks-ue/[slug]/_index.tsx b/packages/website/src/pages/[...locale]/tanks-ue/[slug]/_index.tsx
index c908c635f..e54e03d7e 100644
--- a/packages/website/src/pages/[...locale]/tanks-ue/[slug]/_index.tsx
+++ b/packages/website/src/pages/[...locale]/tanks-ue/[slug]/_index.tsx
@@ -1,6 +1,3 @@
-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 { PageWrapper } from 'packages/website/src/components/PageWrapper';
import { MetaSection } from 'packages/website/src/components/Tankopedia_ue/MetaSection';
import {
@@ -11,25 +8,14 @@ import { App } from 'packages/website/src/stores/app';
import { TankopediaEphemeral_ue } from 'packages/website/src/stores/tankopediaEphemeral_ue';
interface PageProps extends LocaleAcceptorProps {
- tank: TankCatalogComponent;
- compensation: CompensationComponent;
- set: TankSetCatalogComponent;
- catalogueId: string;
+ tankContext: TankopediaEphemeral_ue;
}
-export function Page({
- tank,
- compensation,
- set,
- localeContext,
- catalogueId,
-}: PageProps) {
+export function Page({ localeContext, tankContext }: PageProps) {
return (
-
+
-
+
diff --git a/packages/website/src/pages/[...locale]/tanks-ue/[slug]/index.astro b/packages/website/src/pages/[...locale]/tanks-ue/[slug]/index.astro
index 8e408e95c..e4ede1ee4 100644
--- a/packages/website/src/pages/[...locale]/tanks-ue/[slug]/index.astro
+++ b/packages/website/src/pages/[...locale]/tanks-ue/[slug]/index.astro
@@ -8,21 +8,21 @@ import { slugify } from '@blitzkit/core';
import locales from '@blitzkit/i18n/locales.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 { metadata } from '../../../../core/blitz/metadata';
import BaseLayout from '../../../../layouts/BaseLayout.astro';
import { getStaticPaths as parentGetStaticPaths } from '../index.astro';
import { Page } from './_index';
export const getStaticPaths = (async () => {
- const tanks = await metadata
- .get('CatalogItemsGroupEntity.all_tanks')
- .then((components) =>
- components.get('catalogItemsGroupComponent'),
- );
+ const tanks = await metadata.getComponent(
+ 'CatalogItemsGroupEntity.all_tanks',
+ 'catalogItemsGroupComponent',
+ );
+ const gameStringsDefault = await metadata.stringsSubset(locales.default, [
+ 'TankEntity',
+ ]);
const parentPaths = parentGetStaticPaths();
- const gameStringsDefault = await metadata
- .strings(locales.default)
- .then((strings) => strings.subset(['TankEntity']));
return (
await Promise.all(
@@ -36,7 +36,7 @@ export const getStaticPaths = (async () => {
return parentPaths.map((parent) => {
return {
params: { ...parent.params, slug },
- props: { ...parent.props, item },
+ props: { ...parent.props, entity: item },
};
});
}),
@@ -44,24 +44,23 @@ export const getStaticPaths = (async () => {
).flat();
}) satisfies GetStaticPaths;
-const { item, locale, strings } = Astro.props;
-const set = await tankToSet(metadata, item);
-const tankComponents = await metadata.get(item);
-const tank = await tankComponents.get(
- 'tankCatalogComponent',
-);
-const compensation = await tankComponents.get(
+const { entity, locale, strings, blitzLocale } = Astro.props;
+const set = await tankToSet(metadata, entity);
+const gameStrings = await metadata.stringsSubset(blitzLocale, [
+ set.tank_set_ui!.tank_set_displayed_name,
+]);
+const tankEntity = await metadata.get(entity);
+const tank = await tankEntity.get('tankCatalogComponent');
+const compensation = await tankEntity.get(
'compensationComponent',
);
+const tankContext: TankopediaEphemeral_ue = { tank, set, compensation, entity };
---
diff --git a/packages/website/src/pages/[...locale]/tanks-ue/index.astro b/packages/website/src/pages/[...locale]/tanks-ue/index.astro
index 0aac83088..4220dc989 100644
--- a/packages/website/src/pages/[...locale]/tanks-ue/index.astro
+++ b/packages/website/src/pages/[...locale]/tanks-ue/index.astro
@@ -3,35 +3,41 @@ import { slugify } from '@blitzkit/core';
import locales from '@blitzkit/i18n/locales.json';
import type { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
import { TankCatalogComponent } from '@protos/blitz_static_tank_component';
+import { TestComponent } from 'packages/website/src/components/TestComponent';
import { metadata } from '../../../core/blitz/metadata';
export { getStaticPaths } from '../index.astro';
const { blitzLocale } = Astro.props;
-const allTanks = await metadata
- .get('CatalogItemsGroupEntity.all_tanks')
- .then((components) =>
- components.get('catalogItemsGroupComponent'),
- );
-const gameStrings = await metadata
- .strings(blitzLocale)
- .then((strings) => strings.subset(['TankEntity']));
-const gameStringsDefault = await metadata
- .strings(locales.default)
- .then((strings) => strings.subset(['TankEntity']));
+const allTanks = await metadata.getComponent(
+ 'CatalogItemsGroupEntity.all_tanks',
+ 'catalogItemsGroupComponent',
+);
+const gameStrings = await metadata.stringsSubset(blitzLocale, ['TankEntity']);
+const gameStringsDefault = await metadata.stringsSubset(locales.default, [
+ 'TankEntity',
+]);
const tanks: { tank: TankCatalogComponent; slug: string; id: string }[] = [];
for (const tankComponentId of allTanks.catalog_items) {
- const tank = await metadata.get(tankComponentId).then((components) => {
- return components.get('tankCatalogComponent');
- });
- const nameEn = gameStringsDefault[tank.name!.value];
+ const tank = await metadata.getComponent(
+ tankComponentId,
+ 'tankCatalogComponent',
+ );
+
+ if (tank.name === undefined) {
+ continue;
+ }
+
+ const nameEn = gameStringsDefault[tank.name.value];
const slug = slugify(nameEn);
tanks.push({ tank, slug, id: tankComponentId });
}
---
+
+
{
tanks.map(({ tank, slug, id }) => {
return (
diff --git a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx
deleted file mode 100644
index 7f00d7ad9..000000000
--- a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx
+++ /dev/null
@@ -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 (
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-function Content() {
- return ;
-}
diff --git a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro
deleted file mode 100644
index e8e8d414a..000000000
--- a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro
+++ /dev/null
@@ -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;
----
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/website/src/stores/tankopediaEphemeral_ue.ts b/packages/website/src/stores/tankopediaEphemeral_ue.ts
index 76c60ca4a..b0d8616da 100644
--- a/packages/website/src/stores/tankopediaEphemeral_ue.ts
+++ b/packages/website/src/stores/tankopediaEphemeral_ue.ts
@@ -5,11 +5,11 @@ import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { createContextualStore } from '../core/zustand/createContextualStore';
-interface TankopediaEphemeral_ue {
+export interface TankopediaEphemeral_ue {
tank: TankCatalogComponent;
compensation: CompensationComponent;
set: TankSetCatalogComponent;
- catalogueId: string;
+ entity: string;
}
export const TankopediaEphemeral_ue = createContextualStore(
diff --git a/submodules/blitzkit-closed b/submodules/blitzkit-closed
index 793d8c9f4..accc9ee26 160000
--- a/submodules/blitzkit-closed
+++ b/submodules/blitzkit-closed
@@ -1 +1 @@
-Subproject commit 793d8c9f4efafb07435be001f4f9fb1a8c5ce422
+Subproject commit accc9ee26bca2f327381ceac8ff9f72869a72aec