|
|
||
|---|---|---|
| .. | ||
| assets | ||
| audio | ||
| automap | ||
| frontend | ||
| i18n | ||
| input | ||
| inspector | ||
| map | ||
| motion | ||
| render | ||
| scene | ||
| session | ||
| settings | ||
| sw | ||
| toolbar | ||
| ui | ||
| ui-model | ||
| view | ||
| world | ||
| README.md | ||
| main.ts | ||
README.md
src/client — 纯浏览器 WebGL2 渲染与交互客户端
src/client 是 Diablo II: Lord of Destruction (v1.13c) 的纯浏览器客户端实现,对标原版 D2Client.dll、D2Gfx.dll、D2Win.dll、D2Launch.dll 与 D2Sound.dll。
在**单客户端模式(Single-Client Mode)**下,本模块仅通过 src/netproto 的 WebSocket 桥接协议与远端原生 C++ PvPGN + D2GS (1.13c) 通信,在浏览器端完成种子驱动的 DRLG 地图重建、WebGL2 等距视角渲染、客户端移动预测与全套经典 UI 交互。
1. 模块职责与架构边界
- 唯一 HTML 入口:
play.html\rightarrowsrc/client/main.ts。 - TypeScript 工程约束(
tsconfig.client.json):lib: ["ES2022", "DOM", "DOM.Iterable"],types: []。- 严禁依赖
src/server或src/baker,严禁导入任何 Node.js 内置模块(fs,path,net,Buffer等)。 - 仅依赖
src/common(DRLG 算法、格式解析器、数据表定义)与src/netproto(协议门面与D2gsServerAdapter)。
2. 目录结构
src/client/
├── main.ts # 客户端主入口:组装 WebGL2 画布、工具栏、前端战网状态机、OnlineSession 与 60fps 渲染循环
├── session/ # OnlineSession 会话协调器与 C2S 发包速率限制器 (OutboundRateLimiter)
├── world/ # ClientWorld:由 ServerEvent 驱动的客户端权威状态镜像 (玩家/怪物/NPC/地面物品/投射物/传送门)
├── map/ # 种子驱动的客户端 DRLG 地图服务 (MapService, LevelView, TileAtlas GPU 瓦片加载)
├── motion/ # 本地玩家移动预测 (LocalMovementPredictor)、远端实体插值器与 A* 寻路 (pathfind)
├── render/ # WebGL2 渲染管线 (SpriteRenderer, TileAtlasGpuCache, EntityArtLoader, 投射物/覆盖层/地面物品渲染)
├── scene/ # 场景摄像机、屏幕/世界等距坐标转换与分幕环境光照预设 (lighting-presets)
├── ui/ # 游戏内 HUD 渲染与交互 (HudManager, 底部状态栏, 小地图 Automap, 7 大面板, D2 点阵字体渲染)
├── ui-model/ # UI 纯视图状态模型 (HudModel, 属性加点/技能树/背包网格/商店/赫拉迪克方块交互逻辑)
├── frontend/ # 战网前置界面 (FrontendRenderer:Gateway 选择、账号登录/注册、8 角色选择、建房/加房大厅)
├── toolbar/ # 顶部 32px 窄条工具栏 (FPS/Ping、网络抓包开关、设置弹窗、全屏与音量控制)
├── settings/ # 客户端持久化设置存储 (SettingsStore / client-settings.ts,管理 WS Bridge 地址与显示偏好)
├── inspector/ # 实时网络封包检查器 (PacketInspector) 与 .d2cap 录制/回放面板
├── sw/ # Service Worker (sw.ts) + CacheUpdater:基于 SHA-256 清单的离线资产增量缓存
├── audio/ # Web Audio API 音效与背景音乐服务 (SoundService)
└── assets/ # OPFS (Origin Private File System) 本地 MPQ 导入与缓存支持
3. 核心数据流与子系统详解
3.1 单客户端连接与会话生命周期 (frontend/, session/, world/)
- 战网前置流程 (
FrontendRenderer+D2OnlineFlow):- 启动后加载
/act-packs/frontend/frontend-ui.json,渲染原版风格登录界面、角色选择界面(支持 7 职业动态纸娃娃预览)与战网大厅(Create Game / Join Game 房间列表)。 - 通过
wsBridgeUrl(默认/d2net,可通过 URL 参数?wsBridge=...或顶部工具栏 Settings 面板配置)依次握手 BNCS (/bnet) 与 MCP (/realm)。
- 启动后加载
- 进入游戏 (
OnlineSession+ClientWorld):- 拿到 MCP 颁发的
GameHash与GameToken后,连接 D2GS (/game) 并创建D2gsServerAdapter。 OnlineSession订阅全部 37 种ServerEvent,实时更新ClientWorld中的本地玩家属性、背包/穿戴物品、周围怪物/NPC 状态、地面掉落与任务/小站进度。
- 拿到 MCP 颁发的
3.2 种子驱动的客户端 DRLG 地图重建 (map/)
原生 D2GS 不会在网络上传输完整的瓦片地图数据,仅在 0x03 (LoadAct) 包中下发 32 位 mapSeed 与当前 areaId(并伴随 0x07/0x08 房间加载通知):
MapService在收到LoadAct后,使用src/common/drlg与服务端完全一致的 1.13c DRLG 算法,根据mapSeed在浏览器端毫秒级还原整张地图的 Floor / Wall / Roof / Collision 网格。- 从
/act-packs/tiles/按需流式加载对应LvlType的 WebP/PNG 瓦片图集并上传至TileAtlasGpuCache。
3.3 移动预测与网络平滑 (motion/)
LocalMovementPredictor:玩家左键点击地面或按住移动时,本地立即沿 A* 路径按角色Velocity推進预测坐标,同时由OutboundRateLimiter按 250ms 节流向 D2GS 发送0x01 (Walk)/0x03 (Run)。当收到服务端0x15 (ReassignPlayer)强制拉回包时平滑纠正坐标。RemoteEntityInterpolator:将 D2GS 下发的离散实体移动目标点 (0x0F/0x10,0x67/0x68) 转化为 60fps 连续内插位移与 8/16 方向朝向切换。
3.4 WebGL2 等距视角渲染器 (render/)
- 深度排序 (Painter's Algorithm + Sub-tile Sorting):将地面瓦片、阴影、地面物品、角色/怪物多部位 DCC/DC6 纸娃娃图层 (
EntityArtLoader)、投射物 (missile-overlay-renderer) 与悬挑屋顶按等距子格深度(X + Y)严格排序合批绘制。 - 完整 HUD 面板 (
ui/):支持角色属性面板 (C/A)、背包与穿戴 (I/B)、技能树与快捷技能选择 (T/S)、任务日志 (Q)、佣兵面板 (O)、小站传送菜单、NPC 商店/赌博/修理、储物箱与赫拉迪克方块以及 Tab 小地图 (Minimap)。
4. 常用开发与验证命令
# 启动本地开发服务器 (默认监听 http://127.0.0.1:5173/play.html)
npm run dev
# 单独对 src/client 进行严格类型检查
npx tsc -p tsconfig.client.json --noEmit
# 构建生产环境客户端静态包
npm run build