feat: module selection

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
TrèsAbhiandCopilot committed 2026-04-28 16:56:38 -05:00
1 parent 272824a72f
commit 4b7b8b3392
9 files changed
+109 -38

No files matched your search

+4 -1
View File
@@ -136,9 +136,10 @@
"name": "varuna",
"dependencies": {
"@types/lodash-es": "^4.17.12",
"@types/react": "^19.2.14",
"immer": "^10.1.3",
"lodash-es": "^4.17.21",
"react": "^19.1.1",
"react": "^19.2.5",
},
},
"packages/website": {
@@ -3217,6 +3218,8 @@
"utif2/pako": ["[email protected]", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
"varuna/react": ["[email protected]", "", {}, "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA=="],
"vscode-json-languageservice/jsonc-parser": ["[email protected]", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="],
"which-builtin-type/isarray": ["[email protected]", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+2 -1
View File
@@ -4,8 +4,9 @@
"main": "src/index.ts",
"dependencies": {
"@types/lodash-es": "^4.17.12",
"@types/react": "^19.2.14",
"immer": "^10.1.3",
"lodash-es": "^4.17.21",
"react": "^19.1.1"
"react": "^19.2.5"
}
}
+2 -2
View File
@@ -11,7 +11,7 @@ export class Varuna<Type, Arguments = void> {
constructor(
private creator: Type | ((...args: Arguments[]) => Type),
private persistence?: string
private persistence?: string,
) {
if (typeof creator !== "function") this.initialize(creator);
}
@@ -100,7 +100,7 @@ export class Varuna<Type, Arguments = void> {
}
use<Slice = Type>(
slicer: (state: Type) => Slice = (state) => state as unknown as Slice
slicer: (state: Type) => Slice = (state) => state as unknown as Slice,
) {
return this.useDeferred(slicer, slicer(this.state));
}
@@ -1,4 +1,4 @@
import type { Tank } from "@blitzkit/closed/protos/blitzkit/tank";
import type { Tank } from "@protos/blitzkit/tank";
import {
ShellUpgradeSingleChange_AttributeName,
TankAttributeChange_AttributeName,
@@ -1,16 +1,26 @@
import type { TankCatalogComponent } from "@protos/blitz_static_tank_component";
import { TerrainHardness } from "./tankState";
import type { Tank } from "@protos/blitzkit/tank";
import { TerrainHardness, type TankState } from "./tankState";
export function createTankState({ tank, id }: Tank) {
const upgrades: Record<string, number> = {};
for (const upgradeLine of tank!.upgrade_lines) {
upgrades[upgradeLine.name] = upgradeLine.stages.length - 1;
}
export function createTankState(tank: TankCatalogComponent) {
return {
stage: tank.upgrade_stages.length,
id,
upgrades,
shell: 0,
isGunDamaged: false,
isHullTraversing: false,
isShooting: false,
isTurretTraversing: false,
speed: 0,
terrainHardness: TerrainHardness.Hard,
isShooting: false,
isGunDamaged: false,
isTurretTraversing: false,
isHullTraversing: false,
isCaughtOnFire: false,
};
} satisfies TankState;
}
@@ -5,13 +5,17 @@ export enum TerrainHardness {
}
export interface TankState {
stage: number;
id: string;
upgrades: Record<string, number>;
shell: number;
speed: number;
isHullTraversing: boolean;
isTurretTraversing: boolean;
terrainHardness: TerrainHardness;
isShooting: boolean;
isGunDamaged: boolean;
terrainHardness: TerrainHardness;
isTurretTraversing: boolean;
isHullTraversing: boolean;
isCaughtOnFire: boolean;
}
@@ -7,28 +7,82 @@ import { characteristicsOrder } from "../../../../core/tankopedia/characteristic
import { computeCharacteristics } from "../../../../core/tankopedia/computeCharacteristics";
import { TerrainHardness } from "../../../../core/tankopedia/tankState";
import { useAwait } from "../../../../hooks/useAwait";
import { useGameStrings } from "../../../../hooks/useGameStrings";
import { LocaleProvider } from "../../../../hooks/useLocale";
import { Tankopedia, TankopediaCompare } from "../../../../stores/tankopedia";
export function Page({ id }: { id: string }) {
interface PageProps {
id: string;
locale: string;
}
export function Page({ id, locale }: PageProps) {
const tank = useAwait(() => api.tank(id), `tank-${id}`);
Tankopedia.useInitialization(tank);
return (
<LocaleProvider locale={locale}>
<Content />
</LocaleProvider>
);
return (
<Suspense fallback={null}>
<Content id={id} />
<Content />
</Suspense>
);
}
function Content({ id }: { id: string }) {
const tank = useAwait(() => api.tank(id), `tank-${id}`);
// const tankList = useAwait(() => api.tankList(), "tank-list");
// const otherTanks = useAwait(() => api.tanks(), "tanks");
Tankopedia.useInitialization(tank.tank!);
function Content() {
const tankEntityGameStrings = useGameStrings("TankEntity");
const protagonist = Tankopedia.use((state) => state.protagonist);
const protagonistTank = useAwait(
() => api.tank(protagonist.id),
`tank-${protagonist.id}`,
);
return (
<>
<h1>{protagonist.id}</h1>
<br />
{protagonistTank.tank!.upgrade_lines.map((line) => {
return (
<>
<h2>
{line.name} ({protagonist.upgrades[line.name]})
</h2>
<div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
{line.stages.map((stage, index) => {
return (
<button
key={stage.tech_name}
onClick={() => {
Tankopedia.mutate((draft) => {
draft.protagonist.upgrades[line.name] = index;
});
}}
>
{protagonist.upgrades[line.name] === index && "✓"}{" "}
{tankEntityGameStrings[stage.display_name]}
</button>
);
})}
</div>
</>
);
})}
</>
);
const compare = Tankopedia.use((state) => state.compare);
const characteristics = useMemo(
() => computeCharacteristics(id, tank, protagonist),
[protagonist]
[protagonist],
);
// const otherCharacteristics = useMemo(
// () =>
@@ -187,7 +241,7 @@ function Content({ id }: { id: string }) {
{TerrainHardness[hardness]}{" "}
{hardness === protagonist.terrainHardness && "(selected)"}
</button>
)
),
)}
</div>
@@ -222,7 +276,7 @@ function Content({ id }: { id: string }) {
>
{TankopediaCompare[c]} {c === compare && "(selected)"}
</button>
)
),
)}
</div>
@@ -242,7 +296,7 @@ function Content({ id }: { id: string }) {
others={[]}
config={config}
/>
)
),
)}
</>
))}
@@ -19,5 +19,5 @@ const { id, locale } = Astro.props;
---
<BaseLayout {locale} accent="violet">
<Page {id} client:load />
<Page {locale} {id} client:load />
</BaseLayout>
+6 -7
View File
@@ -1,4 +1,4 @@
import type { TankCatalogComponent } from "@protos/game/proto/legacy/blitz_static_tank_component";
import type { Tank } from "@protos/blitzkit/tank";
import { Varuna } from "varuna";
import { createTankState } from "../core/tankopedia/createTankState";
import { type TankState } from "../core/tankopedia/tankState";
@@ -14,9 +14,8 @@ export enum TankopediaCompare {
All,
}
export const Tankopedia = new Varuna<Tankopedia, TankCatalogComponent>(
(tank) => ({
compare: TankopediaCompare.TierAndClass,
protagonist: createTankState(tank),
}),
);
export const Tankopedia = new Varuna<Tankopedia, Tank>((tank) => ({
compare: TankopediaCompare.TierAndClass,
protagonist: createTankState(tank),
}));