no message
This commit is contained in:
94
tools/split-levels-database.js
Normal file
94
tools/split-levels-database.js
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 将 levels-database.json 拆为 index + 分片,首屏只下 index(~几 KB)。
|
||||
*
|
||||
* 输出:
|
||||
* <outDir>/levels-db-index.json (+ .br)
|
||||
* <outDir>/StreamingAssets/aa/levels-db/<min>-<max>.json (+ .br)
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { brotliCompressFile, formatBytes } = require('./package-optimize');
|
||||
|
||||
const DEFAULT_SHARD_SIZE = 100;
|
||||
|
||||
function mkdirp(p) { fs.mkdirSync(p, { recursive: true }); }
|
||||
|
||||
/**
|
||||
* @param {string} srcPath assets/level-data/levels-database.json
|
||||
* @param {string} outDir 运行时包根目录
|
||||
* @param {{ shardSize?: number }} opts
|
||||
*/
|
||||
function splitLevelsDatabase(srcPath, outDir, opts = {}) {
|
||||
const shardSize = opts.shardSize || DEFAULT_SHARD_SIZE;
|
||||
const raw = JSON.parse(fs.readFileSync(srcPath, 'utf8'));
|
||||
const levels = raw.levels || {};
|
||||
const ids = Object.keys(levels)
|
||||
.map((k) => parseInt(k, 10))
|
||||
.filter((n) => !Number.isNaN(n))
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
if (ids.length < 1) {
|
||||
throw new Error(`关卡库为空: ${srcPath}`);
|
||||
}
|
||||
|
||||
const min = ids[0];
|
||||
const max = ids[ids.length - 1];
|
||||
const shardDir = path.join(outDir, 'StreamingAssets', 'aa', 'levels-db');
|
||||
mkdirp(shardDir);
|
||||
|
||||
const shards = [];
|
||||
for (let start = min; start <= max; start += shardSize) {
|
||||
const end = Math.min(start + shardSize - 1, max);
|
||||
const slice = {};
|
||||
for (const id of ids) {
|
||||
if (id >= start && id <= end) {
|
||||
slice[String(id)] = levels[String(id)];
|
||||
}
|
||||
}
|
||||
if (!Object.keys(slice).length) continue;
|
||||
|
||||
const fileName = `${start}-${end}.json`;
|
||||
const relFile = `levels-db/${fileName}`;
|
||||
const absPath = path.join(shardDir, fileName);
|
||||
fs.writeFileSync(absPath, JSON.stringify({ levels: slice }), 'utf8');
|
||||
const br = brotliCompressFile(absPath, absPath + '.br');
|
||||
console.log(`>>> levels-db/${fileName}: ${formatBytes(br.raw)} → .br ${formatBytes(br.br)}`);
|
||||
|
||||
shards.push({ min: start, max: end, file: relFile, count: Object.keys(slice).length });
|
||||
}
|
||||
|
||||
const index = {
|
||||
version: 2,
|
||||
mode: 'sharded',
|
||||
shardSize,
|
||||
levelIdBase: raw.levelIdBase,
|
||||
generatedAt: raw.generatedAt || new Date().toISOString(),
|
||||
source: raw.source || 'split-levels-database',
|
||||
total: ids.length,
|
||||
min,
|
||||
max,
|
||||
stats: raw.stats,
|
||||
shards,
|
||||
};
|
||||
|
||||
const indexPath = path.join(outDir, 'levels-db-index.json');
|
||||
fs.writeFileSync(indexPath, JSON.stringify(index), 'utf8');
|
||||
const indexBr = brotliCompressFile(indexPath, indexPath + '.br');
|
||||
console.log(`>>> levels-db-index.json: ${formatBytes(indexBr.raw)} → .br ${formatBytes(indexBr.br)}`);
|
||||
console.log(`>>> 关卡库分片: ${shards.length} 片, ${ids.length} 关 (${min}–${max})`);
|
||||
|
||||
return { index, shards, total: ids.length };
|
||||
}
|
||||
|
||||
module.exports = { splitLevelsDatabase, DEFAULT_SHARD_SIZE };
|
||||
|
||||
if (require.main === module) {
|
||||
const src = path.resolve(process.argv[2]);
|
||||
const out = path.resolve(process.argv[3]);
|
||||
if (!src || !out) {
|
||||
console.error('Usage: split-levels-database.js <levels-database.json> <outDir>');
|
||||
process.exit(1);
|
||||
}
|
||||
splitLevelsDatabase(src, out);
|
||||
}
|
||||
Reference in New Issue
Block a user