45 lines
2.7 KiB
JavaScript
45 lines
2.7 KiB
JavaScript
'use strict';
|
|
const check = (ok, message) => { if (!ok) throw Error(message); };
|
|
const integer = (n, min = 0) => Number.isSafeInteger(n) && n >= min && n <= 100000;
|
|
const digest = h => typeof h === 'string' && /^[a-f0-9]{64}$/.test(h);
|
|
const levelFile = (g, id, e) => g + '/levels/' + id + '.' + e.hash + '.json';
|
|
const packFile = (g, key, e) => g + '/packs/' + key + '.' + e.hash + '.zip';
|
|
function entry(e) { check(e && digest(e.hash) && Number.isSafeInteger(e.size) && e.size > 0, '资源条目无效'); return e; }
|
|
function level(data) {
|
|
check(data && Array.isArray(data.LEVEL_INFO) && data.LEVEL_INFO.length > 0
|
|
&& data.LEVEL_INFO[0] && typeof data.LEVEL_INFO[0] === 'object'
|
|
&& Array.isArray(data.BLOCK_INFO) && Array.isArray(data.BLOCK_INFO[0]), '关卡配置无效');
|
|
return data;
|
|
}
|
|
function manifest(m, version, environment) {
|
|
check(m && m.schemaVersion === 1 && m.contentVersion === version && m.environment === environment
|
|
&& typeof m.release === 'string' && /^[a-zA-Z0-9_-]+$/.test(m.release) && m.groups, '关卡清单版本或环境不匹配');
|
|
for (const g of ['A', 'B']) {
|
|
const group = m.groups[g];
|
|
check(group && group.levels && group.packs && integer(group.resourceCount, g === 'A' ? 100 : 0), '关卡资源范围无效');
|
|
check(Object.keys(group.levels).length === group.resourceCount, '关卡文件数量不符');
|
|
for (let id = 1; id <= group.resourceCount; id++) entry(group.levels[id]);
|
|
const keys = [];
|
|
for (let start = 1; start <= group.resourceCount; start += 100) keys.push(String(start));
|
|
if (g === 'A') keys.push('all');
|
|
check(Object.keys(group.packs).length === keys.length, '关卡包数量不符');
|
|
for (const key of keys) {
|
|
const p = entry(group.packs[key]), start = key === 'all' ? 1 : Number(key);
|
|
check(p.start === start && p.end === (key === 'all' ? group.resourceCount : Math.min(start + 99, group.resourceCount))
|
|
&& digest(p.indexHash), '关卡包范围无效');
|
|
}
|
|
}
|
|
check(!m.simulatedB || environment === 'test', '模拟B不能发布到正式环境');
|
|
return m;
|
|
}
|
|
function builtin(b) {
|
|
check(b && b.schemaVersion === 1 && integer(b.contentVersion, 1) && b.groups && b.groups.A && b.groups.B, '内置关卡清单无效');
|
|
for (const g of ['A', 'B']) for (const id of Object.keys(b.groups[g])) {
|
|
check(integer(Number(id), 1), '内置关卡编号无效');
|
|
const e = entry(b.groups[g][id]);
|
|
check(e.file === 'levels-local/' + g + '/' + id + '.' + e.hash + '.json', '内置关卡路径无效');
|
|
}
|
|
return b;
|
|
}
|
|
module.exports = { check, integer, digest, entry, level, manifest, builtin, levelFile, packFile };
|