二七王:建房选项配置补精灵键、bit 统一挂到 item、补 || {} 保护声明
Sprites_CreateRoom.js 的注释说「配置里每个选项声明自己用哪个精灵键」,但 EQW_RoomOptions
的 items 只有 label/value,渲染器只剩「按下标拼字符串」一条路——而那正是同文件明文禁止的;
何况也拼不对(组的 key 是 'rules',精灵却叫 ROOM_BOX_RULE_1)。
- 每个类别加 titleSprite,每个选项加 box/text 精灵键,房卡附注加 noteSprite。
- bit 统一挂到每个 item 上(单选组各项写同一个 bit),拼 roomtype 的循环对
radio/checkbox 是同一个形状(item → 写 value 到 bit),不再按组/项两种层级分支;
checkbox 项补上 value:'1'。
- 补上其他常量文件都有的 `|| {}` 保护性声明。
- 守卫新增:精灵键必须存在且互不重复、必须恰好覆盖建房 View 预置的全部选项精灵、
bit 不得再挂在组上、单选组内 bit 一致、多选组 bit 互异、位号刚好铺满 0–4
(对齐服务端 class.config.js 的 IDX_ASET..IDX_NOCHECK)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -267,6 +267,53 @@ function checkKind(node, path) {
|
||||
Object.keys(EQW_Layout).forEach(k => checkKind(EQW_Layout[k], k));
|
||||
t.eq('布局 kind 全部合法', badKinds, []);
|
||||
|
||||
// ---- 建房选项配置:精灵键由配置给出,渲染器不按下标拼字符串 ----
|
||||
const optProblems = [];
|
||||
const usedOptSprites = {};
|
||||
function useSprite(where, key) {
|
||||
if (!key) { optProblems.push(where + ' 未声明精灵键'); return; }
|
||||
if (!index.hasOwnProperty(key)) { optProblems.push(where + ' -> 精灵键不存在: ' + key); return; }
|
||||
if (usedOptSprites[key]) { optProblems.push(where + ' -> 精灵键被重复引用: ' + key); }
|
||||
usedOptSprites[key] = true;
|
||||
}
|
||||
const bitsSeen = {};
|
||||
EQW_RoomOptions.categories.forEach((cat, ci) => {
|
||||
useSprite('类别' + ci + ' titleSprite', cat.titleSprite);
|
||||
cat.groups.forEach(g => {
|
||||
if (g.hasOwnProperty('bit')) { optProblems.push('组 ' + g.key + ' 仍把 bit 挂在组上(应统一到 item)'); }
|
||||
if (g.note) { useSprite('组 ' + g.key + ' noteSprite', g.noteSprite); }
|
||||
if (['radio', 'checkbox', 'radioOptional'].indexOf(g.type) < 0) {
|
||||
optProblems.push('组 ' + g.key + ' -> 未知 type: ' + g.type);
|
||||
}
|
||||
g.items.forEach((it, ii) => {
|
||||
const where = '组 ' + g.key + ' 第' + ii + '项';
|
||||
useSprite(where + ' box', it.box);
|
||||
useSprite(where + ' text', it.text);
|
||||
if (typeof it.bit !== 'number') { optProblems.push(where + ' 缺 bit'); }
|
||||
if (it.value !== '0' && it.value !== '1') { optProblems.push(where + ' value 非 0/1: ' + it.value); }
|
||||
bitsSeen[it.bit] = true;
|
||||
// 单选组内各项必须共用同一个 bit(同一位互斥取值)
|
||||
if (g.type !== 'checkbox' && it.bit !== g.items[0].bit) {
|
||||
optProblems.push(where + ' 与同组首项 bit 不一致');
|
||||
}
|
||||
});
|
||||
// 多选组各项必须占用互不相同的位
|
||||
if (g.type === 'checkbox') {
|
||||
const bs = g.items.map(it => it.bit);
|
||||
if (new Set(bs).size !== bs.length) { optProblems.push('组 ' + g.key + ' 多选各项 bit 重复'); }
|
||||
}
|
||||
});
|
||||
});
|
||||
// 配置声明的精灵必须恰好覆盖建房 View 里预置的全部选项精灵(多一个少一个都说明两边不同步)
|
||||
Object.keys(EQW_Sprites.CreateRoomView.CreateRoom).forEach(k => {
|
||||
if (k === 'id') { return; }
|
||||
if (!usedOptSprites[k]) { optProblems.push('精灵 ' + k + ' 没有任何配置项引用它'); }
|
||||
});
|
||||
if (optProblems.length) { console.log('建房选项配置问题:\n ' + optProblems.join('\n ')); }
|
||||
t.eq('建房选项精灵键与 bit 声明完整', optProblems, []);
|
||||
// roomtype 是 5 位串(服务端 class.config.js IDX_ASET..IDX_NOCHECK = 0..4),位号必须刚好铺满
|
||||
t.eq('roomtype 位号铺满 0-4', Object.keys(bitsSeen).map(Number).sort((a, b) => a - b), [0, 1, 2, 3, 4]);
|
||||
|
||||
// ---- 牌尺寸档引用的资源键存在 ----
|
||||
['L', 'M', 'S'].forEach(size => {
|
||||
t.eq('CARD_SIZE.' + size + ' 的资源存在', EQW_Images.hasOwnProperty(EQW_Layout.CARD_SIZE[size].res), true);
|
||||
|
||||
Reference in New Issue
Block a user