feat: meta section

This commit is contained in:
TrèsAbhi committed 2025-12-26 14:14:29 -06:00
1 parent 1d3cb95b89
commit 40a1eb861d
14 files changed
+141 -18

No files matched your search

+1
View File
@@ -186,6 +186,7 @@
"@blitzkit/closed": "workspace:*", "@blitzkit/closed": "workspace:*",
"@blitzkit/core": "workspace:*", "@blitzkit/core": "workspace:*",
"@blitzkit/i18n": "workspace:*", "@blitzkit/i18n": "workspace:*",
"@bufbuild/protobuf": "^2.10.2",
"@fontsource-variable/inter": "^5.2.8", "@fontsource-variable/inter": "^5.2.8",
"@radix-ui/colors": "^3.0.0", "@radix-ui/colors": "^3.0.0",
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
+3 -2
View File
@@ -56,7 +56,7 @@ for (const root of roots) {
"--ts_proto_opt=unrecognizedEnum=false", "--ts_proto_opt=unrecognizedEnum=false",
"--ts_proto_opt=snakeToCamel=false", "--ts_proto_opt=snakeToCamel=false",
`--ts_proto_out=${root}`, `--ts_proto_out=${root}`,
`-I=${root}`, ...roots.map((root) => `-I=${root}`),
].join(" "); ].join(" ");
while (true) { while (true) {
@@ -66,8 +66,9 @@ for (const root of roots) {
const newLine = ` ${root}/${file}`; const newLine = ` ${root}/${file}`;
if (command.length + newLine.length < MAX_COMMAND_LENGTH) { if (command.length + newLine.length < MAX_COMMAND_LENGTH) {
const file = files.pop();
command += newLine; command += newLine;
console.log(` ${files.pop()}`); // console.log(` ${file}`);
} else { } else {
break; break;
} }
+1
View File
@@ -16,6 +16,7 @@
"@blitzkit/closed": "workspace:*", "@blitzkit/closed": "workspace:*",
"@blitzkit/core": "workspace:*", "@blitzkit/core": "workspace:*",
"@blitzkit/i18n": "workspace:*", "@blitzkit/i18n": "workspace:*",
"@bufbuild/protobuf": "^2.10.2",
"@fontsource-variable/inter": "^5.2.8", "@fontsource-variable/inter": "^5.2.8",
"@radix-ui/colors": "^3.0.0", "@radix-ui/colors": "^3.0.0",
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
+2 -2
View File
@@ -1,4 +1,4 @@
import type { TankCatalogComponent } from "@protos/blitz_static_tank_component"; import type { Tank } from "../../protos/tank";
import type { Tanks } from "../../protos/tanks"; import type { Tanks } from "../../protos/tanks";
export abstract class AbstractAPI { export abstract class AbstractAPI {
@@ -9,5 +9,5 @@ export abstract class AbstractAPI {
prefix?: string prefix?: string
): Promise<Record<string, string>>; ): Promise<Record<string, string>>;
abstract tank(id: string): Promise<TankCatalogComponent>; abstract tank(id: string): Promise<Tank>;
} }
+2 -2
View File
@@ -1,4 +1,4 @@
import { TankCatalogComponent } from "@protos/blitz_static_tank_component"; import { Tank } from "../../protos/tank";
import { AbstractAPI } from "./abstract"; import { AbstractAPI } from "./abstract";
export class ClientAPI extends AbstractAPI { export class ClientAPI extends AbstractAPI {
@@ -7,6 +7,6 @@ export class ClientAPI extends AbstractAPI {
const buffer = await response.arrayBuffer(); const buffer = await response.arrayBuffer();
const array = new Uint8Array(buffer); const array = new Uint8Array(buffer);
return TankCatalogComponent.decode(array); return Tank.decode(array);
} }
} }
+4 -2
View File
@@ -2,6 +2,7 @@ import type { MetadataAccessor } from "@blitzkit/closed";
import { sluggify } from "@blitzkit/core"; import { sluggify } from "@blitzkit/core";
import type { RemoteStorageComponent } from "@protos/blitz_static_remote_storage_component"; import type { RemoteStorageComponent } from "@protos/blitz_static_remote_storage_component";
import { parse } from "yaml"; import { parse } from "yaml";
import type { Tank } from "../../protos/tank";
import type { TanksEntry } from "../../protos/tanks"; import type { TanksEntry } from "../../protos/tanks";
import { AbstractAPI } from "./abstract"; import { AbstractAPI } from "./abstract";
@@ -115,8 +116,9 @@ export class ServerAPI extends AbstractAPI {
async tank(id: string) { async tank(id: string) {
const item = this.metadata.item(`TankEntity.${id}`); const item = this.metadata.item(`TankEntity.${id}`);
const tankCatalog = item.TankCatalog(); const tank = item.TankCatalog();
const compensation = item.Compensation();
return tankCatalog; return { tank, compensation } satisfies Tank;
} }
} }
@@ -1,5 +1,6 @@
import { TankClass } from "@blitzkit/core"; import { TankClass } from "@blitzkit/core";
import type { TankCatalogComponent } from "@protos/blitz_static_tank_component"; import type { CompensationComponent } from "@protos/blitz_static_compensation_component";
import { type TankCatalogComponent } from "@protos/blitz_static_tank_component";
import { import {
ShellUpgrageSingleChange_AttributeName, ShellUpgrageSingleChange_AttributeName,
StageParameters, StageParameters,
@@ -9,7 +10,7 @@ import { radToDeg } from "three/src/math/MathUtils.js";
import { applyPitchYawLimits } from "./applyPitchYawLimits"; import { applyPitchYawLimits } from "./applyPitchYawLimits";
import { TerrainHardness, type TankState } from "./tankState"; import { TerrainHardness, type TankState } from "./tankState";
export type CharacteristicOutput = number | number[] | null; export type CharacteristicOutput = number | number[] | string | null;
type Characteristic = (helpers: { type Characteristic = (helpers: {
characteristic: (name: CharacteristicName) => CharacteristicOutput; characteristic: (name: CharacteristicName) => CharacteristicOutput;
@@ -20,6 +21,8 @@ type Characteristic = (helpers: {
state: TankState; state: TankState;
tank: TankCatalogComponent; tank: TankCatalogComponent;
parameters: StageParameters; parameters: StageParameters;
compensation: CompensationComponent;
id: string;
}) => CharacteristicOutput; }) => CharacteristicOutput;
export type CharacteristicName = keyof typeof characteristics; export type CharacteristicName = keyof typeof characteristics;
@@ -391,4 +394,28 @@ export const characteristics = {
volume() { volume() {
return -Infinity; return -Infinity;
}, },
nation({ tank }) {
return tank.nation;
},
name({ tank }) {
return tank.name!.value;
},
tier({ tank }) {
return tank.tier_catalog_id;
},
type({ tank }) {
return tank.tank_type;
},
id({ id }) {
return id;
},
compensation({ compensation }) {
return compensation.compensation?.currency_reward?.amount ?? null;
},
} satisfies Record<string, Characteristic>; } satisfies Record<string, Characteristic>;
@@ -1,4 +1,13 @@
import type { CharacteristicName } from "./characteristics"; import {
Nation,
TankClass,
TankType,
} from "@protos/blitz_static_tank_component";
import {
GunType,
type CharacteristicName,
type CharacteristicOutput,
} from "./characteristics";
export enum BetterDirection { export enum BetterDirection {
Higher, Higher,
@@ -9,6 +18,7 @@ export interface CharacteristicRenderConfig {
name: CharacteristicName; name: CharacteristicName;
decimals?: number; decimals?: number;
units?: string; units?: string;
render?: (output: CharacteristicOutput) => string;
} }
type CharacteristicsOrder = { type CharacteristicsOrder = {
@@ -22,10 +32,42 @@ type CharacteristicsOrder = {
}[]; }[];
export const characteristicsOrder: CharacteristicsOrder = [ export const characteristicsOrder: CharacteristicsOrder = [
{
group: "meta",
order: [
{ name: "name" },
{ name: "tier" },
{
name: "nation",
render(output) {
return Nation[output as Nation];
},
},
{
name: "class",
render(output) {
return TankClass[output as TankClass];
},
},
{
name: "type",
render(output) {
return TankType[output as TankType];
},
},
{ name: "compensation" },
{ name: "id" },
],
},
{ {
group: "firepower", group: "firepower",
order: [ order: [
{ name: "gun_type" }, {
name: "gun_type",
render(output) {
return GunType[output as GunType];
},
},
{ name: "dpm", decimals: 0, units: "hp_min" }, { name: "dpm", decimals: 0, units: "hp_min" },
{ name: "reload", decimals: 2, units: "s" }, { name: "reload", decimals: 2, units: "s" },
{ name: "reloads", decimals: 2, units: "s" }, { name: "reloads", decimals: 2, units: "s" },
@@ -1,3 +1,4 @@
import type { CompensationComponent } from "@protos/blitz_static_compensation_component";
import type { TankCatalogComponent } from "@protos/blitz_static_tank_component"; import type { TankCatalogComponent } from "@protos/blitz_static_tank_component";
import { import {
ShellUpgrageSingleChange_AttributeName, ShellUpgrageSingleChange_AttributeName,
@@ -12,7 +13,9 @@ import {
import type { TankState } from "./tankState"; import type { TankState } from "./tankState";
export function computeCharacteristics( export function computeCharacteristics(
id: string,
tank: TankCatalogComponent, tank: TankCatalogComponent,
compensation: CompensationComponent,
state: TankState state: TankState
) { ) {
const parameters = aggregateStageParameters( const parameters = aggregateStageParameters(
@@ -89,6 +92,8 @@ export function computeCharacteristics(
state, state,
tank, tank,
parameters, parameters,
id,
compensation,
}); });
computed[name] = value; computed[name] = value;
} }
@@ -7,6 +7,8 @@ export function renderCharacteristic(
): string | null { ): string | null {
if (characteristic === null) return null; if (characteristic === null) return null;
if (config.render) return config.render(characteristic);
if (typeof characteristic === "number") { if (typeof characteristic === "number") {
if (Number.isFinite(characteristic)) { if (Number.isFinite(characteristic)) {
if (config.decimals === undefined) { if (config.decimals === undefined) {
@@ -19,5 +21,9 @@ export function renderCharacteristic(
return `${characteristic < 0 ? "-" : ""}∞`; return `${characteristic < 0 ? "-" : ""}∞`;
} }
if (typeof characteristic === "string") {
return characteristic;
}
return characteristic.map((c) => renderCharacteristic(c, config)).join(", "); return characteristic.map((c) => renderCharacteristic(c, config)).join(", ");
} }
@@ -0,0 +1,27 @@
import { Nation } from "@protos/blitz_static_tank_component";
import type { APIContext, GetStaticPaths } from "astro";
const enums = {
nation: Nation,
};
export const getStaticPaths = (() => {
return Object.keys(enums).map((name) => ({ params: { enum: name } }));
}) satisfies GetStaticPaths;
/**
* The one who wipes, swipes.
*/
export function GET({
params,
}: APIContext<never, { enum: keyof typeof enums }>) {
const map: Record<number, string> = {};
for (const key in enums[params.enum]) {
const value = enums[params.enum][key];
if (typeof value !== "string") continue;
map[key] = value;
}
return Response.json(map);
}
@@ -1,6 +1,6 @@
import { TankCatalogComponent } from "@protos/blitz_static_tank_component";
import type { APIContext, GetStaticPaths } from "astro"; import type { APIContext, GetStaticPaths } from "astro";
import { api } from "../../../core/api/dynamic"; import { api } from "../../../core/api/dynamic";
import { Tank } from "../../../protos/tank";
export const getStaticPaths = (async () => { export const getStaticPaths = (async () => {
const { tanks } = await api.tanks(); const { tanks } = await api.tanks();
@@ -13,5 +13,5 @@ export const getStaticPaths = (async () => {
*/ */
export async function GET({ params }: APIContext<never, { id: string }>) { export async function GET({ params }: APIContext<never, { id: string }>) {
const tank = await api.tank(params.id); const tank = await api.tank(params.id);
return new Response(TankCatalogComponent.encode(tank).finish()); return new Response(Tank.encode(tank).finish());
} }
@@ -17,13 +17,13 @@ export function Page({ id }: { id: string }) {
} }
function Content({ id }: { id: string }) { function Content({ id }: { id: string }) {
const tank = useAwait(() => api.tank(id), `tank-${id}`); const { tank, compensation } = useAwait(() => api.tank(id), `tank-${id}`);
Tankopedia.useInitialization(tank.upgrade_stages.length); Tankopedia.useInitialization(tank!.upgrade_stages.length);
const protagonist = Tankopedia.use((state) => state.protagonist); const protagonist = Tankopedia.use((state) => state.protagonist);
const { characteristics, parameters } = useMemo( const { characteristics, parameters } = useMemo(
() => computeCharacteristics(tank, protagonist), () => computeCharacteristics(id, tank!, compensation!, protagonist),
[protagonist] [protagonist]
); );
@@ -34,7 +34,7 @@ function Content({ id }: { id: string }) {
<br /> <br />
<div style={{ display: "flex", flexWrap: "wrap" }}> <div style={{ display: "flex", flexWrap: "wrap" }}>
{times(tank.upgrade_stages.length + 1, (index) => ( {times(tank!.upgrade_stages.length + 1, (index) => (
<button <button
key={index} key={index}
onClick={() => { onClick={() => {
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
package blitzkit;
import "blitz_static_compensation_component.proto";
import "blitz_static_tank_component.proto";
message Tank {
blitz_static_tank_component.TankCatalogComponent tank = 1;
blitz_static_compensation_component.CompensationComponent compensation = 2;
}