数据:evidence.json 的 byModule.<模块>.enums = { 枚举短名: [{field, member, value}] },全局 348 类 / 2633 成员。查表键定为 (字段所属模块, 枚举短名, 序数):同模块内短名天然唯一;跨模块同名 11 个短名 / 9 个同名异义,键含模块号即可隔离。全表 102 条 enum<X> 引用的定义模块均由字段的 TypeCodec 唯一确定(无冲突、未解 0),导出后落盘 77 类 / 1343 成员(33879 字符,整表增量 33894)。两层分离(本任务核心约束):协议层原始值仍是 enum#N,一字不改,因此 CompareContainerDecode.mjs 的逐字段对照口径不变;EnumNames 只在 UI/日志/dump 里翻译,查不到返回 null 并由调用方标「未解」,不猜。category 实测(15 件仓库物品全部解出):ARMOR#1 / WEAPON#0 / PAINT#2 / BAZOOKA#13 / DRONE#8 / INVENTORY#3 / INVISIBLE#9,真实 5 件挂载物品类别互不相同 —— M8 结论不变。UI 与日志显示「成员名(enum#N)」。顺带修正 GarageDriver 接线:上一轮把 URL 硬编码成 9092 且日志 label 写死 store-02,改为环境变量 TANKIC_WS_URL(默认 9091)与 TANKIC_LOG_LABEL(默认 store-03),否则「配对表 ⇔ 服务端日志」会找错目录。验收:CompareContainerDecode 5 帧 / 一致叶子 26950 / 不一致 0(硬门槛);server selftest 逐字节一致 1108 / 不一致 9 / 解码中断 90;三构建全绿;浏览器实测 15/15 类别显示成员名。未解:枚举成员名未覆盖 list<enum<X>>/opt<enum<X>> 的元素级。
44 lines
2.1 KiB
JavaScript
44 lines
2.1 KiB
JavaScript
// enum_names.js - 枚举线形序数 → 成员名(**仅日志/展示用**;原始值一律不改)
|
||
//
|
||
// 为什么单独一个模块:协议里的 enum<T> 在线上只有 4 字节 i32,解出来只有线形序数 `enum#N`
|
||
// (口径见 tools/lib_space_codec.js)。真实客户端知道成员名,证据在 names/evidence.json:
|
||
// byModule.<moduleId>.enums = { <枚举短名>: [ {field, member, value}, … ] }
|
||
// 本模块按需把它读进内存,供服务端日志把 `enum#N` 翻成「成员名(enum#N)」。
|
||
// **不参与任何解码/编码/落库**:Items.Category 等列里存的仍是原始令牌,一字不改。
|
||
//
|
||
// 目前只做「物品装备槽类别」这一个枚举(服务端日志只用到它):
|
||
// 字段所在 codec = module_85196::Lo,线形 type = `enum<ja>`;ja 定义在 module_85667(TypeCodec=module_85667::pu)。
|
||
'use strict';
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const NAMES_DIR = path.resolve(__dirname, '..', '..', 'names');
|
||
const CATEGORY = { Module: '85667', Short: 'ja' };
|
||
|
||
let MemberByValue = null;
|
||
|
||
// 懒加载(证据文件约 1MB;只有真要打日志时才读,读不到就按「未解」回退,绝不猜)
|
||
function Ensure() {
|
||
if (MemberByValue) return MemberByValue;
|
||
MemberByValue = new Map();
|
||
try {
|
||
const Ev = JSON.parse(fs.readFileSync(path.join(NAMES_DIR, 'evidence.json'), 'utf8'));
|
||
const Members = ((((Ev.byModule || {})[CATEGORY.Module] || {}).enums) || {})[CATEGORY.Short] || [];
|
||
for (const M of Members) if (!MemberByValue.has(String(M.value))) MemberByValue.set(String(M.value), String(M.member));
|
||
} catch (Err) {
|
||
// 证据不可用:保持空表,CategoryLabel 会如实写「未解」
|
||
}
|
||
return MemberByValue;
|
||
}
|
||
|
||
// 'enum#1' → 'ARMOR(enum#1)';空/NULL → '未知';查不到 → 'enum#1(未解)'
|
||
function CategoryLabel(Raw) {
|
||
if (Raw === null || Raw === undefined || Raw === '') return '未知';
|
||
const S = String(Raw);
|
||
const M = /^enum#(-?\d+)$/.exec(S);
|
||
const Name = M ? Ensure().get(M[1]) : null;
|
||
return Name ? Name + '(' + S + ')' : S + '(未解)';
|
||
}
|
||
|
||
module.exports = { CategoryLabel, CATEGORY };
|