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