feat: hot garbage

This commit is contained in:
TrèsAbhi committed 2025-05-26 14:23:00 -05:00
1 parent ae5e38139b
commit d0170d53e4
19 files changed
+136 -210

No files matched your search

BIN
View File
Binary file not shown.
+2
View File
@@ -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",
+1
View File
@@ -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",
+4
View File
@@ -0,0 +1,4 @@
export function entityName(entity: string) {
const [_, ...name] = entity.split('.');
return name.join('.');
}
+2
View File
@@ -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';
@@ -0,0 +1,10 @@
import { Metadata } from '@protos/blitz_metadata';
export class MetadataAccessor {
constructor() {}
loadMetadata(metadata: Metadata) {
for (const catalogItem of metadata.catalog_items) {
}
}
}
+2 -1
View File
@@ -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",
@@ -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>
);
}
@@ -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<Record<Nation, string>> = {
@@ -15,12 +15,15 @@ const NATIONAL_BANNER_POSITION_OVERRIDES: Partial<Record<Nation, string>> = {
};
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]}
</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={
@@ -99,71 +104,19 @@ export function MetaSection() {
>
{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">
{developerMode && (
<Listing
label={strings.website.tools.tankopedia.meta.dev_id}
>
<Code>TANK_ID</Code>
</Listing>
)}
{tank.tank_type === TankType.TANK_TYPE_PREMIUM && (
<Listing
label={strings.website.tools.tankopedia.meta.purchase}
>
<Flex align="center" gap="1">
{(9999999999).toLocaleString(locale)}
<img
style={{ width: '1em', height: '1em' }}
alt="gold"
src={asset('icons/currencies/gold.webp')}
/>
</Flex>
</Listing>
)}
<Listing
label={
tank.tank_type === TankType.TANK_TYPE_COMMON
? strings.website.tools.tankopedia.meta.purchase
: strings.website.tools.tankopedia.meta.restoration
}
>
<Flex align="center" gap="1">
{(999999999).toLocaleString(locale)}
<img
style={{ width: '1em', height: '1em' }}
alt="TODO: REPLACE WITH CURRENCY NAME"
// src={asset(
// `icons/currencies/${
// protagonist.price.type === TankPriceType.GOLD
// ? 'gold'
// : 'silver'
// }.webp`,
// )}
/>
</Flex>
</Listing>
<Listing label={strings.website.tools.tankopedia.meta.sale}>
<Flex align="center" gap="1">
{(999999999).toLocaleString(locale)}
<img
style={{ width: '1em', height: '1em' }}
alt="TODO: REPLACE WITH CURRENCY NAME"
// src={asset(
// `icons/currencies/${
// protagonist.price.type === TankPriceType.GOLD
// ? 'gold'
// : 'silver'
// }.webp`,
// )}
/>
</Flex>
</Listing>
<Listing label={strings.website.tools.tankopedia.meta.set}>
{set.tank_set_ui!.tank_set_displayed_name}
{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 ? (
@@ -183,6 +136,16 @@ export function MetaSection() {
)}
</Flex>
</Listing>
{compensation.compensation?.currency_reward && (
<Listing
label={strings.website.tools.tankopedia.meta.compensation}
>
<Currency
reward={compensation.compensation.currency_reward}
/>
</Listing>
)}
</Flex>
</Flex>
</Flex>
@@ -0,0 +1,3 @@
export function TestComponent({ data }: { data: any }) {
return 'TestComponent';
}
+14 -14
View File
@@ -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<string, string>;
}
type LocaleContextData = Omit<LocaleContextContent, 'gameStrings'> & {
gameStrings?: Record<string, string>;
};
const LocaleContext = createContext<LocaleContextContent | null>(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 (
<LocaleContext.Provider value={{ locale, strings }}>
<LocaleContext.Provider value={{ gameStrings: {}, ...data }}>
{children}
</LocaleContext.Provider>
);
@@ -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;
}
@@ -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],
@@ -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 (
<LocaleProvider {...localeContext}>
<LocaleProvider data={localeContext}>
<App.Provider>
<TankopediaEphemeral_ue.Provider
data={{ tank, compensation, set, catalogueId }}
>
<TankopediaEphemeral_ue.Provider data={tankContext}>
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
<MetaSection />
</PageWrapper>
@@ -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<CatalogItemsComponent>('catalogItemsGroupComponent'),
);
const tanks = await metadata.getComponent<CatalogItemsComponent>(
'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>(
'tankCatalogComponent',
);
const compensation = await tankComponents.get<CompensationComponent>(
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>('tankCatalogComponent');
const compensation = await tankEntity.get<CompensationComponent>(
'compensationComponent',
);
const tankContext: TankopediaEphemeral_ue = { tank, set, compensation, entity };
---
<BaseLayout {locale} {strings}>
<Page
client:load
catalogueId={item}
{set}
{tank}
{compensation}
localeContext={{ locale, strings }}
{tankContext}
localeContext={{ locale, strings, gameStrings }}
/>
</BaseLayout>
@@ -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<CatalogItemsComponent>('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<CatalogItemsComponent>(
'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>('tankCatalogComponent');
});
const nameEn = gameStringsDefault[tank.name!.value];
const tank = await metadata.getComponent<TankCatalogComponent>(
tankComponentId,
'tankCatalogComponent',
);
if (tank.name === undefined) {
continue;
}
const nameEn = gameStringsDefault[tank.name.value];
const slug = slugify(nameEn);
tanks.push({ tank, slug, id: tankComponentId });
}
---
<TestComponent client:load data={metadata} />
{
tanks.map(({ tank, slug, id }) => {
return (
@@ -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>
@@ -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(