mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: provision filtering
This commit is contained in:
1 parent
5bbe93bcec
commit
8f8c91e0b0
7 files changed
+123
-24
No files matched your search
@@ -21,9 +21,10 @@ export const POI = {
|
||||
optionalDevicesImage:
|
||||
'Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp',
|
||||
consumablesCommon: 'XML/item_defs/vehicles/common/consumables/common.xml',
|
||||
provisionsCommon: 'XML/item_defs/vehicles/common/provisions/common.xml',
|
||||
consumableIcons: 'Gfx/UI/InventoryIcons/Big/Consumables',
|
||||
provisionIcons: 'Gfx/UI/InventoryIcons/Big/Provisions',
|
||||
equipmentItemImageMappings:
|
||||
'UI/Screens3/Lobby/Inventory/Equipment/EquipmentItemImage.style.yaml',
|
||||
provisionsCommon: 'XML/item_defs/vehicles/common/provisions/common.xml',
|
||||
defaultCamoIcon: 'Gfx/UI/Hangar/IconCamouflage.webp',
|
||||
} as const;
|
||||
+78
-13
@@ -16,15 +16,20 @@ interface Mappings {
|
||||
}[];
|
||||
}
|
||||
|
||||
export async function consumableIcons(production: boolean) {
|
||||
console.log('Building consumable icons...');
|
||||
export async function consumableProvisionIcons(production: boolean) {
|
||||
console.log('Building consumable and provision icons...');
|
||||
|
||||
const changes: FileChange[] = [];
|
||||
const texture = sharp(
|
||||
const consumablesTexture = sharp(
|
||||
await readDVPLFile(
|
||||
`${DATA}/${POI.consumableIcons}/texture0.packed.webp.dvpl`,
|
||||
),
|
||||
);
|
||||
const provisionsTexture = sharp(
|
||||
await readDVPLFile(
|
||||
`${DATA}/${POI.provisionIcons}/texture0.packed.webp.dvpl`,
|
||||
),
|
||||
);
|
||||
|
||||
const equipmentItemImageMappings = await readYAMLDVPL<Mappings>(
|
||||
`${DATA}/${POI.equipmentItemImageMappings}.dvpl`,
|
||||
@@ -32,6 +37,9 @@ export async function consumableIcons(production: boolean) {
|
||||
const consumablesCommon = await readXMLDVPL<{
|
||||
root: ConsumablesProvisionsCommon;
|
||||
}>(`${DATA}/${POI.consumablesCommon}.dvpl`);
|
||||
const provisionsCommon = await readXMLDVPL<{
|
||||
root: ConsumablesProvisionsCommon;
|
||||
}>(`${DATA}/${POI.provisionsCommon}.dvpl`);
|
||||
const styleSheets = Object.values(equipmentItemImageMappings.StyleSheets);
|
||||
|
||||
await Promise.all(
|
||||
@@ -43,20 +51,21 @@ export async function consumableIcons(production: boolean) {
|
||||
);
|
||||
|
||||
if (!styleSheet) {
|
||||
throw new Error(
|
||||
`No style sheet found for consumable ${consumable.icon}`,
|
||||
console.warn(
|
||||
`No style sheet found for consumable ${consumable.icon}; skipping...`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const configPath = styleSheet.properties['bg-sprite']
|
||||
.replace('~res:/', '')
|
||||
.replace('.psd', '.txt');
|
||||
.replace('.psd', '')
|
||||
.replace('.txt', '');
|
||||
|
||||
if (configPath.startsWith('Gfx/Shared')) {
|
||||
const imagePath = `${configPath}.packed.webp.dvpl`;
|
||||
const content = (await readDVPLFile(`${DATA}/${imagePath}`)).toString(
|
||||
'base64',
|
||||
);
|
||||
const content = (
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`)
|
||||
).toString('base64');
|
||||
|
||||
changes.push({
|
||||
path: `icons/consumables/${consumable.id}.webp`,
|
||||
@@ -64,12 +73,12 @@ export async function consumableIcons(production: boolean) {
|
||||
content,
|
||||
});
|
||||
} else {
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.dvpl`))
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||
.split('\n')[4]
|
||||
.split(' ')
|
||||
.map(Number);
|
||||
const content = (
|
||||
await texture
|
||||
await consumablesTexture
|
||||
.clone()
|
||||
.extract({
|
||||
left: sizes[0],
|
||||
@@ -89,5 +98,61 @@ export async function consumableIcons(production: boolean) {
|
||||
}),
|
||||
);
|
||||
|
||||
await commitAssets('consumable icons', changes, production);
|
||||
await Promise.all(
|
||||
Object.values(provisionsCommon.root).map(async (provision) => {
|
||||
const styleSheet = styleSheets.find((styleSheet) =>
|
||||
styleSheet.selectors.includes(
|
||||
`.equipment_item.${provision.icon} * .equipment-img`,
|
||||
),
|
||||
);
|
||||
|
||||
if (!styleSheet) {
|
||||
console.warn(
|
||||
`No style sheet found for provision ${provision.icon}; skipping...`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const configPath = styleSheet.properties['bg-sprite']
|
||||
.replace('~res:/', '')
|
||||
.replace('.psd', '')
|
||||
.replace('.txt', '');
|
||||
|
||||
if (configPath.startsWith('Gfx/Shared')) {
|
||||
const content = (
|
||||
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`)
|
||||
).toString('base64');
|
||||
|
||||
changes.push({
|
||||
path: `icons/provisions/${provision.id}.webp`,
|
||||
encoding: 'base64',
|
||||
content,
|
||||
});
|
||||
} else {
|
||||
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||
.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()
|
||||
).toString('base64');
|
||||
|
||||
changes.push({
|
||||
path: `icons/provisions/${provision.id}.webp`,
|
||||
encoding: 'base64',
|
||||
content,
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
await commitAssets('consumable and provision icons', changes, production);
|
||||
}
|
||||
@@ -201,8 +201,8 @@ export interface ConsumablesProvisionsCommon {
|
||||
category: string;
|
||||
tags: string;
|
||||
vehicleFilter?: {
|
||||
include: { vehicle: ConsumablesFilter };
|
||||
exclude?: { vehicle: ConsumablesFilter };
|
||||
include: { vehicle: ConsumablesVehicleFilter; nations?: string };
|
||||
exclude?: { vehicle: ConsumablesVehicleFilter; nations?: string };
|
||||
};
|
||||
script: {
|
||||
'#text': string;
|
||||
@@ -215,7 +215,7 @@ export interface ConsumablesProvisionsCommon {
|
||||
};
|
||||
}
|
||||
|
||||
type ConsumablesFilter =
|
||||
type ConsumablesVehicleFilter =
|
||||
| { minLevel: number; maxLevel: number }
|
||||
| { name: string }
|
||||
| { extendedTags: string };
|
||||
@@ -669,6 +669,13 @@ export async function definitions(production: boolean) {
|
||||
ids: includeRaw.name.split(' ').map((key) => tankStringIdMap[key]),
|
||||
});
|
||||
} else throw new SyntaxError('Unhandled include type');
|
||||
|
||||
if (consumable.vehicleFilter?.include.nations) {
|
||||
consumableDefinitions[consumable.id].include.push({
|
||||
type: 'nation',
|
||||
nations: consumable.vehicleFilter.include.nations.split(' '),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeRaw) {
|
||||
@@ -687,6 +694,13 @@ export async function definitions(production: boolean) {
|
||||
) as TankFilterDefinitionCategory[],
|
||||
});
|
||||
} else throw new SyntaxError('Unhandled exclude type');
|
||||
|
||||
if (consumable.vehicleFilter?.exclude?.nations) {
|
||||
consumableDefinitions[consumable.id].exclude!.push({
|
||||
type: 'nation',
|
||||
nations: consumable.vehicleFilter.exclude.nations.split(' '),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Object.entries({
|
||||
@@ -736,6 +750,13 @@ export async function definitions(production: boolean) {
|
||||
ids: includeRaw.name.split(' ').map((key) => tankStringIdMap[key]),
|
||||
});
|
||||
} else throw new SyntaxError('Unhandled include type');
|
||||
|
||||
if (provision.vehicleFilter?.include.nations) {
|
||||
provisionDefinitions[provision.id].include.push({
|
||||
type: 'nation',
|
||||
nations: provision.vehicleFilter.include.nations.split(' '),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeRaw) {
|
||||
@@ -754,6 +775,13 @@ export async function definitions(production: boolean) {
|
||||
) as TankFilterDefinitionCategory[],
|
||||
});
|
||||
} else throw new SyntaxError('Unhandled exclude type');
|
||||
|
||||
if (provision.vehicleFilter?.exclude?.nations) {
|
||||
provisionDefinitions[provision.id].exclude!.push({
|
||||
type: 'nation',
|
||||
nations: provision.vehicleFilter.exclude.nations.split(' '),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Object.entries({
|
||||
|
||||
@@ -2,7 +2,7 @@ import { config } from 'dotenv';
|
||||
import { argv } from 'process';
|
||||
import { camouflageIcons } from './camouflageIcons';
|
||||
import { circleFlags } from './circleFlags';
|
||||
import { consumableIcons } from './consumableIcons';
|
||||
import { consumableProvisionIcons } from './consumableProvisionIcons';
|
||||
import { definitions } from './definitions';
|
||||
import { equipmentIcons } from './equipmentIcons';
|
||||
import { buildModuleIcons } from './moduleIcons';
|
||||
@@ -33,7 +33,7 @@ const methods = [
|
||||
buildShellIcons,
|
||||
buildModuleIcons,
|
||||
equipmentIcons,
|
||||
consumableIcons,
|
||||
consumableProvisionIcons,
|
||||
camouflageIcons,
|
||||
];
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ export function Configure() {
|
||||
<Camouflage />
|
||||
<Provisions />
|
||||
</Flex>
|
||||
|
||||
{/*
|
||||
<Flex gap="4" direction="column">
|
||||
<Heading size="5">Provisions</Heading>
|
||||
</Flex> */}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -15,6 +15,9 @@ export function checkConsumableProvisionInclusivity(
|
||||
case 'ids':
|
||||
return rule.ids.includes(tank.id);
|
||||
|
||||
case 'nation':
|
||||
return rule.nations.includes(tank.nation);
|
||||
|
||||
case 'category':
|
||||
throw new SyntaxError('Category filtering found in include rule');
|
||||
}
|
||||
@@ -27,6 +30,9 @@ export function checkConsumableProvisionInclusivity(
|
||||
case 'ids':
|
||||
return rule.ids.includes(tank.id);
|
||||
|
||||
case 'nation':
|
||||
return rule.nations.includes(tank.nation);
|
||||
|
||||
case 'category':
|
||||
return rule.categories.some((category) => {
|
||||
switch (category) {
|
||||
|
||||
@@ -15,6 +15,10 @@ export type TankFilterDefinition =
|
||||
| {
|
||||
type: 'category';
|
||||
categories: TankFilterDefinitionCategory[];
|
||||
}
|
||||
| {
|
||||
type: 'nation';
|
||||
nations: string[];
|
||||
};
|
||||
|
||||
export interface ConsumableEntry {
|
||||
|
||||
Reference in new issue
Block a user