feat: game strings in characteristics

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
TrèsAbhiandCopilot committed 2026-04-29 10:17:53 -05:00
1 parent 249f62759e
commit e3db886923
7 files changed
+105 -37

No files matched your search

@@ -1,6 +1,6 @@
import type { CharacteristicOutput } from "../core/tankopedia/characteristics";
import type { CharacteristicRenderConfig } from "../core/tankopedia/characteristicsOrder";
import { renderCharacteristic } from "../core/tankopedia/renderCharacteristic";
import { renderCharacteristic } from "../hooks/useCharacteristicRenderer";
interface Props {
characteristic: CharacteristicOutput;
@@ -18,6 +18,7 @@ export interface CharacteristicRenderConfig {
name: CharacteristicName;
decimals?: number;
units?: string;
strings?: string;
render?: (output: CharacteristicOutput) => string;
}
@@ -35,7 +36,7 @@ export const characteristicsOrder: CharacteristicsOrder = [
{
group: "meta",
order: [
{ name: "name" },
{ name: "name", strings: "TankEntity" },
{ name: "tier" },
{
name: "nation",
@@ -1,29 +0,0 @@
import type { CharacteristicOutput } from "./characteristics";
import type { CharacteristicRenderConfig } from "./characteristicsOrder";
export function renderCharacteristic(
characteristic: CharacteristicOutput,
config: CharacteristicRenderConfig
): string | null {
if (characteristic === null) return null;
if (config.render) return config.render(characteristic);
if (typeof characteristic === "number") {
if (Number.isFinite(characteristic)) {
if (config.decimals === undefined) {
return characteristic.toString();
}
return characteristic.toFixed(config.decimals);
}
return `${characteristic < 0 ? "-" : ""}∞`;
}
if (typeof characteristic === "string") {
return characteristic;
}
return characteristic.map((c) => renderCharacteristic(c, config)).join(", ");
}
@@ -0,0 +1,59 @@
import { useMemo } from "react";
import type { CharacteristicOutput } from "../core/tankopedia/characteristics";
import {
characteristicsOrder,
type CharacteristicRenderConfig,
} from "../core/tankopedia/characteristicsOrder";
import { useGameStrings } from "./useGameStrings";
export function useCharacteristicRenderer() {
const groups = useMemo(() => {
const groups: string[] = [];
for (const group of characteristicsOrder) {
for (const item of group.order) {
if ("strings" in item && item.strings) {
groups.push(item.strings);
}
}
}
return groups;
}, []);
const tankEntityStrings = useGameStrings(groups);
function renderCharacteristic(
characteristic: CharacteristicOutput,
config: CharacteristicRenderConfig,
): string | null {
if (characteristic === null) return null;
if (config.render) return config.render(characteristic);
if (typeof characteristic === "number") {
if (Number.isFinite(characteristic)) {
if (config.decimals === undefined) {
return characteristic.toString();
}
return characteristic.toFixed(config.decimals);
}
return `${characteristic < 0 ? "-" : ""}∞`;
}
if (typeof characteristic === "string") {
if (config.strings) {
return tankEntityStrings[characteristic];
}
return characteristic;
}
return characteristic
.map((c) => renderCharacteristic(c, config))
.join(", ");
}
return renderCharacteristic;
}
@@ -2,11 +2,24 @@ import { api } from "../core/api/dynamic";
import { useAwait } from "./useAwait";
import { useLocale } from "./useLocale";
export function useGameStrings(group: string) {
export function useGameStrings(groups: string | string[]) {
const resolved = typeof groups === "string" ? [groups] : groups;
const locale = useLocale();
const strings = useAwait(
() => api.groupedGameStrings(locale, group, true),
`game-strings-${locale}-${group}`,
async () => {
const accumulated: Record<string, string> = {};
await Promise.all(
resolved.map(async (group) => {
const strings = await api.groupedGameStrings(locale, group, true);
Object.assign(accumulated, strings);
}),
);
return accumulated;
},
`game-strings-${locale}-${resolved.sort().join("-")}`,
);
return strings;
}
@@ -2,8 +2,10 @@ import { Grade } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_st
import { StageParameters_StageType } from "@blitzkit/closed/protos/game/proto/legacy/blitz_static_tank_upgrade_single_stage";
import { useMemo } from "react";
import { api } from "../../../../core/api/dynamic";
import { characteristicsOrder } from "../../../../core/tankopedia/characteristicsOrder";
import { computeCharacteristics } from "../../../../core/tankopedia/computeCharacteristics";
import { useAwait } from "../../../../hooks/useAwait";
import { useCharacteristicRenderer } from "../../../../hooks/useCharacteristicRenderer";
import { useGameStrings } from "../../../../hooks/useGameStrings";
import { LocaleProvider } from "../../../../hooks/useLocale";
import { Tankopedia } from "../../../../stores/tankopedia";
@@ -27,6 +29,7 @@ export function Page({ id, locale }: PageProps) {
function Content() {
const tankEntityGameStrings = useGameStrings("TankEntity");
const renderCharacteristic = useCharacteristicRenderer();
const protagonist = Tankopedia.use((state) => state.protagonist);
const protagonistTank = useAwait(
@@ -146,11 +149,32 @@ function Content() {
<h2>characteristics</h2>
{Object.entries(characteristics).map(([key, value]) => (
{/* {Object.entries(characteristics).map(([key, value]) => (
<p>
{key}: {value}
</p>
))}
))} */}
{characteristicsOrder.map((group) => {
return (
<>
<h3>{group.group}</h3>
{group.order.map((item) => {
if ("toy" in item) {
return <span>toy: {item.toy}</span>;
}
return (
<span>
{item.name}:{" "}
{renderCharacteristic(characteristics[item.name], item)}
</span>
);
})}
</>
);
})}
</>
);