From 5e9aa99755836f48cf163203a7480ea34be4b5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 28 May 2025 18:32:04 -0500 Subject: [PATCH] feat: remote catalog --- .gitignore | 2 +- _package.json | 2 - ...metadataAccessor.ts => catalogAccessor.ts} | 48 +++++++------------ .../core/src/blitz/catalogItemAccessor.ts | 21 ++++++++ packages/core/src/blitz/index.ts | 3 +- packages/core/tsconfig.json | 2 +- packages/website-ue/astro.config.mjs | 1 + packages/website-ue/package.json | 4 +- packages/website-ue/src/core/blitz/catalog.ts | 6 +++ .../src/core/blitz/discreteMetadata.ts | 3 -- .../src/core/blitz/remoteCatalog.ts | 4 ++ .../src/core/blitz/unpackedMetadata.ts | 9 ---- packages/website-ue/src/core/blitzkit/api.ts | 11 +++++ .../src/pages/[...locale]/tanks/_index.tsx | 20 ++++++++ .../src/pages/[...locale]/tanks/index.astro | 20 ++------ .../src/pages/api/catalog/[item].pb.ts | 18 +++++++ submodules/blitzkit-closed | 2 +- 17 files changed, 109 insertions(+), 67 deletions(-) rename packages/core/src/blitz/{metadataAccessor.ts => catalogAccessor.ts} (64%) create mode 100644 packages/website-ue/src/core/blitz/catalog.ts delete mode 100644 packages/website-ue/src/core/blitz/discreteMetadata.ts create mode 100644 packages/website-ue/src/core/blitz/remoteCatalog.ts delete mode 100644 packages/website-ue/src/core/blitz/unpackedMetadata.ts create mode 100644 packages/website-ue/src/core/blitzkit/api.ts create mode 100644 packages/website-ue/src/pages/[...locale]/tanks/_index.tsx create mode 100644 packages/website-ue/src/pages/api/catalog/[item].pb.ts diff --git a/.gitignore b/.gitignore index abd77cc70..3804cd921 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules _node_modules package-lock.json -.env +*.env /test-results/ /playwright-report/ /playwright/.cache/ diff --git a/_package.json b/_package.json index d8adc0af6..03b0424f9 100644 --- a/_package.json +++ b/_package.json @@ -95,13 +95,11 @@ "urlon": "^3.1.0", "zustand": "^4.5.5", "@types/bun": "latest", - "@types/lodash-es": "^4.17.12", "@types/node": "^22.14.1", "prettier": "^3.5.3", "prisma": "^6.6.0", "typescript": "^5.8.3", "googleapis": "^144.0.0", - "lodash-es": "^4.17.21", "protobufjs": "^7.5.2", "quicklime": "^1.2.0", "sharp": "^0.33.5" diff --git a/packages/core/src/blitz/metadataAccessor.ts b/packages/core/src/blitz/catalogAccessor.ts similarity index 64% rename from packages/core/src/blitz/metadataAccessor.ts rename to packages/core/src/blitz/catalogAccessor.ts index 472d686f7..f0966eeaf 100644 --- a/packages/core/src/blitz/metadataAccessor.ts +++ b/packages/core/src/blitz/catalogAccessor.ts @@ -1,15 +1,14 @@ import { CatalogItem } from '@protos/blitz_items'; -import { Metadata } from '@protos/blitz_metadata'; import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component'; -import { BlitzKitAllTankEntities } from '@protos/blitzkit_static_all_tank_entities'; +import { BlitzkitAllTanksComponent } from '@protos/blitzkit_static_all_tanks_component'; import { BlitzKitTankCatalogComponent } from '@protos/blitzkit_static_tank_component'; import { CatalogItemAccessor } from './catalogItemAccessor'; -export class UnpackedMetadataAccessor { +export class CatalogAccessor { items: Record = {}; - constructor(metadata: Metadata) { - for (const item of metadata.catalog_items) { + constructor(catalogItems: CatalogItem[]) { + for (const item of catalogItems) { if (item.catalog_id in this.items) { throw new Error(`Duplicate catalog ID: ${item.catalog_id}`); } @@ -20,29 +19,14 @@ export class UnpackedMetadataAccessor { get(item: string) { if (item in this.items) return this.items[item]; - throw new Error(`Unknown catalog ID: ${item}`); } - addCatalogItem(item: CatalogItemAccessor) { + add(item: CatalogItemAccessor) { this.items[item.id] = item; return this; } - addCatalogItemWithComponent( - catalogId: string, - componentId: string, - url: string, - value: Uint8Array, - ) { - this.addCatalogItem( - new CatalogItemAccessor({ - catalog_id: catalogId, - components: [], - }).addComponent(componentId, { type_url: url, value }), - ); - } - getAllTanks() { return this.get('CatalogItemsGroupEntity.all_tanks').get( CatalogItemsComponent, @@ -52,7 +36,7 @@ export class UnpackedMetadataAccessor { injectBlitzkit() { this.injectBlitzKitTankComponents(); - this.injectBlitzKitAllTankEntities(); + this.injectBlitzKitAllTanksEntity(); return this; } @@ -73,23 +57,27 @@ export class UnpackedMetadataAccessor { } } - injectBlitzKitAllTankEntities() { - const allTanksEntities: BlitzKitAllTankEntities = { tanks: [] }; + injectBlitzKitAllTanksEntity() { + const allTanksEntities: BlitzkitAllTanksComponent = { tanks: [] }; for (const item of this.getAllTanks().catalog_items) { allTanksEntities.tanks.push(this.get(item).pack()); } - this.addCatalogItemWithComponent( - 'BlitzKitAllTankEntities.all_tanks', - 'blitzkitAllTankEntitiesComponent', - './blitzkit_static_all_tank_entities.BlitzKitAllTankEntities', - BlitzKitAllTankEntities.encode(allTanksEntities).finish(), + this.add( + CatalogItemAccessor.fromComponent( + 'BlitzKitAllTanksEntity.blitzkit_all_tanks', + { + type_url: + './blitzkit_static_all_tanks_component.BlitzkitAllTanksComponent', + value: BlitzkitAllTanksComponent.encode(allTanksEntities).finish(), + }, + ), ); } } -export class DiscreteMetadataAccessor { +export class RemoteCatalogAccessor { constructor(private base: string) {} async get(item: string) { diff --git a/packages/core/src/blitz/catalogItemAccessor.ts b/packages/core/src/blitz/catalogItemAccessor.ts index 2ed837a29..fb782f6d3 100644 --- a/packages/core/src/blitz/catalogItemAccessor.ts +++ b/packages/core/src/blitz/catalogItemAccessor.ts @@ -1,5 +1,6 @@ import { CatalogItem } from '@protos/blitz_items'; import { Any } from '@protos/google/protobuf/any'; +import { lowerFirst } from 'lodash-es'; import { MessageFns } from '../protos'; export class CatalogItemAccessor { @@ -21,6 +22,22 @@ export class CatalogItemAccessor { } } + static fromComponent(id: string, component: Any) { + return this.fromComponents(id, [component]); + } + + static fromComponents(id: string, components: Any[]) { + return new CatalogItemAccessor({ + catalog_id: id, + components: components.map((component) => ({ + key: lowerFirst( + component.type_url.slice(2).split('.').slice(1).join('.'), + ), + value: { type_url: component.type_url, component }, + })), + }); + } + addComponent(key: string, value: Any) { this.components[key] = value; return this; @@ -48,4 +65,8 @@ export class CatalogItemAccessor { return item; } + + encode() { + return CatalogItem.encode(this.pack()).finish(); + } } diff --git a/packages/core/src/blitz/index.ts b/packages/core/src/blitz/index.ts index 7765608cb..95a590201 100644 --- a/packages/core/src/blitz/index.ts +++ b/packages/core/src/blitz/index.ts @@ -1,5 +1,5 @@ export * from './canSplash'; -export * from './catalogItemAccessor'; +export * from './catalogAccessor'; export * from './clans'; export * from './classes'; export * from './constants'; @@ -19,7 +19,6 @@ 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/tsconfig.json b/packages/core/tsconfig.json index f2ca1d8d9..70747e7dc 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "../../tsconfig.json", - "include": ["src/**/*", "../i18n/src/strings.ts"], + "include": ["src/**/*"], "compilerOptions": { "baseUrl": "../../" } diff --git a/packages/website-ue/astro.config.mjs b/packages/website-ue/astro.config.mjs index cef38998c..4e39c0f77 100644 --- a/packages/website-ue/astro.config.mjs +++ b/packages/website-ue/astro.config.mjs @@ -7,4 +7,5 @@ import react from '@astrojs/react'; export default defineConfig({ integrations: [react()], devToolbar: { enabled: false }, + site: 'https://blitzkit.app', }); diff --git a/packages/website-ue/package.json b/packages/website-ue/package.json index 24d0eb79d..6108771c1 100644 --- a/packages/website-ue/package.json +++ b/packages/website-ue/package.json @@ -19,6 +19,8 @@ "@types/react-dom": "^19.1.5", "astro": "^5.8.0", "react": "^19.1.0", - "react-dom": "^19.1.0" + "react-dom": "^19.1.0", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" } } diff --git a/packages/website-ue/src/core/blitz/catalog.ts b/packages/website-ue/src/core/blitz/catalog.ts new file mode 100644 index 000000000..33656cf07 --- /dev/null +++ b/packages/website-ue/src/core/blitz/catalog.ts @@ -0,0 +1,6 @@ +import { fetchMetadata } from '@blitzkit/closed'; +import { CatalogAccessor } from 'packages/core/src'; + +export const catalog = new CatalogAccessor( + await fetchMetadata().then((data) => data.catalog_items), +).injectBlitzkit(); diff --git a/packages/website-ue/src/core/blitz/discreteMetadata.ts b/packages/website-ue/src/core/blitz/discreteMetadata.ts deleted file mode 100644 index ad2b97025..000000000 --- a/packages/website-ue/src/core/blitz/discreteMetadata.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { DiscreteMetadataAccessor } from 'packages/core/src'; - -export const discreteMetadata = new DiscreteMetadataAccessor('/api/catalog'); diff --git a/packages/website-ue/src/core/blitz/remoteCatalog.ts b/packages/website-ue/src/core/blitz/remoteCatalog.ts new file mode 100644 index 000000000..928381322 --- /dev/null +++ b/packages/website-ue/src/core/blitz/remoteCatalog.ts @@ -0,0 +1,4 @@ +import { RemoteCatalogAccessor } from 'packages/core/src'; +import { api } from '../blitzkit/api'; + +export const remoteCatalog = new RemoteCatalogAccessor(api('catalog')); diff --git a/packages/website-ue/src/core/blitz/unpackedMetadata.ts b/packages/website-ue/src/core/blitz/unpackedMetadata.ts deleted file mode 100644 index 649970ef9..000000000 --- a/packages/website-ue/src/core/blitz/unpackedMetadata.ts +++ /dev/null @@ -1,9 +0,0 @@ -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( - 'GetPackedMetadataAsyncRequest', - ).then(unpackMetadata), -).injectBlitzkit(); diff --git a/packages/website-ue/src/core/blitzkit/api.ts b/packages/website-ue/src/core/blitzkit/api.ts new file mode 100644 index 000000000..7d11c7294 --- /dev/null +++ b/packages/website-ue/src/core/blitzkit/api.ts @@ -0,0 +1,11 @@ +let base: string; + +if (import.meta.env.DEV) { + base = 'http://localhost:4321'; +} else { + base = import.meta.env.SITE; +} + +export function api(path: string) { + return `${base}/api/${path}`; +} diff --git a/packages/website-ue/src/pages/[...locale]/tanks/_index.tsx b/packages/website-ue/src/pages/[...locale]/tanks/_index.tsx new file mode 100644 index 000000000..8b3378d15 --- /dev/null +++ b/packages/website-ue/src/pages/[...locale]/tanks/_index.tsx @@ -0,0 +1,20 @@ +import { TankCatalogComponent } from '@protos/blitz_static_tank_component'; +import { BlitzkitAllTanksComponent } from '@protos/blitzkit_static_all_tanks_component'; +import { CatalogAccessor } from 'packages/core/src'; +import { remoteCatalog } from 'packages/website-ue/src/core/blitz/remoteCatalog'; + +const data = await remoteCatalog + .get('BlitzKitAllTanksEntity.blitzkit_all_tanks') + .then((components) => + components.get(BlitzkitAllTanksComponent, 'blitzkitAllTanksComponent'), + ); + +export function Page() { + const tankCatalog = new CatalogAccessor(data.tanks); + + const content = tankCatalog + .get('TankEntity.A92_M60') + .get(TankCatalogComponent, 'tankCatalogComponent'); + + return
;
+}
diff --git a/packages/website-ue/src/pages/[...locale]/tanks/index.astro b/packages/website-ue/src/pages/[...locale]/tanks/index.astro
index 197c70125..96ea63bd0 100644
--- a/packages/website-ue/src/pages/[...locale]/tanks/index.astro
+++ b/packages/website-ue/src/pages/[...locale]/tanks/index.astro
@@ -1,23 +1,9 @@
 ---
