diff --git a/packages/scripts/src/buildAssets/consumableProvisionIcons.ts b/packages/scripts/src/buildAssets/consumableProvisionIcons.ts deleted file mode 100644 index a934a5ad8..000000000 --- a/packages/scripts/src/buildAssets/consumableProvisionIcons.ts +++ /dev/null @@ -1,189 +0,0 @@ -import sharp from "sharp"; -import { parsePackedSpriteRect } from "../core/blitz/parsePackedSpriteRect"; -import { AssetUploader } from "../core/github/assetUploader"; -import { vfs } from "./constants"; -import { ConsumablesCommon, ProvisionsCommon } from "./definitions"; - -interface Mappings { - Header: { version: number }; - StyleSheets: { - selectors: string[]; - properties: { "bg-sprite": string }; - }[]; -} - -const listItemsPattern = //g; - -export async function consumableProvisionIcons() { - console.log("Building consumable and provision icons..."); - - using uploader = new AssetUploader("consumable and provision icons"); - const styles = [ - "UI/Styles/Lobby/Inventory/InventoryNormalStyles.yaml", - "UI/Styles/Lobby/Inventory/Event/InventoryBigStyles.yaml", - "UI/Styles/Lobby/Inventory/Event/InventoryNormalStyles.yaml", - "UI/Screens3/Lobby/Inventory/Equipment/EquipmentItemImage.style.yaml", - "UI/Screens/Battle/Styles/BattleEquipmentStyles.yaml", - ]; - const styleSheets = await Promise.all( - styles.map(async (path) => - Object.values((await vfs.yaml(`Data/${path}`)).StyleSheets), - ), - ).then((array) => array.flat()); - - for (const match of ( - await vfs.text(`Data/XML/item_defs/vehicles/common/consumables/list.xml`) - ).matchAll(listItemsPattern)) { - const consumablesCommon = await vfs.xml<{ - root: ConsumablesCommon; - }>(`Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`); - - for (const consumable of Object.values(consumablesCommon.root)) { - const styleSheet = styleSheets.find((styleSheet) => - styleSheet.selectors.some((selector) => - selector.includes(`${consumable.icon} `), - ), - ); - - if (!styleSheet) { - console.warn( - `No style sheet found for consumable ${consumable.icon}; skipping...`, - ); - continue; - } - - const configPath = styleSheet.properties["bg-sprite"] - .replace("~res:/", "") - .replace(".psd", "") - .replace(".txt", ""); - - if (await vfs.resolve(`Data/${configPath}.packed.webp`)) { - const packedBuffer = await vfs.file(`Data/${configPath}.packed.webp`); - const consumablesTexture = sharp(packedBuffer); - const sizes = parsePackedSpriteRect(packedBuffer); - let content: Buffer; - - if (sizes) { - content = await extractPackedIcon( - consumablesTexture, - sizes, - `consumable ${consumable.icon}`, - ); - } else { - content = await consumablesTexture.trim({ threshold: 80 }).toBuffer(); - } - - await uploader.add({ - path: `icons/consumables/${consumable.id}.webp`, - content, - }); - } else { - const consumablesTexture = sharp( - await vfs.file( - `${`Data/${configPath}` - .split("/") - .slice(0, -1) - .join("/")}/texture0.packed.webp`, - ), - ); - const sizes = (await vfs.text(`Data/${configPath}.txt`)) - .split("\n")[4] - .split(" ") - .map(Number); - const content = await consumablesTexture - .clone() - .extract({ - left: sizes[0], - top: sizes[1], - width: sizes[2], - height: sizes[3], - }) - .toBuffer(); - - await uploader.add({ - path: `icons/consumables/${consumable.id}.webp`, - content, - }); - } - } - } - - for (const match of ( - await vfs.text(`Data/XML/item_defs/vehicles/common/provisions/list.xml`) - ).matchAll(listItemsPattern)) { - const provisionsCommon = await vfs.xml<{ - root: ProvisionsCommon; - }>(`Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`); - - for (const provision of Object.values(provisionsCommon.root)) { - const styleSheet = styleSheets.find((styleSheet) => - styleSheet.selectors.some((selector) => - selector.includes(`${provision.icon} `), - ), - ); - - if (!styleSheet) { - console.warn( - `No style sheet found for provision ${provision.icon}; skipping...`, - ); - continue; - } - - const configPath = styleSheet.properties["bg-sprite"] - .replace("~res:/", "") - .replace(".psd", "") - .replace(".txt", ""); - - if (await vfs.resolve(`Data/${configPath}.packed.webp`)) { - const packedBuffer = await vfs.file(`Data/${configPath}.packed.webp`); - const provisionsTexture = sharp(packedBuffer); - const sizes = parsePackedSpriteRect(packedBuffer); - let content: Buffer; - - if (sizes) { - content = await extractPackedIcon( - provisionsTexture, - sizes, - `provision ${provision.icon}`, - ); - } else { - content = await provisionsTexture.trim({ threshold: 80 }).toBuffer(); - } - - await uploader.add({ - path: `icons/provisions/${provision.id}.webp`, - content, - }); - } else { - const provisionsTexture = sharp( - await vfs.file( - `${`Data/${configPath}` - .split("/") - .slice(0, -1) - .join("/")}/texture0.packed.webp`, - ), - ); - const sizes = (await vfs.text(`Data/${configPath}.txt`)) - .split("\n")[4] - .split(" ") - .map(Number); - const content = await provisionsTexture - .clone() - .extract({ - left: sizes[0], - top: sizes[1], - width: sizes[2], - height: sizes[3], - }) - .toBuffer(); - - await uploader.add({ - path: `icons/provisions/${provision.id}.webp`, - content, - }); - } - } - } - - await uploader.flush(); -} diff --git a/packages/website/src/pages/[...chunk_api]/icons/provisions/[id].webp.ts b/packages/website/src/pages/[...chunk_api]/icons/provisions/[id].webp.ts new file mode 100644 index 000000000..db38f389a --- /dev/null +++ b/packages/website/src/pages/[...chunk_api]/icons/provisions/[id].webp.ts @@ -0,0 +1,112 @@ +import type { ProvisionsCommon } from "@blitzkit/core"; +import type { APIContext, GetStaticPathsItem } from "astro"; +import sharp from "sharp"; +import { extractPackedIcon } from "../../../../core/blitz/extractPackedIcon"; +import { parsePackedSpriteRect } from "../../../../core/blitz/parsePackedSpriteRect"; +import { mixStaticPaths } from "../../../../core/blitzkit/mixStaticPaths"; +import { vfs } from "../../../../core/blitzkit/vfs"; +import { getStaticPaths as _getStaticPaths } from "../../_index"; + +interface Mappings { + Header: { version: number }; + StyleSheets: { + selectors: string[]; + properties: { "bg-sprite": string }; + }[]; +} + +const listItemsPattern = //g; + +export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => { + const paths: GetStaticPathsItem[] = []; + + const styles = [ + "UI/Styles/Lobby/Inventory/InventoryNormalStyles.yaml", + "UI/Styles/Lobby/Inventory/Event/InventoryBigStyles.yaml", + "UI/Styles/Lobby/Inventory/Event/InventoryNormalStyles.yaml", + "UI/Screens3/Lobby/Inventory/Equipment/EquipmentItemImage.style.yaml", + "UI/Screens/Battle/Styles/BattleEquipmentStyles.yaml", + ]; + const styleSheets = await Promise.all( + styles.map(async (path) => + Object.values((await vfs.yaml(`Data/${path}`)).StyleSheets), + ), + ).then((array) => array.flat()); + + for (const match of ( + await vfs.text(`Data/XML/item_defs/vehicles/common/provisions/list.xml`) + ).matchAll(listItemsPattern)) { + const provisionsCommon = await vfs.xml<{ + root: ProvisionsCommon; + }>(`Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`); + + for (const provision of Object.values(provisionsCommon.root)) { + const styleSheet = styleSheets.find((styleSheet) => + styleSheet.selectors.some((selector) => + selector.includes(`${provision.icon} `), + ), + ); + + if (!styleSheet) { + console.warn( + `No style sheet found for provision ${provision.icon}; skipping...`, + ); + continue; + } + + const path = styleSheet.properties["bg-sprite"] + .replace("~res:/", "") + .replace(".psd", "") + .replace(".txt", ""); + + paths.push({ + props: { path }, + params: { id: provision.id }, + }); + } + } + + return paths; +}); + +export async function GET({ props }: APIContext<{ path: string }>) { + let buffer: Buffer; + + if (await vfs.resolve(`Data/${props.path}.packed.webp`)) { + const packedBuffer = await vfs.file(`Data/${props.path}.packed.webp`); + const provisionsTexture = sharp(packedBuffer); + const sizes = parsePackedSpriteRect(packedBuffer); + + if (sizes) { + buffer = await extractPackedIcon(provisionsTexture, sizes); + } else { + buffer = await provisionsTexture.trim({ threshold: 80 }).toBuffer(); + } + } else { + const provisionsTexture = sharp( + await vfs.file( + `${`Data/${props.path}` + .split("/") + .slice(0, -1) + .join("/")}/texture0.packed.webp`, + ), + ); + const sizes = (await vfs.text(`Data/${props.path}.txt`)) + .split("\n")[4] + .split(" ") + .map(Number); + buffer = await provisionsTexture + .clone() + .extract({ + left: sizes[0], + top: sizes[1], + width: sizes[2], + height: sizes[3], + }) + .toBuffer(); + } + + const bytes = new Uint8Array(buffer); + + return new Response(bytes); +}