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)} - gold - - - )} - - - {(999999999).toLocaleString(locale)} - TODO: REPLACE WITH CURRENCY NAME - - - - - {(999999999).toLocaleString(locale)} - TODO: REPLACE WITH CURRENCY NAME - - - {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