Files
TermiNexus 356647937e feat: M9 枚举线形序数 enum#N 解析成成员名(category 显示 ARMOR/WEAPON/PAINT…)
数据: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>> 的元素级。
2026-09-18 12:59:45 +08:00

44 lines
2.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 };