feat: custom components

This commit is contained in:
TrèsAbhi committed 2025-05-27 12:39:04 -05:00
1 parent bc6bb4f10e
commit 69b13fd33a
9 files changed
+164 -58

No files matched your search

@@ -3,9 +3,12 @@ import { Any } from '@protos/google/protobuf/any';
import { MessageFns } from '../protos';
export class CatalogItemAccessor {
public id: string;
private components: Record<string, Any> = {};
constructor(item: CatalogItem) {
this.id = item.catalog_id;
for (const component of item.components) {
if (
component.value === undefined ||
@@ -18,6 +21,11 @@ export class CatalogItemAccessor {
}
}
addComponent(key: string, value: Any) {
this.components[key] = value;
return this;
}
get<Type>(Message: MessageFns<Type>, component: string) {
if (component in this.components) {
return Message.decode(this.components[component].value);
@@ -25,4 +33,19 @@ export class CatalogItemAccessor {
throw new Error(`Unknown component: ${component}`);
}
pack() {
const item: CatalogItem = { catalog_id: this.id, components: [] };
for (const componentId in this.components) {
const component = this.components[componentId];
item.components.push({
key: componentId,
value: { type_url: component.type_url, component },
});
}
return item;
}
}
@@ -1,5 +1,8 @@
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 { BlitzKitTankCatalogComponent } from '@protos/blitzkit_static_tank_component';
import { CatalogItemAccessor } from './catalogItemAccessor';
export class UnpackedMetadataAccessor {
@@ -20,6 +23,70 @@ export class UnpackedMetadataAccessor {
throw new Error(`Unknown catalog ID: ${item}`);
}
addCatalogItem(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,
'catalogItemsGroupComponent',
);
}
injectBlitzkit() {
this.injectBlitzKitTankComponents();
this.injectBlitzKitAllTankEntities();
return this;
}
injectBlitzKitTankComponents() {
for (const item of this.getAllTanks().catalog_items) {
const tank = this.get(item);
const value = BlitzKitTankCatalogComponent.encode({
id: 'TEST',
set: 'TEST',
}).finish();
tank.addComponent('blitzkitTankCatalogComponent', {
type_url:
'./blitzkit_static_tank_component.BlitzKitTankCatalogComponent',
value,
});
}
}
injectBlitzKitAllTankEntities() {
const allTanksEntities: BlitzKitAllTankEntities = { 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(),
);
}
}
export class DiscreteMetadataAccessor {
+38 -30
View File
@@ -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/unreal/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,9 +1,20 @@
import { use } from 'react';
import {
LocaleProvider,
useLocale,
type LocaleAcceptorProps,
} from '../hooks/useLocale';
export function TestComponent() {
const content = use(
fetch('https://example.com/').then((response) => response.text()),
);
function Content() {
const { locale, strings } = useLocale();
const content = JSON.stringify(strings, null, 2);
return <pre children={content} />;
return <span>{strings.common.units.deg_s}</span>;
}
export function TestComponent({ locale }: LocaleAcceptorProps) {
return (
<LocaleProvider locale={locale}>
<Content />
</LocaleProvider>
);
}
@@ -6,4 +6,4 @@ export const unpackedMetadata = new UnpackedMetadataAccessor(
await requestAutoProxyClient<GetPackedMetadataAsyncResponse>(
'GetPackedMetadataAsyncRequest',
).then(unpackMetadata),
);
).injectBlitzkit();
+6 -4
View File
@@ -23,15 +23,17 @@ export function LocaleProvider({ locale, children }: LocaleProviderProps) {
);
}
const strings = import.meta.glob('../../../i18n/strings/*.json', {
import: 'default',
});
const cache = new Map<string, Promise<BlitzKitStrings>>();
function loadLocale(locale: string) {
if (cache.has(locale)) return cache.get(locale)!;
const promise = fetch(`/api/strings/${locale}.json`).then((response) => {
if (!response.ok) throw new Error('Failed to load locale');
return response.json();
});
const promise = strings[
`../../../i18n/strings/${locale}.json`
]() as Promise<BlitzKitStrings>;
cache.set(locale, promise);
@@ -1,6 +1,6 @@
---
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
import { TestComponent } from '../../../components/TestComponent';
import { BlitzKitAllTankEntities } from '@protos/blitzkit_static_all_tank_entities';
import { unpackedMetadata } from '../../../core/blitz/unpackedMetadata';
export { getStaticPaths } from '../index.astro';
@@ -9,6 +9,15 @@ const { locale } = Astro.props;
const allTanks = unpackedMetadata
.get('CatalogItemsGroupEntity.all_tanks')
.get(CatalogItemsComponent, 'catalogItemsGroupComponent');
const allTankEntities = unpackedMetadata
.get('BlitzKitAllTankEntities.all_tanks')
.get(BlitzKitAllTankEntities, 'blitzkitAllTankEntitiesComponent');
---
<TestComponent />
<pre>
{JSON.stringify(allTankEntities.tanks.map(tank=>({
tank: tank.catalog_id,
components: tank.components.map(component=>component.key)
})), null, 2)}
</pre>
@@ -1,14 +0,0 @@
import locales from '@blitzkit/i18n/locales.json' with { type: 'json' };
import type { APIRoute, GetStaticPaths, GetStaticPathsItem } from 'astro';
import { getStrings } from 'packages/website-ue/src/core/i18n/getStrings';
export const getStaticPaths: GetStaticPaths = () => {
return locales.supported.map(
({ locale }) => ({ params: { locale } }) satisfies GetStaticPathsItem,
);
};
export const GET: APIRoute = async ({ params, request }) => {
const strings = await getStrings(params.locale!);
return Response.json(strings);
};