|
|
||
|---|---|---|
| .. | ||
| bncs | ||
| core | ||
| crypto | ||
| d2gs | ||
| domain | ||
| flow | ||
| mcp | ||
| transport | ||
| ts | ||
| README.md | ||
| index.ts | ||
README.md
src/netproto — 1.13c 权威网络协议与传输引擎
src/netproto 是 Diablo II: Lord of Destruction (v1.13c) 的独立网络协议栈模块,1:1 复刻原版 D2Net.dll、Bnclient.dll、D2MCPClient.dll 与 Fog.dll 的二进制封包编解码、加密哈希、Huffman 压缩与状态机流转。
1. 模块职责与架构边界
- 对应原版 DLL:
Bnclient.dll:BNCS(Battle.net Chat Server,默认 TCP6112)握手、CheckRevision 校验、CD-Key 哈希、XSHA-1 密码认证、账户注册与大厅聊天频道。D2MCPClient.dll:MCP(Realm Server /d2cs,默认 TCP6113)领域登录、角色列表读取、角色创建/删除、游戏房间创建 (0x03) 与加入 (0x04)。D2Net.dll+Fog.dll:D2GS(Game Server,默认 TCP4000)帧头解析、动态 Huffman 解压、167 个 S2C 服务端下行指令解析、C2S 客户端上行指令编码、以及0x9C/0x9D物品比特流解析。
- 架构强隔离约束(
tsconfig.netproto.json):- 零外部模块依赖:
src/netproto不依赖src/common、src/client、src/server或src/baker。 - 单一门面入口:外部模块(如
src/client、src/server、tools/)必须且只能通过src/netproto/index.ts导入符号,禁止跨入子目录深层路径导入(由tests/arch/boundaries.test.ts强制守护)。
- 零外部模块依赖:
2. 目录结构
src/netproto/
├── index.ts # 模块唯一公开导出门面 (Public Facade)
├── core/ # Little-Endian BinaryReader / BinaryWriter / BitReader 及基础协议类型
├── transport/ # ByteStream 传输抽象、WebSocket 桥接流 (WsStream)、内存回环流与端点解析器
├── crypto/ # Broken SHA-1 (XSHA-1)、CheckRevision、CD-Key 解密哈希等 1.13c 加密算法
├── bncs/ # BNCS (端口 6112) 报文成帧、状态机、登录/注册/Realm 切换/大厅聊天协议
├── mcp/ # MCP (端口 6113) 报文成帧、角色列表 (0x19)、创建角色 (0x02)、建房/加房协议
├── d2gs/ # D2GS (端口 4000) Huffman 解压、S2C 167 操作码注册表、C2S 编码与物品 Bitstream
├── flow/ # D2OnlineFlow:串联 BNCS -> MCP -> D2GS 全链路自动重连与令牌交接编排器
├── domain/ # 协议无关领域契约:GameServerAdapter、ServerEvent (37 种事件)、ClientCommand (30 种指令)
└── ts/ # 预留的 TypeScript 远端服务协议适配层 (TsServerAdapter)
3. 核心子系统详解
3.1 传输层与 WebSocket/TCP 桥接 (transport/)
由于浏览器无法直接发起原生 TCP 连接,而原生 PvPGN + D2GS 在消息体内嵌返回了内部 IP 与原始 TCP 端口(如 MCP 返回 D2GS IP + 端口 4000),transport/endpoint.ts 提供了可插拔的 EndpointResolver:
createWsBridgeResolver(bridgeBaseUrl):将目标端口动态映射为 Nginx +websockify反向代理路径:- 端口
6112(BNCS)\rightarrow<bridgeBaseUrl>/bnet(如wss://host/d2net/bnet) - 端口
6113(MCP)\rightarrow<bridgeBaseUrl>/realm(如wss://host/d2net/realm) - 端口
4000(D2GS)\rightarrow<bridgeBaseUrl>/game(如wss://host/d2net/game)
- 端口
createTcpResolver():供 Node.js 环境下的无头 Bot (tools/d2-bot.ts) 直连原生 TCP 端口。MemoryStream:零拷贝内存全双工字节流,供单元测试与本地闭环验证使用。
3.2 BNCS 与 MCP 战网前置协议 (crypto/, bncs/, mcp/)
- 加密算法 (
crypto/):精确实现暴雪特有的无左移循环 Broken SHA-1 (xsha1.ts)、基于 MPQ 版本特征码的CheckRevision(check-revision.ts) 以及 16/26 位 D2/LoD 双 CD-Key 哈希封装。 - 全链路状态机 (
flow/online-flow.ts):BncsClient完成SID_AUTH_INFO (0x50)\rightarrowSID_AUTH_CHECK (0x51)\rightarrowSID_LOGONRESPONSE2 (0x3A)\rightarrowSID_LOGONREALMEX (0x3E)获取 64 字节 MCP Cookie。McpClient携带 Cookie 连接d2cs,执行MCP_STARTUP (0x01)\rightarrowMCP_CHARLIST2 (0x19)\rightarrowMCP_CHARLOGON (0x07)\rightarrowMCP_CREATEGAME (0x03)/MCP_JOINGAME (0x04)获取 D2GS GameHash 与 GameToken。- 自动交接至
D2gsClient发起0x68 (D2GS_GAMELOGON)进入游戏世界。
3.3 D2GS 游戏服协议与 Huffman 解压 (d2gs/)
- 报文成帧与解压 (
framer.ts,huffman.ts):- 处理首包
0xAF压缩协商握手。 - 实现
Fog.dll静态预置 Huffman 树比特流解码,并将单帧解压后的粘包数据依赖于packet-sizes.ts(167 个 S2C 操作码定长/变长/回调计算表)精确切分为独立指令帧。
- 处理首包
- S2C 解析与领域映射 (
s2c-registry.ts,adapter.ts):- 将底层二进制包(如
0x03 LoadAct、0x07/0x08 MapAdd/Remove、0x0F/0x10 PlayerMove、0x15 ReassignPlayer、0x51 AssignObject、0xAC AssignNPC、0x9C/0x9D ItemAction、0x18..0x1F Attribute/Orb Update等)无损转化为强类型的ServerEvent领域事件流。
- 将底层二进制包(如
- 物品比特流解码 (
item-bitstream.ts):- 逐比特解析
0x9C(地面/容器/商店物品)与0x9D(穿戴/佣兵/鼠标物品)变长属性流,由 D2DataRegistry 驱动读取ItemStatCost.txt的Save Bits与Save Add。
- 逐比特解析
4. 常用验证命令
# 单独对 src/netproto 进行类型检查
npx tsc -p tsconfig.netproto.json --noEmit
# 运行协议编解码、Huffman 解压与在线流程单元测试
npx vitest run tests/netproto/
# 重放并检查 .d2cap 抓包录制文件
npx tsx tools/netproto-replay.ts <path-to-capture.d2cap>