Files
TankIC/tools/hornet_schema.js
T
TermiNexus 69defa85e7 feat(ignore): 栅栏诊断输出重叠物体信息(形状 + 邻近场景节点名)
保持原有几何判定(仅陡峭静态三角形);DebugFence(true) 后,本车与任意非坦克形状配对时按签名去重打印 cat/type/法线/位置/7m 内场景节点名,用于确认栅栏对应哪个物体;schema 补 Body.State/PositionVec。
2026-10-21 00:25:16 +08:00

391 lines
17 KiB
JavaScript
Raw 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.
// hornet_schema.js — 引擎匿名字段抽象层(字段映射总表)
//
// 为什么需要它:
// 游戏每个构建版本都会把类的字段名整体平移(如 ejt 的 zzq_1 / bzr_1),
// 工具里到处硬编码 `comp.zzq_1`、`tank.qz1_1.s2a_1` 这类匿名名,
// 版本一换就要全局搜替换,还容易改错(同名复用极严重)。
// 这里把「语义名 → 匿名字段路径」集中成一张表:
// · 工具只用语义名(Schema.Get(tank, 'Tank.StateValue'))
// · 换版本时只改这张表,并跑一次 SelfCheck() 看哪几项失配
//
// 路径语法:
// 'a.b.c' 属性链
// 'lz4()' 方法调用(末尾带括号即调用,中间也可混用,如 'm10b_1.j11y()')
//
// 用法:
// var S = window.__hornetSchema__;
// S.Get(gm, 'GameMode.TankList')
// S.Get(tank, 'Tank.StateValue')
// S.Check(gm, 'GameMode') // → { Ok: [...], Missing: [...] }
// S.SelfCheck() // 用当前战局对象自检并打印
//
// 版本:main.7cfa4058(字段核对自 module_87072 / 61378 / 92980 / 55088)
(function () {
'use strict';
// ===== 字段映射总表 =====
// 命名规则:<对象类型>.<语义名>
var Fields = {
// ---- 向量(O$)----
'Vec.X': 'f20_1',
'Vec.Y': 'g20_1',
'Vec.Z': 'h20_1',
// ---- 战斗实体基类(fe / BattleEntity)----
'Entity.Id': 'iz1_1', // 实体 ID(坦克/战场唯一)
'Entity.Root': 'qz1_1', // 组件宿主根对象
'Entity.ComponentMap': 's2a_1', // 宿主上的组件 Map
'Entity.Components': 'qz1_1.s2a_1', // Map<组件标识, 组件列表>,取值要 valueList.g1(0)
// ---- GameMode(ght,window.__gameMode__)----
'GameMode.Scene': 'lz4()', // 场景实体
'GameMode.TankManager': 'm10b_1', // 坦克管理器
'GameMode.TankList': 'm10b_1.j11y()', // 坦克列表(e1() 数量 / g1(i) 取)
'GameMode.OwnedTank': 'u10b_1', // 本地玩家拥有的坦克(onTankPossessed)
'GameMode.ObservedTank': 't10b_1', // 当前观察目标(死亡/观战时可能指向敌人)
'GameMode.LocalTeam': 'v10b_1', // 本地队伍(与 u10b_1 同生命周期)
// ---- 坦克组件(lxt,含状态机)----
'Tank.Fsm': 'p10c_1', // 状态机字段(组件识别用)
'Tank.State': 'k10c_1', // 状态枚举对象
'Tank.StateValue': 'k10c_1.k3_1', // 状态数值:0=DEAD 1=DEAD_PHANTOM 2=SEMI_ACTIVE 3=ACTIVE 4=DISABLED 5=TELEPORT
'Tank.IsAlive': 's14j()', // 引擎可见性判定(2/3/5)
'Tank.TeamSource': 'l10c_1', // 状态机里下发的队伍对象
// ---- 队伍组件(GIt)与队伍对象 ----
'Team.Field': 'b135_1', // 队伍组件上保存队伍对象的字段
'Team.Id': 'k3_1', // 队伍编号:0 / 1 / 2(2 = 中立)
'Team.NeutralId': 2,
// ---- 坦克物理组件(ejt,组件名 tankPhysics)----
'Physics.Position': 'bzr_1', // 世界位置向量(f20_1/g20_1/h20_1)
'Physics.PositionOld1': 'gzh_1', // 旧版位置字段名(兜底候选)
'Physics.PositionOld2': 'pz7_1', // 更旧位置字段名(兜底候选)
'Physics.Size': 'xzq_1', // 车体半尺寸(**不是位置**)
'Physics.Hull': 'zzq_1', // 车体主碰撞形状(x9j_1 === 'hull-main')
'Physics.Body': 'pbk()', // 物理刚体(jM)
'Physics.AddMask': 'n155()', // z9j_1 |= t
'Physics.RemoveMask': 'm155()', // z9j_1 &= ~t
'Physics.BodyShapes': 'pbk().y9i_1', // 刚体上的形状列表(e1()/g1(i))
// ---- 碰撞形状(yi)----
'Shape.Name': 'x9j_1',
'Shape.Category': 'y9j_1', // bit0=坦克(1) bit3=地雷(8) bit4=地形(16)
'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位
'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应
'Shape.Body': 'b9k_1', // 形状 → 所属刚体(Fn)
'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形)
'Shape.Vertex0': 'u9x_1', // 三角形顶点 0
'Shape.Vertex1': 'v9x_1', // 三角形顶点 1
'Shape.Vertex2': 'w9x_1', // 三角形顶点 2
'Body.Owner': 'x9i_1', // 刚体 → 拥有者(坦克物理组件 ejt)
'Body.State': 'f9j_1', // 刚体当前物理态
'Body.PositionVec': 's9j_1', // 刚体位置向量(f9j_1.s9j_1)
// ---- 碰撞世界(module_55088 的 ki)----
'CollisionWorld.ShouldCollide': 'q9q()', // 唯一配对过滤:mask + 形状类型 → 生成接触
// ---- 实体事件总线 / 外力事件(ODt)----
'Entity.Dispatch': 'kz7()', // 向实体内所有订阅者派发事件
'Event.PushPoint': 'o13i_1', // 外力事件:作用点(O$ 向量)
'Event.PushDir': 'p13i_1', // 外力事件:方向(O$ 向量)
'Event.PushStrength': 'q13i_1', // 外力事件:强度(坦克物理交给 m9k)
// ---- 血量组件(Vkt)----
'Health.Max': 'p12o_1',
'Health.Current': 'q12o_1',
// ---- 用户信息组件(yot)----
'User.Name': 'c12n_1',
'User.Clan': 'e12n_1',
// ---- 装备分组件(BattleGearScoreCC)----
'Gear.Score': 'cjf_1',
// ---- 皮肤组件(eUt)----
'Skin.HullSkin': 'g159_1', // 皮肤对象
'Skin.HullRoot': 'h159_1', // 车身渲染树根(BP 节点)
'Skin.Parts': 'g159_1.g17r_1', // 部件表
'Skin.PartNode': 'j17r_1', // 部件 → BP 节点
// ---- 炮塔皮肤组件(LUt)----
'Turret.Wrapper': 'a11p_1', // 组件首字段(包装对象)
'Turret.Root': 'e11p_1.a17q_1', // 炮塔 BP 根节点
'Turret.GetRoot': 'u11p()',
// ---- BP 场景节点(zl)----
'Node.Name': 'g35_1',
'Node.Matrix': 'p35_1', // 世界矩阵(列主序,[12][13][14] = 平移)
'Node.MatrixOld': 'n35_1', // 旧版矩阵字段(兜底候选)
'Node.Children': 'r35_1',
'Node.Mesh': 'v3m_1',
'Node.Lod': 'u4x_1',
// ---- 相机(场景实体 .jz1_1.iyx_1)----
'Camera.SceneRef': 'jz1_1',
'Camera.Object': 'iyx_1', // 主相机对象(挂在场景实体的 jz1_1 上)
'Camera.Viewport': 'w36_1', // 视口(h29() 宽 / g29() 高)
'Camera.Main': 'jz1_1.iyx_1',
'Camera.Position': 'jz1_1.iyx_1.t35_1',
'Camera.ViewMatrix': 'jz1_1.iyx_1.d37_1',
'Camera.ClipMatrix': 'jz1_1.iyx_1.g37_1',
'Camera.Fov': 'jz1_1.iyx_1.b37_1',
// ---- 相机:单段叶子字段(FieldName 只认单段,这里给同一批字段补叶子别名)----
'Camera.PositionLeaf': 't35_1',
'Camera.ViewMatrixLeaf': 'd37_1',
'Camera.ClipMatrixLeaf': 'g37_1',
'Camera.FovLeaf': 'b37_1',
'Camera.PositionNode': 'r35_1', // 旧版相机位置字段(与 Node.Children 同名但不通用)
'Camera.Angles': 'u35_1', // 欧拉角(pitch/roll/yaw)
'Camera.Euler': 'u35_1', // 同上(自由视角叫法)
'Camera.Rotation': 'u35_1', // 同上(沙盘叫法)
'Camera.Update': 'o37()', // 相机矩阵刷新
'Camera.ViewportWidth': 'u36_1',
'Camera.ViewportHeight': 'v36_1',
'Camera.RenderWidth': 'u36_1', // 别名
'Camera.RenderHeight': 'v36_1', // 别名
'Camera.FovValue': 'z36_1',
'Camera.Near': 'x36_1',
'Camera.Far': 'y36_1',
'Camera.SceneFx': 'd75_1',
// ---- 渲染器 / 绘制流程(module_92980)----
'Render.Renderer': 'gyw_1', // 场景渲染器
'Render.Drawer': 'd75_1', // Ff 绘制器
'Render.DrawBuffer': 'd75_1', // 别名(透视里按"绘制缓冲"称呼)
'Renderer.Object': 'd75_1', // 别名(沙盘里按"渲染器对象"称呼)
'Render.Gl': 'w39_1', // GL 包装器
'Renderer.Device': 'w39_1', // 别名
'Render.GlNative': 'b74_1', // 原生 WebGL2RenderingContext
'Renderer.Gl': 'b74_1', // 别名
'Render.Device': 's3h_1', // 资源侧设备包装
'Render.DeviceNative': 'f75_1', // 设备里的原生 GL
'Render.Settings': 'y38_1', // 渲染开关组
'Renderer.Flags': 'y38_1', // 别名
'Render.ShadowEnabled': 'e3o_1',
'Renderer.Shadow': 'e3o_1', // 别名
'Render.PostProcessEnabled': 'f3o_1',
'Renderer.PostFx': 'f3o_1', // 别名
'Render.ExtraPassEnabled': 'k3o_1',
'Renderer.FlagAux': 'k3o_1', // 别名
'Render.LayerQueue': 'e39_1', // 渲染层队列(20=Hud 21-24=GUI)
'Renderer.QueueList': 'e39_1', // 别名
'Render.Draw': 'f3t()', // y3s → f3t 主渲染
'Render.DrawingWidth': 'o3c()',
'Render.DrawingHeight': 'n3c()',
'Scene.RootNode': 'fyx_1', // 场景根节点
// ---- 网格资源(Tp / sm)----
'Mesh.VertexGroups': 'x4w_1',
'Mesh.VertexBuffer': 'h3x_1',
'Mesh.VertexCount': 'w3x_1',
'Mesh.CpuVertexData': 'x3x_1',
'Mesh.GpuBuffer': 'v3x_1',
'Mesh.IndexGroups': 'y4w_1',
'Mesh.IndexBuffer': 'q4w_1',
'Mesh.IndexBufferOld': 'u3p_1',
'Mesh.CpuIndexData': 'p3x_1',
'Mesh.IndexGpuBuffer': 'n3x_1',
// ---- 射线检测(碰撞世界的射线接口)----
'CollisionWorld.Raycast': 'a17p()',
'Ray.Cast': 'a17p()', // 别名
'Ray.StartPoint': 'y178_1',
'Ray.HitPoint': 'y178_1', // 别名
'Ray.EndPoint': 'z178_1',
'Ray.HitNormal': 'z178_1', // 别名
'Ray.Distance': 'a179_1',
'Ray.HitEntity': 'q17o_1',
'Ray.HitShape': 'q17o_1', // 别名(雷达/瞄准把第 4 参数叫 HitShape)
'Ray.HitBody': 'b179_1', // 第 5 参数
'RayFilter.Context': 'l1da_1',
'RayFilter.Query': 'l1da_1', // 别名
// ---- 车体朝向 / 武器(雷达、瞄准警告)----
'Tank.HullComponent': 'qzv_1', // 车体朝向组件识别字段
'Tank.HullDirection': 'wzl_1', // 车体朝向向量
'Tank.StateId': 'k3_1', // 状态枚举数值(与 Team.Id 同名字段,按用途分开)
'Weapon.Component': 'n11c_1',
'Weapon.ComponentAlt': 'q112_1',
'Weapon.TurretRoot': 'm17a_1',
// ---- 炮塔 / 皮肤槽位 ----
'Turret.InnerWrapper': 'e11p_1',
'Turret.RootNode': 'a17q_1',
'Skin.SlotHull': 'w14w_1',
'Skin.SlotHullLegacy': 't14l_1',
'Skin.SlotHullAlt': 'w14x_1',
'Skin.SlotHullOld': 'p14l_1'
};
// ===== module_87072 的导出键($_.xx),每版都可能平移 =====
// 队伍:vd = WIt(t) 取实体队伍;dl = R7(a,b) 同队且非中立
// ⚠ 旧版是 kd / rk;新版 kd 已指向无关构造器
var Exports = {
'Export.TeamOf': ['vd', 'kd'],
'Export.TeamSame': ['dl', 'rk'],
'Export.PhysicsWorld': ['h'] // module_55088.$_$.h = 碰撞世界类 ki
};
// ===== 路径解析 =====
function IsCall(Token) {
var N = Token.length;
return N > 2 && Token.charAt(N - 1) === ')' && Token.charAt(N - 2) === '(';
}
function ResolvePath(Target, Path) {
if (Target === null || Target === undefined || !Path) return undefined;
var Tokens = String(Path).split('.');
var Cur = Target;
for (var i = 0; i < Tokens.length; i++) {
if (Cur === null || Cur === undefined) return undefined;
var Tok = Tokens[i];
if (IsCall(Tok)) {
var Name = Tok.slice(0, -2);
if (typeof Cur[Name] !== 'function') return undefined;
try { Cur = Cur[Name](); } catch (e) { return undefined; }
} else {
Cur = Cur[Tok];
}
}
return Cur;
}
// 取字段值:Key 是总表键(如 'Tank.StateValue'),未命中则把 Key 当字面路径
function Get(Target, Key) {
var Path = Fields[Key];
return ResolvePath(Target, Path !== undefined ? Path : Key);
}
// 取字段路径(字符串),用于打印/自检
function PathOf(Key) {
return Fields[Key] !== undefined ? Fields[Key] : String(Key);
}
// 取单段属性名:'Node.Matrix' → 'p35_1';带方法或多段时返回 null
// 工具里写成 `Node[FieldName('Node.Matrix') || 'p35_1']`,即「优先用总表,缺表时用字面名」
function FieldName(Key) {
var P = Fields[Key];
if (!P || P.indexOf('.') >= 0 || IsCall(P)) return null;
return P;
}
// 取单段方法名:'Physics.RemoveMask' → 'm155'
function MethodName(Key) {
var P = Fields[Key];
if (!P || !IsCall(P) || P.indexOf('.') >= 0) return null;
return P.slice(0, -2);
}
// 自检:按前缀检查某对象上哪些语义字段能解析
function Check(Target, Prefix) {
var Out = { Ok: [], Missing: [] };
Object.keys(Fields).forEach(function (Key) {
if (Prefix && Key.indexOf(Prefix + '.') !== 0) return;
if (typeof Fields[Key] !== 'string') return; // 常量项(如 Team.NeutralId)不参与自检
var V = Get(Target, Key);
if (V === undefined) Out.Missing.push(Key + ' → ' + Fields[Key]);
else Out.Ok.push(Key + ' → ' + Fields[Key]);
});
return Out;
}
// 自检项(只查核心字段:别名/扩展项不在样本对象上,查了会误报)
var CoreKeys = {
Entity: ['Entity.Id', 'Entity.Root', 'Entity.ComponentMap', 'Entity.Components'],
GameMode: ['GameMode.Scene', 'GameMode.TankManager', 'GameMode.TankList',
'GameMode.OwnedTank', 'GameMode.ObservedTank', 'GameMode.LocalTeam'],
Tank: ['Tank.Fsm', 'Tank.State', 'Tank.StateValue', 'Tank.IsAlive', 'Tank.TeamSource'],
Physics: ['Physics.Position', 'Physics.Size', 'Physics.Hull', 'Physics.Body', 'Physics.BodyShapes'],
Shape: ['Shape.Name', 'Shape.Category', 'Shape.Mask', 'Shape.Body', 'Body.Owner'],
Skin: ['Skin.HullSkin', 'Skin.HullRoot', 'Skin.Parts', 'Skin.PartNode'],
Turret: ['Turret.Wrapper', 'Turret.GetRoot'],
Node: ['Node.Name', 'Node.Matrix', 'Node.Children', 'Node.Mesh'],
Camera: ['Camera.SceneRef', 'Camera.Main', 'Camera.Position', 'Camera.ViewMatrix',
'Camera.ClipMatrix', 'Camera.Fov']
};
// 用当前战局对象做一次全量自检(控制台调用 __hornetSchema__.SelfCheck())
function SelfCheck() {
var Gm = window.__gameMode__;
var Report = { HasGameMode: !!Gm, Groups: {}, Missing: [] };
if (!Gm) return Report;
var Scene = Get(Gm, 'GameMode.Scene');
var TankList = Get(Gm, 'GameMode.TankList');
var Tank = null;
try {
Tank = Get(Gm, 'GameMode.OwnedTank');
if (!Tank && TankList && typeof TankList.e1 === 'function' && TankList.e1() > 0) Tank = TankList.g1(0);
} catch (e) {}
var Physics = Tank ? FindPhysics(Tank) : null;
var Targets = {
Entity: Tank || Scene,
GameMode: Gm,
Tank: Tank,
Physics: Physics,
Shape: Physics ? Get(Physics, 'Physics.Hull') : null,
Skin: Tank,
Turret: Tank,
Node: Tank ? Get(Tank, 'Skin.HullRoot') : null,
Camera: Scene
};
Object.keys(CoreKeys).forEach(function (Prefix) {
var Target = Targets[Prefix];
if (!Target) { Report.Groups[Prefix] = '无样本对象'; return; }
var Ok = [], Missing = [];
CoreKeys[Prefix].forEach(function (Key) {
var V = Get(Target, Key);
if (V === undefined) Missing.push(Key + ' → ' + PathOf(Key));
else Ok.push(Key);
});
Report.Groups[Prefix] = { Ok: Ok, Missing: Missing };
Missing.forEach(function (M) { Report.Missing.push(Prefix + '.' + M); });
});
if (Report.Missing.length) {
console.warn('[字段抽象] 失配 ' + Report.Missing.length + ' 项:', Report.Missing);
} else {
console.log('[字段抽象] 全部核心字段解析正常');
}
return Report;
}
// 找坦克物理组件(与工具内实现同源,放这里方便自检)
function FindPhysics(Tank) {
if (!Tank) return null;
var Map = Get(Tank, 'Entity.Components');
if (!Map || typeof Map.forEach !== 'function') return null;
var Found = null;
Map.forEach(function (ValueList) {
if (Found) return;
var Comp = (ValueList && typeof ValueList.g1 === 'function') ? ValueList.g1(0) : ValueList;
if (!Comp) return;
var Hull = Get(Comp, 'Physics.Hull');
if (Hull && Get(Hull, 'Shape.Name') === 'hull-main') Found = Comp;
});
return Found;
}
// ===== 导出 =====
window.__hornetSchema__ = {
Version: 'main.7cfa4058',
Fields: Fields,
Exports: Exports,
Get: Get,
PathOf: PathOf,
FieldName: FieldName,
MethodName: MethodName,
Check: Check,
SelfCheck: SelfCheck,
ResolvePath: ResolvePath,
FindPhysics: FindPhysics
};
console.log('[3DTank] 字段抽象层已加载(版本 main.7cfa4058,语义字段 ' + Object.keys(Fields).length + ' 项)');
})();