mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-26 20:19:50 +01:00
tank icons
This commit is contained in:
1 parent
94c3608ca7
commit
9813459310
3 files changed
+104
-38
No files matched your search
@@ -5,44 +5,6 @@ import { AssetUploader } from "../core/github/assetUploader";
|
|||||||
import { vfs } from "./constants";
|
import { vfs } from "./constants";
|
||||||
import type { VehicleDefinitionList } from "./definitions";
|
import type { VehicleDefinitionList } from "./definitions";
|
||||||
|
|
||||||
async function extractPackedTankIcon(packedBuffer: Buffer, context: string) {
|
|
||||||
const texture = sharp(packedBuffer);
|
|
||||||
const spriteRect = parsePackedSpriteRect(packedBuffer);
|
|
||||||
|
|
||||||
if (!spriteRect) {
|
|
||||||
throw new Error(`Missing RIFF sprite bounds for ${context}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [left, top, width, height] = spriteRect;
|
|
||||||
const bounds = [left, top, width, height];
|
|
||||||
|
|
||||||
if (!bounds.every(Number.isInteger)) {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid RIFF sprite bounds for ${context}: ${bounds.join(" ")}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata = await texture.metadata();
|
|
||||||
|
|
||||||
if (metadata.width === undefined || metadata.height === undefined) {
|
|
||||||
throw new Error(`Failed to read image dimensions for ${context}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
left < 0 ||
|
|
||||||
top < 0 ||
|
|
||||||
width <= 0 ||
|
|
||||||
height <= 0 ||
|
|
||||||
left + width > metadata.width ||
|
|
||||||
top + height > metadata.height
|
|
||||||
) {
|
|
||||||
throw new Error(
|
|
||||||
`Out-of-bounds RIFF sprite for ${context}: ${bounds.join(" ")} in ${metadata.width}x${metadata.height}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await texture.extract({ left, top, width, height }).toBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function tankIcons() {
|
export async function tankIcons() {
|
||||||
console.log("Building tank icons...");
|
console.log("Building tank icons...");
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { api } from "../../../../core/blitzkit/api";
|
||||||
|
import { mixStaticPaths } from "../../../../core/blitzkit/mixStaticPaths";
|
||||||
|
import { getStaticPaths as _getStaticPaths } from "../../_index";
|
||||||
|
|
||||||
|
export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => {
|
||||||
|
const tanks = await api.tankDefinitions();
|
||||||
|
|
||||||
|
return Object.values(tanks.tanks).map((tank) => ({
|
||||||
|
params: { id: tank.id },
|
||||||
|
props: { id: tank.id },
|
||||||
|
}));
|
||||||
|
});
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import {
|
||||||
|
NATION_IDS,
|
||||||
|
type TankParameters,
|
||||||
|
type VehicleDefinitionList,
|
||||||
|
} from "@blitzkit/core";
|
||||||
|
import type { APIContext } from "astro";
|
||||||
|
import sharp from "sharp";
|
||||||
|
import { parsePackedSpriteRect } from "../../../../../core/blitz/parsePackedSpriteRect";
|
||||||
|
import { vfs } from "../../../../../core/blitzkit/vfs";
|
||||||
|
|
||||||
|
export { getStaticPaths } from "../_index";
|
||||||
|
|
||||||
|
export async function GET({ props }: APIContext<{ id: number }>) {
|
||||||
|
const nations = await vfs
|
||||||
|
.dir(`Data/XML/item_defs/vehicles`)
|
||||||
|
.then((files) => files.filter((nation) => nation !== "common"));
|
||||||
|
|
||||||
|
for (const nation of nations) {
|
||||||
|
const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
|
||||||
|
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const tankKey in tanks.root) {
|
||||||
|
const tank = tanks.root[tankKey];
|
||||||
|
|
||||||
|
if (tankKey.includes("tutorial_bot")) continue;
|
||||||
|
|
||||||
|
const nationVehicleId = tank.id;
|
||||||
|
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
|
||||||
|
|
||||||
|
if (id !== props.id) continue;
|
||||||
|
|
||||||
|
const parameters = await vfs.yaml<TankParameters>(
|
||||||
|
`Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
|
||||||
|
);
|
||||||
|
const bigPath = `Data/${parameters.resourcesPath.bigIconPath
|
||||||
|
.replace(/~res:\//, "")
|
||||||
|
.replace(/\..+/, "")}.packed.webp`;
|
||||||
|
const big = await extractPackedTankIcon(
|
||||||
|
await vfs.file(bigPath),
|
||||||
|
`tank ${tankKey} big`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Response(big);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function extractPackedTankIcon(
|
||||||
|
bytes: Uint8Array,
|
||||||
|
context: string,
|
||||||
|
) {
|
||||||
|
const texture = sharp(bytes);
|
||||||
|
const spriteRect = parsePackedSpriteRect(bytes);
|
||||||
|
|
||||||
|
if (!spriteRect) {
|
||||||
|
throw new Error(`Missing RIFF sprite bounds for ${context}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [left, top, width, height] = spriteRect;
|
||||||
|
const bounds = [left, top, width, height];
|
||||||
|
|
||||||
|
if (!bounds.every(Number.isInteger)) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid RIFF sprite bounds for ${context}: ${bounds.join(" ")}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata = await texture.metadata();
|
||||||
|
|
||||||
|
if (metadata.width === undefined || metadata.height === undefined) {
|
||||||
|
throw new Error(`Failed to read image dimensions for ${context}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
left < 0 ||
|
||||||
|
top < 0 ||
|
||||||
|
width <= 0 ||
|
||||||
|
height <= 0 ||
|
||||||
|
left + width > metadata.width ||
|
||||||
|
top + height > metadata.height
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Out-of-bounds RIFF sprite for ${context}: ${bounds.join(" ")} in ${metadata.width}x${metadata.height}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buffer = await texture.extract({ left, top, width, height }).toBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user