Files
blitzkit/packages/scripts/src/buildAssets/consumableProvisionIcons.ts
T

181 lines
5.4 KiB
TypeScript
Raw Normal View History

2025-10-23 21:22:21 -05:00
import { existsSync } from "fs";
import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readStringDVPL } from "../../src/core/blitz/readStringDVPL";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants";
import { ConsumablesCommon, ProvisionsCommon } from "./definitions";
2024-01-17 11:34:27 -06:00
interface Mappings {
Header: { version: number };
StyleSheets: {
selectors: string[];
2025-10-23 21:22:21 -05:00
properties: { "bg-sprite": string };
2024-01-17 11:34:27 -06:00
}[];
}
2024-08-14 14:04:06 -05:00
const listItemsPattern = /<items path="(.+)\.xml"\/>/g;
2024-08-27 14:40:43 -05:00
export async function consumableProvisionIcons() {
2025-10-23 21:22:21 -05:00
console.log("Building consumable and provision icons...");
2024-08-14 14:04:06 -05:00
2025-10-23 21:22:21 -05:00
using uploader = new AssetUploader("consumable and provision icons");
2024-08-14 14:04:06 -05:00
const styles = [
2025-10-23 21:22:21 -05:00
"UI/Styles/Lobby/Inventory/Event/InventoryBigStyles.yaml",
"UI/Styles/Lobby/Inventory/Event/InventoryNormalStyles.yaml",
"UI/Styles/Lobby/Inventory/InventoryNormalStyles.yaml",
"UI/Screens3/Lobby/Inventory/Equipment/EquipmentItemImage.style.yaml",
"UI/Screens/Battle/Styles/BattleEquipmentStyles.yaml",
2024-08-14 14:04:06 -05:00
];
const styleSheets = await Promise.all(
styles.map(async (path) =>
Object.values(
2025-10-23 21:22:21 -05:00
(
await readYAMLDVPL<Mappings>(`${DATA}/${path}`)
).StyleSheets
)
)
2024-08-14 14:04:06 -05:00
).then((array) => array.flat());
2024-01-17 11:34:27 -06:00
2024-08-14 14:04:06 -05:00
for (const match of (
await readStringDVPL(
2025-10-23 21:22:21 -05:00
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml`
2024-08-14 14:04:06 -05:00
)
).matchAll(listItemsPattern)) {
const consumablesCommon = await readXMLDVPL<{
root: ConsumablesCommon;
2025-01-14 19:22:41 -06:00
}>(`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`);
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
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...`
2024-01-17 11:34:27 -06:00
);
2025-10-23 21:22:21 -05:00
continue;
}
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
const configPath = styleSheet.properties["bg-sprite"]
.replace("~res:/", "")
.replace(".psd", "")
.replace(".txt", "");
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
if (existsSync(`${DATA}/${configPath}.packed.webp`)) {
const image = sharp(
await readDVPLFile(`${DATA}/${configPath}.packed.webp`)
);
const content = await image.trim({ threshold: 100 }).toBuffer();
2024-08-14 14:04:06 -05:00
2025-10-23 21:22:21 -05:00
await uploader.add({
path: `icons/consumables/${consumable.id}.webp`,
content,
});
} else {
const consumablesTexture = sharp(
await readDVPLFile(
`${`${DATA}/${configPath}`
.split("/")
.slice(0, -1)
.join("/")}/texture0.packed.webp`
)
);
const sizes = (await readStringDVPL(`${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();
2024-08-14 14:04:06 -05:00
2025-10-23 21:22:21 -05:00
await uploader.add({
path: `icons/consumables/${consumable.id}.webp`,
content,
});
}
}
2024-08-14 14:04:06 -05:00
}
for (const match of (
await readStringDVPL(
2025-10-23 21:22:21 -05:00
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml`
2024-08-14 14:04:06 -05:00
)
).matchAll(listItemsPattern)) {
const provisionsCommon = await readXMLDVPL<{
root: ProvisionsCommon;
2025-01-14 19:22:41 -06:00
}>(`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`);
2025-10-23 21:22:21 -05:00
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...`
2024-02-12 19:24:34 -06:00
);
2025-10-23 21:22:21 -05:00
continue;
}
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
const configPath = styleSheet.properties["bg-sprite"]
.replace("~res:/", "")
.replace(".psd", "")
.replace(".txt", "");
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
if (existsSync(`${DATA}/${configPath}.packed.webp`)) {
const image = sharp(
await readDVPLFile(`${DATA}/${configPath}.packed.webp`)
);
const content = await image.trim({ threshold: 100 }).toBuffer();
2024-01-17 11:34:27 -06:00
2025-10-23 21:22:21 -05:00
await uploader.add({
path: `icons/provisions/${provision.id}.webp`,
content,
});
} else {
const provisionsTexture = sharp(
await readDVPLFile(
`${`${DATA}/${configPath}`
.split("/")
.slice(0, -1)
.join("/")}/texture0.packed.webp`
)
);
const sizes = (await readStringDVPL(`${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();
2024-01-25 13:51:30 -06:00
2025-10-23 21:22:21 -05:00
await uploader.add({
path: `icons/provisions/${provision.id}.webp`,
content,
});
}
}
2024-08-14 14:04:06 -05:00
}
2024-01-25 13:51:30 -06:00
2025-10-23 21:22:21 -05:00
await uploader.flush();
2024-01-17 11:34:27 -06:00
}