Files
svn/tech/client/交接文档/谭健交接文档/Script/ProjectScript/Subpackage/subpackage/Config.ts
2025-08-04 10:46:00 +08:00

282 lines
12 KiB
TypeScript

import xlsx from 'node-xlsx'
import fs from 'fs';
import path from 'path';
import { Utils } from './Utils';
const ROOM_COUNT = 7;
export type SubpackageConfig = {
key: string,
name: string,
des: string,
uuids: string[],
}
type RoomFishData = { [filePath: string]: { [roomType: number]: boolean } };
type SubpackageInfoData = { [name: string]: { key: string, name: string, des: string; } };
type SubpackageContentDataItem = { path: string, type: number }[]
type SubpackageContentData = { [name: string]: SubpackageContentDataItem };
export class Config {
private readonly assetsDir: string;
private readonly uuidMap: { db: string, uuid: string, dest: string }[];
private readonly gameConfig: any;
private readonly packageMap: { [name: string]: string[] };
private readonly subpackageInfoData: SubpackageInfoData;
private readonly subpackageContentData: SubpackageContentData;
private subpackageConfigs: SubpackageConfig[];
constructor(projectDir: string, xlsxPath: string, xxtea?: string) {
this.assetsDir = path.join(projectDir, 'assets');
const buildJson = fs.readFileSync(path.join(projectDir, 'build', 'build.json'));
const buildData = JSON.parse(buildJson.toString());
this.uuidMap = buildData.uuid;
const gameConfigPath = path.join(this.assetsDir, 'resources', 'conf', 'allConf.json');
const gameConfigContent = fs.readFileSync(gameConfigPath);
this.gameConfig = JSON.parse(gameConfigContent.toString());
this.packageMap = {}
for (let db in buildData.pac) {
const url: string = buildData.pac[db];
const name = url.substring(url.lastIndexOf('\\') + 1, url.lastIndexOf('.'));
this.packageMap[name] = this.packageMap[name] || [];
this.packageMap[name].push(db);
}
this.subpackageContentData = {};
const data = xlsx.parse(xlsxPath);
for (const item of data) {
switch (item.name) {
case 'Subpackage':
this.subpackageInfoData = this.decodeSubpackageInfoData(item.data as string[][]);
break;
default:
this.subpackageContentData[item.name] = this.initializeSubpackageData(item.data as string[][]);
break;
}
}
}
private dataArrayToObjectArray(data: any[][]): any[] {
const title: string[] = data.shift()!;
const objArray: { [title: string]: string }[] = [];
for (const dataItem of data) {
const dataObj: { [title: string]: string } = {}
for (let i = 0, length = title.length; i < length; i++) {
const key: string = title[i];
if (!key) break;
dataObj[key] = dataItem[i];
}
objArray.push(dataObj);
}
return objArray;
}
private decodeSubpackageInfoData(data: string[][]): SubpackageInfoData {
const subpackageInfoData: SubpackageInfoData = {}
data.splice(1, 1);//排除说明行
const objArray = this.dataArrayToObjectArray(data);
for (const obj of objArray) {
obj.name && (subpackageInfoData[obj.key] = { key: obj.key, name: obj.name, des: obj.des });
}
return subpackageInfoData;
}
private initializeSubpackageData(data: string[][]): SubpackageContentDataItem {
const files: SubpackageContentDataItem = [];
data.splice(1, 1);//排除说明行
const objArray = this.dataArrayToObjectArray(data);
for (const obj of objArray) {
const path: string = obj.path;
const type: number = parseInt(obj.type);
files.push({ path, type });
}
return files;
}
private getUUIDsInPath(filePath: string, uuids?: { db: string, uuid: string }[]): { db: string, uuid: string }[] {
uuids = uuids || [];
this.uuidMap.forEach(value => {
const db = value.db.substring(12);//"db://assets/".length
if (!db.startsWith(filePath)) return;
if (uuids.findIndex(item => item.uuid === value.uuid) >= 0) return;
uuids.push(value);
});
return uuids;
}
private getUUIDsByRegExp(regExp: RegExp, uuids?: { db: string, uuid: string }[]): { db: string, uuid: string }[] {
uuids = uuids || [];
this.uuidMap.forEach(value => {
const db = value.db.substring(12);//"db://assets/".length
if (!regExp.test(db)) return;
if (uuids.findIndex(item => item.uuid === value.uuid) >= 0) return;
uuids.push(value);
});
return uuids;
}
private updatePackageAssets(uuids?: { db: string, uuid: string }[]): { db: string, uuid: string }[] {
for (const fileName in this.packageMap) {
const packageDBs = this.packageMap[fileName];
let match = true;
const removedUUIDs: { db: string, uuid: string }[] = [];
for (const packageDB of packageDBs) {
const index = uuids.findIndex(value => value.db === packageDB);
match = index >= 0;
if (match) {
removedUUIDs.push(...uuids.splice(index, 1));
} else {
uuids.push(...removedUUIDs);
match = false;
break;
}
}
match && uuids.push({ db: null, uuid: fileName });
}
return uuids;
}
//通过鱼属性表读取相关资源所属的房间
private decodeRoomFishData(): RoomFishData {
const filesRoomData: RoomFishData = {};
const fishAttribute = this.dataArrayToObjectArray(this.gameConfig['FishAttribute']);
for (const fish of fishAttribute) {
//房间数据
const fishName: string = fish.name;
if (!fishName) continue;
//处理鱼资源、鱼技能资源
this.updateRoomFishData(filesRoomData, `resources/anim/clip/fish/${fishName}`, fish);//鱼动画
this.updateRoomFishData(filesRoomData, `res/anim/texture/fish/${fishName}`, fish);;//鱼动画纹理
this.updateRoomFishData(filesRoomData, `resources/spine/fish/play/${fishName}`, fish);//鱼技能Spine
this.updateRoomFishData(filesRoomData, `res/spine/fish/play/${fishName}`, fish);//鱼技能Spine
//处理背景资源
// const backgroundString: string | null = fish.Background
// if (backgroundString) {
// const background = backgroundString.split('|');
// switch (background[0]) {
// case '1':
// this.updateRoomFishData(filesRoomData, `resources/texture/mainScene/bg/${background[1]}`, fish);//鱼背景静态图
// break;
// case '2':
// }
// }
}
return filesRoomData;
}
private updateRoomFishData(container: RoomFishData, key: string, fish: any): void {
const exitsData = container[key] || {};
for (let i = 1; i <= ROOM_COUNT; i++) {
exitsData[i] = exitsData[i] || (fish[`room${i}`] === 1);
}
container[key] = exitsData;
}
private initExcelSubpackage(config: SubpackageConfig[]): void {
const fileRoomData: RoomFishData = this.decodeRoomFishData();
Utils.log(`fileRoomData: ${JSON.stringify(fileRoomData)}`, Utils.LogLevel.Particular);
for (const key in this.subpackageContentData) {
Utils.log(`-------------------------------------------Decode package [${key}] config---------------------------------------------------`, Utils.LogLevel.Particular);
const uuids: { db: string, uuid: string }[] = [];
const files = this.subpackageContentData[key];
const roomTypes: number[] = [];
const excludeRoomTypes: number[] = [];
for (const file of files) {
switch (file.type) {
case 1:
{
Utils.log(`Add path: ${file.path}`, Utils.LogLevel.Particular);
this.getUUIDsInPath(file.path, uuids);
}
break;
case 2:
{
Utils.log(`Add path: ${file.path}`, Utils.LogLevel.Particular);
const regexp = new RegExp(file.path, 'i');
this.getUUIDsByRegExp(regexp, uuids);
}
break;
case 3:
{
const roomType = parseInt(file.path);
roomTypes.indexOf(roomType) >= 0 || roomTypes.push(roomType);
}
break;
case 4:
{
const roomType = parseInt(file.path);
excludeRoomTypes.indexOf(roomType) >= 0 || excludeRoomTypes.push(roomType);
}
break;
}
}
if (roomTypes.length || excludeRoomTypes.length) {
for (const filePath in fileRoomData) {
let isSubFile = true;
const data = fileRoomData[filePath];
for (let i = 0; i < roomTypes.length && isSubFile; i++) {
const roomType = roomTypes[i];
if (!data[roomType]) isSubFile = false;
}
for (let i = 0; i < excludeRoomTypes.length && isSubFile; i++) {
const roomType = excludeRoomTypes[i];
if (data[roomType]) isSubFile = false;
}
if (isSubFile) {
Utils.log(`Add path: ${filePath}`, Utils.LogLevel.Particular);
this.getUUIDsInPath(filePath, uuids);
}
}
}
this.updatePackageAssets(uuids);
const base = this.subpackageInfoData[key];
console.log(`Package ${key} files: \n${uuids.join(', ')}`);
config.push({ key: base.key, name: base.name, des: base.des, uuids: uuids.map(value => value.uuid) });
}
}
// private initWelfareSubpackage(config: SubpackageConfig[]): void {
// const welfare = this.dataArrayToObjectArray(this.gameConfig['Welfare']);
// welfare.forEach(({ id, page, pic }) => {
// const uuids: { db: string; uuid: string; }[] = [];
// this.getUUIDsInPath(`res/spine/welfare/${page}`, uuids);
// this.getUUIDsInPath(`res/prefab/welfare/${page}`, uuids);
// this.getUUIDsInPath(`res/texture/welfare/${page}`, uuids);
// this.getUUIDsInPath(`res/texture/_atlasexclude/welfare/${page}`, uuids);
// this.getUUIDsInPath(`resources/texture/welfareImgs/${pic}`, uuids);
// this.updatePackageAssets(uuids);
// config.push({ name: `welfare${id}`, des: '', uuids: uuids.map(value => value.uuid) });
// })
// }
private initSubpackageConfig(): SubpackageConfig[] {
const config: SubpackageConfig[] = [];
this.initExcelSubpackage(config);
return config;
}
public getSubpackageConfig(): SubpackageConfig[] {
this.subpackageConfigs = this.subpackageConfigs || this.initSubpackageConfig();
return this.subpackageConfigs;
}
}