-import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
-import { BlitzKitAllTankEntities } from '@protos/blitzkit_static_all_tank_entities';
-import { unpackedMetadata } from '../../../core/blitz/unpackedMetadata';
+import { Page } from './_index';
+
 export { getStaticPaths } from '../index.astro';
 
 const { locale } = Astro.props;
-
-const allTanks = unpackedMetadata
-  .get('CatalogItemsGroupEntity.all_tanks')
-  .get(CatalogItemsComponent, 'catalogItemsGroupComponent');
-
-const allTankEntities = unpackedMetadata
-  .get('BlitzKitAllTankEntities.all_tanks')
-  .get(BlitzKitAllTankEntities, 'blitzkitAllTankEntitiesComponent');
 ---
 
-
-{JSON.stringify(allTankEntities.tanks.map(tank=>({
-  tank: tank.catalog_id,
-  components: tank.components.map(component=>component.key)
-})), null, 2)}
-
+ diff --git a/packages/website-ue/src/pages/api/catalog/[item].pb.ts b/packages/website-ue/src/pages/api/catalog/[item].pb.ts new file mode 100644 index 000000000..8f1ced2c3 --- /dev/null +++ b/packages/website-ue/src/pages/api/catalog/[item].pb.ts @@ -0,0 +1,18 @@ +import type { APIRoute, GetStaticPaths, GetStaticPathsItem } from 'astro'; +import { catalog } from 'packages/website-ue/src/core/blitz/catalog'; + +export const getStaticPaths: GetStaticPaths = () => { + const paths: GetStaticPathsItem[] = []; + + for (const item in catalog.items) { + paths.push({ params: { item } }); + } + + return paths; +}; + +export const GET: APIRoute<{}, { item: string }> = ({ params }) => { + return new Response(catalog.get(params.item).encode(), { + headers: { 'Content-Type': 'application/octet-stream' }, + }); +}; diff --git a/submodules/blitzkit-closed b/submodules/blitzkit-closed index 0ce4f6181..add1ddf24 160000 --- a/submodules/blitzkit-closed +++ b/submodules/blitzkit-closed @@ -1 +1 @@ -Subproject commit 0ce4f618188affdb1c3904589d59fac0293fdf76 +Subproject commit add1ddf2479fe8bdd31be550dcea84f28761a207