infrastructure for inline vfs and clients

This commit is contained in:
tresabhi committed 2026-07-31 20:48:33 -05:00
1 parent d81d885767
commit 39745dd475
19 files changed
+133 -64

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
import { GameDefinitions } from "../../protos";
export abstract class BlitzKitAPI {
abstract game(): Promise<GameDefinitions>;
}
+9
View File
@@ -0,0 +1,9 @@
import { fetchPB } from "../../protobuf";
import { GameDefinitions } from "../../protos";
import { BlitzKitAPI } from "./base";
export class ClientBlitzKitAPI extends BlitzKitAPI {
game() {
return fetchPB("/api/definitions/game.pb", GameDefinitions);
}
}
+3
View File
@@ -0,0 +1,3 @@
export * from "./base";
export * from "./client";
export * from "./server";
+69
View File
@@ -0,0 +1,69 @@
import {
AbstractVFS,
AvailableNationsYaml,
SquadBattleTypeStylesYaml,
} from "@blitzkit/core";
import { GameDefinitions } from "../../protos";
import { BlitzKitAPI } from "./base";
export class ServerBlitzKitAPI extends BlitzKitAPI {
vfs: AbstractVFS;
constructor(vfs: AbstractVFS) {
super();
this.vfs = vfs;
}
async game() {
const versionFile = await this.vfs.text("Data/version.txt");
const version = versionFile.split(" ")[0];
const availableNations = await this.vfs.yaml<AvailableNationsYaml>(
"Data/available_nations.yaml",
);
const nations = availableNations.available_nations;
const game: GameDefinitions = {
version,
nations,
gameModes: {},
roles: {},
};
const squadBattleTypeStyles =
await this.vfs.yaml<SquadBattleTypeStylesYaml>(
`Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
);
for (const match of squadBattleTypeStyles.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
/"(\d+)" -> "(battleType\/([a-zA-Z]+))"/g,
)) {
const id = Number(match[1]);
const name = getString(match[2]);
gameModeNativeNames[match[3]] = id;
game.gameModes[id] = {
name,
};
}
Object.entries(combatRoles).forEach(([, value]) => {
gameDefinitions.roles[value.id] = { provisions: [], consumables: [] };
value.default_abilities.forEach((ability) => {
if (ability in consumableNativeNames) {
gameDefinitions.roles[value.id].consumables.push(
consumableNativeNames[ability],
);
} else if (ability in provisionNativeNames) {
gameDefinitions.roles[value.id].provisions.push(
provisionNativeNames[ability],
);
} else throw new Error(`Unknown ability ${ability}`);
});
});
return game;
}
}
@@ -1,7 +0,0 @@
import { fetchPB } from '../protobuf';
import { GameDefinitions } from '../protos';
import { asset } from './asset';
export function fetchGameDefinitions() {
return fetchPB(asset('definitions/game.pb'), GameDefinitions);
}
+2 -1
View File
@@ -7,15 +7,16 @@ export * from "./averageDefinitions";
export * from "./coefficient";
export * from "./consumableDefinitions";
// export * from './context';
export * from "./api";
export * from "./createDefaultSkills";
export * from "./degressiveStat";
export * from "./discoveredIdDefinitions";
export * from "./emblemURL";
export * from "./equipmentDefinitions";
export * from "./eventManager";
export * from "./gameDefinitions";
export * from "./getArchivedLatestSeasonNumber";
export * from "./sluggify";
export * from "./vfs";
// export * from './getArchivedRatingInfo';
export * from "./getArchivedRatingLeaderboard";
// export * from './getArchivedRatingMidnightLeaderboard';
+5
View File
@@ -0,0 +1,5 @@
export * from "./abstract";
export * from "./local";
export * from "./mixed";
export * from "./steam";
export * from "./zip";
File renamed without changes.
@@ -0,0 +1,3 @@
export interface AvailableNationsYaml {
available_nations: string[];
}
+4 -2
View File
@@ -1,2 +1,4 @@
export * from './glossary';
export * from './tanksStats';
export * from "./availableNationsYaml";
export * from "./glossary";
export * from "./squadBattleTypeStylesYaml";
export * from "./tanksStats";
@@ -0,0 +1,9 @@
export interface SquadBattleTypeStylesYaml {
Prototypes: {
components: {
UIDataLocalBindingsComponent: {
data: [string, string, string][];
};
};
}[];
}
@@ -11,7 +11,6 @@ import {
Equalizer,
EquipmentDefinitions,
EquipmentSlot,
GameDefinitions,
GunDefinition,
I18nString,
MapDefinitions,
@@ -491,20 +490,6 @@ export interface MapAlly {
points: Array<number[]>;
}
interface AvailableNationsYaml {
available_nations: string[];
}
export interface SquadBattleTypeStyles {
Prototypes: {
components: {
UIDataLocalBindingsComponent: {
data: [string, string, string][];
};
};
}[];
}
type CombatRolesYaml = Record<
string,
{
@@ -548,14 +533,7 @@ export async function definitions() {
console.log("Building definitions...");
const uploader = new AssetUploader("definitions");
const gameDefinitions: GameDefinitions = {
version: (await vfs.text("Data/version.txt")).split(" ")[0],
nations: (
await vfs.yaml<AvailableNationsYaml>("Data/available_nations.yaml")
).available_nations,
gameModes: {},
roles: {},
};
const tankDefinitions: TankDefinitions = { tanks: {} };
const camouflageDefinitions: CamouflageDefinitions = { camouflages: {} };
const modelDefinitions: ModelDefinitions = { models: {} };
@@ -673,10 +651,10 @@ export async function definitions() {
`Data/camouflages.yaml`,
);
const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages);
const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStyles>(
const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStylesYaml>(
`Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
);
const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStyles>(
const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStylesYaml>(
`Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`,
);
const gameModeNativeNames: Record<string, number> = {};
@@ -708,12 +686,8 @@ export async function definitions() {
/"(\d+)" -> "(battleType\/([a-zA-Z]+))"/g,
)) {
const id = Number(match[1]);
const name = getString(match[2]);
gameModeNativeNames[match[3]] = id;
gameDefinitions.gameModes[id] = {
name,
};
}
for (const match of gameTypeSelectorStyles.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
@@ -1767,22 +1741,6 @@ export async function definitions() {
}
});
Object.entries(combatRoles).forEach(([, value]) => {
gameDefinitions.roles[value.id] = { provisions: [], consumables: [] };
value.default_abilities.forEach((ability) => {
if (ability in consumableNativeNames) {
gameDefinitions.roles[value.id].consumables.push(
consumableNativeNames[ability],
);
} else if (ability in provisionNativeNames) {
gameDefinitions.roles[value.id].provisions.push(
provisionNativeNames[ability],
);
} else throw new Error(`Unknown ability ${ability}`);
});
});
Object.entries(avatar.root.skillsByClasses).forEach(([tankClass, skills]) => {
skillDefinitions.classes[
blitzTankClassToBlitzkit[tankClass as BlitzTankClass]
@@ -1798,10 +1756,6 @@ export async function definitions() {
};
});
await uploader.add({
content: GameDefinitions.encode(gameDefinitions).finish(),
path: "definitions/game.pb",
});
await uploader.add({
content: TankDefinitions.encode(tankDefinitions).finish(),
path: "definitions/tanks.pb",
@@ -1,16 +1,16 @@
import sharp from "sharp";
import { AssetUploader } from "../core/github/assetUploader";
import { vfs } from "./constants";
import { SquadBattleTypeStyles } from "./definitions";
import { SquadBattleTypeStylesYaml } from "./definitions";
export async function gameModeBanners() {
console.log("Building game mode banners...");
using uploader = new AssetUploader("game mode banners");
const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStyles>(
const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStylesYaml>(
`Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`,
);
const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStyles>(
const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStylesYaml>(
`Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`,
);
const bannerMatches: { name: string; path: string }[] = [];
+3 -2
View File
@@ -1,7 +1,8 @@
---
import { assertSecret, fetchGameDefinitions } from "@blitzkit/core";
import { assertSecret } from "@blitzkit/core";
import { Box, Code, Flex, Heading, Link, Text } from "@radix-ui/themes";
import packageJson from "../../../../package.json";
import { api } from "../core/blitzkit/api";
import { getStrings } from "../core/i18n/getStrings";
import { LinkI18n } from "./LinkI18n";
import { LocaleSwitcherThemeWrapper } from "./LocaleSwitcher";
@@ -10,7 +11,7 @@ export interface Props {
locale: string;
}
const gameDefinitions = await fetchGameDefinitions();
const gameDefinitions = await api.game();
const PUBLIC_ASSET_BRANCH = assertSecret(import.meta.env.PUBLIC_BRANCH);
const { locale } = Astro.props;
const strings = getStrings(locale);
+15
View File
@@ -0,0 +1,15 @@
import {
ClientBlitzKitAPI,
ServerBlitzKitAPI,
type BlitzKitAPI,
} from "@blitzkit/core";
let _api: BlitzKitAPI;
if (import.meta.env.SSR) {
_api = new ServerBlitzKitAPI();
} else {
_api = new ClientBlitzKitAPI();
}
export const api = _api;