docs: add dedicated module READMEs and rewrite root README with single-client guide
This commit is contained in:
parent
6780018ada
commit
eb8447cc00
495
README.md
495
README.md
|
|
@ -1,327 +1,248 @@
|
||||||
# d2web
|
# Diablo II: Lord of Destruction (v1.13c) — Web Port
|
||||||
|
|
||||||
从零实现的**暗黑破坏神 II(v1.13c)Web 引擎**(纯 TypeScript + Vite + WebGL2,**零运行时依赖**),在浏览器里读取
|
## 1. 项目概述
|
||||||
用户自备的经典版 D2 归档(MPQ)或离线烘焙包,完整还原等距地图与 Glide 动态光影、原版等距精灵自动地图(Automap / Minimap)、七大职业 16 层角色合成、221 个原版技能、流式怪物生态、1.13c 宝藏等级(TC)掉落与未鉴定辨识系统、以及城镇 NPC 交易/赌博/修理交互。
|
|
||||||
|
|
||||||
- **仓库不含任何暴雪资源**:没有 `.mpq` / `.dc6` / `.dt1` / 地图图集 PNG;原版数据要自己放进 `samples/d2/`。
|
本项目是 **《暗黑破坏神 II:毁灭之王》(Diablo II: Lord of Destruction v1.13c)** 的高精度 Web 移植实现。项目严格遵循原版 1.13c 反编译二进制汇编(`D2Common.dll`、`D2Client.dll`、`D2Game.dll`、`D2Net.dll`、`Bnclient.dll`、`D2MCPClient.dll`、`Fog.dll`)与官方 MPQ 数据表(`Levels.txt`、`LvlTypes.txt`、`SuperUniques.txt`、`Skills.txt`、`TreasureClassEx.txt` 等)作为唯一事实基准(Ground Truth):
|
||||||
- **代码可复现一切**:格式解码、DRLG 地图构建、资源包烘焙、角色与特效合成都在这份代码里,脚本可重跑。
|
|
||||||
- 路线图、实现细节、验证方法论与未完成项在 [`ROADMAP.md`](ROADMAP.md)(README 只做总览与部署使用)。
|
|
||||||
|
|
||||||
## 总览
|
- **1:1 原生网络协议兼容**:完整实现 BNCS(战网登录/聊天,端口 `6112`)、MCP(Realm 角色管理/建房加房,端口 `6113`)与 D2GS(Huffman 压缩帧、167 个 S2C 操作码、C2S 指令及物品比特流,端口 `4000`),浏览器客户端可通过轻量 TCP-to-WebSocket 桥直接连入原版 C++ **PvPGN + D2GS (1.13c)** 战网服务器。
|
||||||
|
- **种子驱动的确定性 DRLG 地图重建**:1:1 复刻 `D2Common.dll` 64 位进位乘法随机数 (`0x6FDAA9E0`) 与三大 DRLG 拓扑算法(Preset 预设、Maze 地牢迷宫、Outdoors 野外生成),客户端仅凭 D2GS 下发的 32 位 `mapSeed` 即可在浏览器端还原与 C++ 服务端逐格一致的瓦片地图与碰撞网格。
|
||||||
|
- **WebGL2 高性能等距渲染与离线资产管线**:通过 Node.js 离线烘焙管线 (`src/baker`) 将原版 MPQ 中的 DT1/DS1 瓦片、DC6/DCC 角色与怪物动画、COF 复合图层、PL2 调色板与 TBL 字符串表预编译为静态图集与二进制包,配合 Service Worker 增量缓存与 WebGL2 合批渲染实现 60fps 流畅体验。
|
||||||
|
- **严格的模块化架构隔离**:全仓按原版 DLL 职责划分为五大核心代码模块与独立工具集,由多套独立 `tsconfig.*.json` 与架构边界测试(`tests/arch/boundaries.test.ts`)强制保障零跨层污染。
|
||||||
|
|
||||||
| 能力 | 说明 |
|
---
|
||||||
| --- | --- |
|
|
||||||
| **等距地图与动态光影** | DS1 + DT1 投影(2:1 dimetric,格 80×40 px),地板 / **阴影层(`type 13`)** / 墙体与场景物件(按画家序交错深度排序) / **屋顶**(进屋自动渐隐)多层绘制;SplitMix64 空间哈希 + `RarityFrameIndex` 加权选瓦片变体;**1.13c 原版 Glide 动态光照系统**(子格视线遮挡、玩家火炬、飞行投射物/爆炸动态光源、火把/火盆/小站/神殿环境光源、昼夜流转与顶部 9 档光照预设切换);动态瓦片序列与错峰物件动画 |
|
|
||||||
| **碰撞与 A* 寻路系统** | 每格 5×5 个 sub-tile(16×8 px 各向异性)标志位(全层 OR 合并,含 `type 13` 阴影层及通用 `Blank.dt1` / `InvisWal.dt1` / `Warp.dt1` 阻挡规则),虚空越界格子全封闭保护;角色与怪物按真实阻挡子格计数梯度脱困;支持鼠标点击 A* 自动寻路移动、攻击、拾取掉落、NPC 交谈与跨图 |
|
|
||||||
| **真实关卡与世界连通** | 已烘焙 **365 张地图**,覆盖 5 幕全部 **136 个关卡 ID**(35 个预置关卡 `65` 变体 + **70 个随机迷宫 `210` 变体 + 31 个野外关卡 `90` 变体**,1:1 移植自 D2MOO / `D2Common.dll` DRLG 算法);支持鼠标点击楼梯/洞穴入口(Warp / Entrance)切图、野外边界无缝跨越、**双向回城传送门(Town Portal,精确对齐 DS1 Object #33 城镇落点)**与跨幕**小站(Waypoint)传送网络** |
|
|
||||||
| **七大职业与角色合成** | 完整支持亚马逊(Amazon)、刺客(Assassin)、野蛮人(Barbarian)、德鲁伊(Druid)、死灵法师(Necromancer)、圣骑士(Paladin)、女巫(Sorceress)七大职业的 DCC + COF 16 层组件装配与 8 方向动画,支持顶部工具栏实时热切换职业并自动装配初始专属套装与储物箱 |
|
|
||||||
| **全技能系统(221 技能)** | 210 个各职业技能(7 职业 × 3 系 × 10 技能,已全部通过 M1–M30 全职业终极质量门禁)与 11 个通用技能(普攻/踢击/投掷/反召唤/辨识与回城卷轴和书等),严格复现 1.13c 汇编公式、协同加成(Synergies)、`AnimData.d2` 关键帧事件、149 项原版投射物/爆炸图集(零黑边加法混合)、558+ 项施法/状态/光环(含 33 个圣骑士光环)叠加特效、死灵/德鲁伊召唤物与刺客陷阱系统 |
|
|
||||||
| **怪物生态、掉落鉴定与商人交易** | 基于 `Levels.txt` / `MonStats.txt` / `SuperUniques.txt` 流式房间激活(`MonsterStreamingManager`),还原普通怪、头目(Champion `[2,4]`)、金怪(Unique `[3,6]` 随从)及全幕固定暗金 Boss(含秘密母牛关地狱母牛等 78 套实体动画包),支持实时调节怪物密度与精英倍率;完整实现 1.13c 多难度宝藏等级(TC)递归掉落、16×8 子格防卡死扇形散落、原版 `flp*.dc6` 抛物线弹跳与星光闪烁、魔法/稀有/套装/暗金**未鉴定(Unidentified)掉落与卷轴/书辨识**、以及城镇 NPC 原版对话菜单与**商人买卖/赌博/修理(`buysell.dc6`)**完整闭环 |
|
|
||||||
| **原版等距自动地图(Automap & Minimap)** | 基于 `D2Client.dll` (`0x6fb0f080..0x6fb12c28`) 逆向复现,烘焙 8 张原版 DC6 自动地图图集(`MaxiMap` / `Act2Map` / `Act4Map` / `ExTnMap` 全尺寸与半尺寸),按 `floors -> walls -> objects -> extras` 四层等距投影渲染;支持**右上角缩略小地图(`nDivisor=20`)**与**全屏自动地图(`nDivisor=10`)**双模式(面板开启自动避让/偏移)、八向距离迷雾揭露、12 段闭合多边形方向十字标(玩家/NPC/召唤物/Boss)、双向传送门与出口 `Font6` 标签及 `F9` 透明度 / `F10` 标签开关 |
|
|
||||||
| **完整 UI / HUD 交互** | 800×600 原版底栏控制台(流体红蓝血球与中毒覆盖、按技能树行序排列的 Speedbar 技能弹窗与 `F1~F8` 绑定、可展开腰带)、左/右宽屏 400px 停靠面板(背包与装备纸娃娃、角色属性面板、3 系技能树、私人储物箱、赫拉迪克方块及合成按钮、商人/赌博面板、羊皮纸任务日志、小站传送菜单)、严格对齐 `.tbl` 的中英双语词缀 Tooltip、动态手套/交易/修理/辨识专属鼠标光标、鼠标悬浮与 `Alt` 地面物品高亮标签、以及 `/players 1-8` 控制台指令 |
|
|
||||||
| **资源包(离线烘焙)** | 索引色与 32-bit RGBA PNG 图集页(≤2048²,PLTE + tRNS 取自各幕 `pal.pl2`)+ `.r8` 紧凑像素包 + `scene.json`(绘制列表、阴影层、Automap 层、碰撞 RLE、出生点、怪物与对象元数据)+ `manifest.json` |
|
|
||||||
| **按需读归档** | 也可不烘焙,直接用 HTTP Range 只拉需要的 MPQ 字节当场解码(`?live=1`,慢,作为回退路径) |
|
|
||||||
| **多维场景与调试选择器** | 顶部工具栏支持实时切换:职业 → 章节 → 场景 → 细分场景 → 光照预设(9 档) → 怪物密度(`0.5x~8x`) → 精英倍率(`0.5x~All Elite`);中文场景名见 `src/game/level-names-zh.ts` |
|
|
||||||
|
|
||||||
**开发进展**:当前底层引擎、1:1 D2MOO DRLG 迷宫与野外地图生成、Glide 动态光影、1.13c 原版等距精灵自动地图/小地图、七大职业 221 技能、流式怪物与精英群生态、1.13c 掉落/未鉴定辨识/城镇商人交易以及全套 UI 面板已全面打通。下一步将继续推进 `.d2s` 官方二进制存档双向互通与可破坏场景物件深入演进,详见 [`ROADMAP.md`](ROADMAP.md)。
|
## 2. 模块概述与 README 链接
|
||||||
|
|
||||||
### 代码结构
|
项目源码按职责边界严格拆分为以下模块,点击各模块的 `README.md` 可查看详细的子目录结构、核心算法与验证命令:
|
||||||
|
|
||||||
```
|
| 模块路径 | 对标原版组件 | 运行环境与边界约束 | 核心职责简述 | 详细文档 |
|
||||||
src/mpq/ MPQ v1 容器:hash/block 表、Storm 加密、分扇区编解码、PKWARE implode/explode、ADPCM/Huffman 音频、Range 读取
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
src/formats/ dc6 / ds1 / dt1 / pal / pl2 / cel / pcx / tbl / sprite / dcc / cof / animdata / automap-table / bitstream
|
| [`src/common`](./src/common) | `D2Common.dll` `Storm.dll` `D2Lang.dll` | 纯 TypeScript (`ES2022`),零 DOM / 零 Node.js 依赖 | MPQ 与原生二进制格式解析器 (DC6/DCC/DT1/DS1/COF/PL2/TBL)、`D2DataRegistry` 数据表中心、1.13c DRLG 随机地图生成算法、64 位 `D2Rng` 与烘焙校验契约 (`pack-contract`) | [src/common/README.md](./src/common/README.md) |
|
||||||
src/game/ 等距场景与碰撞、关卡拓扑与跨图、DCC+COF 角色合成、怪物流式生成、1.13c 掉落/鉴定/商人系统、确定性 RNG
|
| [`src/netproto`](./src/netproto) | `D2Net.dll` `Bnclient.dll` `D2MCPClient.dll` `Fog.dll` | 纯协议栈模块,零外部模块依赖,唯一入口 `src/netproto/index.ts` | BNCS (`6112`) / MCP (`6113`) / D2GS (`4000`) 二进制协议编解码、XSHA-1 与 CheckRevision 认证、Fog.dll Huffman 解压、167 个 S2C 操作码解析、物品比特流与 WebSocket/TCP 传输层抽象 | [src/netproto/README.md](./src/netproto/README.md) |
|
||||||
drlg/ 1:1 移植自 D2MOO / D2Common.dll 的 DRLG 地图生成管线(迷宫 drlg-maze、野外 drlg-outdoors/outplace/outwild、预置房间与瓦片替换)
|
| [`src/client`](./src/client) | `D2Client.dll` `D2Gfx.dll` `D2Win.dll` `D2Launch.dll` | 纯浏览器客户端 (`DOM` + `WebGL2`),零 Node / 零 `server` / 零 `baker` 依赖 | 唯一页面入口 `play.html`、战网登录/选人/大厅前端界面、`OnlineSession` 与 `ClientWorld` 状态镜像、种子驱动的实时 DRLG 地图重建、移动预测与内插、WebGL2 渲染器、全套经典 HUD 面板与抓包检查器 | [src/client/README.md](./src/client/README.md) |
|
||||||
engine/ 1.13c 真实战斗管线、AST 公式求值器、Glide 动态光照栅格(light-grid / environment)、投射物引擎、光环扫描与召唤物管理
|
| [`src/server`](./src/server) | `D2Game.dll` | 纯确定性模拟 (`ES2022` + `WebWorker`),禁 DOM / 禁 Node / 禁非确定性随机与时钟 | 25fps (40ms/tick) 权威游戏循环、1.13c 战斗伤害与抗性管线、7 职业 221 个技能执行器、投射物与光环引擎、怪物 AI 与房间流式激活、TC 掉落管线与 `.d2s` 存档读写 | [src/server/README.md](./src/server/README.md) |
|
||||||
skills/ 221 个技能的具体实现模块与注册表(uni / ama / sor / nec / pal / bar / dru / ass)
|
| [`src/baker`](./src/baker) | 离线资源构建管线 | 纯 Node.js CLI 环境 (`types: ["node"]`),禁 DOM / 禁 `client` / 禁 `server` | 从原版 1.13c MPQ 归档中提取并烘焙瓦片图集 (`tiles`)、角色/怪物/NPC 实体 (`entities`)、投射物 (`missiles`)、覆盖层 (`overlays`)、HUD/前端 UI、动画表 (`animdata`) 与 SHA-256 资产清单 (`asset-manifest.json`) | [src/baker/README.md](./src/baker/README.md) |
|
||||||
src/ui/ 完整 UI / HUD 模块:原版等距自动地图与小地图(minimap)、背包、属性面板、技能树、控制底栏、小站、储物箱、方块、商人面板、任务日志、字体、鼠标指针
|
| [`tools/`](./tools) | 开发者与 QA 工具集 | Node.js / Playwright CLI | 无头协议测试机器人 (`d2-bot.ts`)、`.d2cap` 抓包离线重放器 (`netproto-replay.ts`)、`.d2s` 存档全解锁工具 (`d2s-unlock.ts`)、全谱系 136 关卡浏览器审计 (`audit-levels-browser.ts`) 与 DRLG 差分对比工具 | [tools/README.md](./tools/README.md) |
|
||||||
src/render/ WebGL2 渲染器(多图集、动态光照着色、加法/常规混合、视口裁剪;含 missiles-meta 与 overlays-meta)
|
|
||||||
src/scene/ 页面级装配(act-scene 主游戏循环、A* 鼠标控制器、跨图过渡;资源包优先,失败回退到直读归档)
|
### 模块依赖拓扑图
|
||||||
src/data/ 1.13c 权威内嵌数据表(canonical-drop-data / canonical-tbl-strings / canonical-vendor-data / canonical-quest-data / skills-catalog / gitea-skill-issues.json)
|
|
||||||
scripts/ 资源包多进程烘焙(地图/UI/动画/实体/投射物/叠加特效)、格式/数据/部署校验、无头浏览器全量走查、夹具生成
|
```text
|
||||||
*.html 入口页面:index.html(双语选择门户)、acts.html / acts-zh.html / acts-en.html(中英战役主页面)、bnet.html(原版片头与战网完整流程)
|
┌──────────────────┐ ┌────────────────────┐
|
||||||
|
│ src/common │ │ src/netproto │
|
||||||
|
│ (Pure TS Base) │ │ (1.13c Wire Stack) │
|
||||||
|
└────────┬─────────┘ └─────────┬──────────┘
|
||||||
|
│ │
|
||||||
|
┌─────────┼──────────────────┐ │
|
||||||
|
▼ ▼ ▼ ▼
|
||||||
|
┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐
|
||||||
|
│ src/baker │ │ src/server │◄──┤ src/client │
|
||||||
|
│ (Node CLI) │ │ (D2Game Sim) │ │ (Browser WebGL2 Client) │
|
||||||
|
└─────────────┘ └──────────────┘ └─────────────────────────┘
|
||||||
|
*(注:src/client 与 src/server 之间完全解耦,仅各自依赖 src/common 与 src/netproto)*
|
||||||
```
|
```
|
||||||
|
|
||||||
## 美术资源与图集资产(Assets)
|
---
|
||||||
|
|
||||||
项目在离线烘焙和客户端运行时划分了清晰的美术资产目录结构,所有视觉素材均可从 1.13c 原版 MPQ 自动导出与打包:
|
## 3. 单客户端模式使用方法(Single-Client Mode Guide)
|
||||||
|
|
||||||
### 1. UI 界面图集、自动地图图集与面板切片 (`public/ui/` & `public/assets/ui/automap/`)
|
在**单客户端模式**下,Web 前端作为纯粹的 1.13c 在线客户端运行([`play.html`](./play.html)),所有战网账号认证、角色存档、房间管理与游戏权威战斗逻辑均由远端原版 **PvPGN (`bnetd` + `d2cs` + `d2dbs`) + D2GS (v1.13c)** 服务器承载。
|
||||||
|
|
||||||
- **综合图集 (Atlases)**:
|
完整跑通单客户端模式包含以下三个核心步骤:
|
||||||
- `items-atlas.png`:装备与物品大图集,同时包含背包/储物箱物品图标(`invfile`)与地面 2:1 等距掉落精灵(`flippyfile` / `flp*.dc6`),覆盖所有武器、防具、饰品(戒指、护身符、珠宝)、符文、药水、卷轴与金币堆,完整支持大/中/小护身符与首饰的原版 `VarInvGfx` 多视觉外观变体。
|
|
||||||
- `quests-atlas.png`:1–5 幕全部任务状态图标图集(未触发、进行中、已完成)。
|
|
||||||
- `skill-tree-tabs.png`:七大职业技能树的 3 系专属垂直选项卡图集(激活/未激活切片)。
|
|
||||||
- **1.13c 原版等距自动地图精灵图集 (`public/ui/automap-*.png` & `public/assets/ui/automap/`)**:
|
|
||||||
- 完整烘焙原版 `data\global\ui\AUTOMAP\` 下的 8 张 DC6 精灵表:
|
|
||||||
- 全屏自动地图(`nDivisor = 10`):`MaxiMap.png`(Slot 0 基础图集)、`Act2Map.png`(Slot 1 第二幕)、`Act4Map.png`(Slot 2 第四幕)、`ExTnMap.png`(Slot 3 资料片第五幕)。
|
|
||||||
- 右上角缩略小地图(`nDivisor = 20`):`MaxiMapS.png`、`Act2MapS.png`、`Act4MapS.png`、`ExTnMapS.png`。
|
|
||||||
- **经典功能面板背景与控件**:
|
|
||||||
- `ctrlpnl-800.png`:800×600 原版底栏控制台面板(包含左右技能槽底框、经验槽、腰带槽)。
|
|
||||||
- `inv-sheet.png` / `inv-tab-0.png` / `inv-tab-1.png` / `goldcoinbtn.png`:装备纸娃娃界面与 10×4 背包网格、主副手武器切换 Tab、金币丢弃按钮。
|
|
||||||
- `char-sheet.png`:角色属性与抗性详情面板。
|
|
||||||
- `stash-bg.png`:营地私人储物箱面板(`TradeStash.dc6`,含顶部标题凹槽与金币槽)。
|
|
||||||
- `cube-bg.png` / `miniconvert.png`:赫拉迪克方块(3×4 合成面板)与原版转化(Transmute)按钮。
|
|
||||||
- `vendor-bg.png` / `vendor-tabs.png` / `buysellbtn.png`:原版 `buysell.dc6` NPC 商人交易/赌博界面、分类选项卡与买/卖/修理交互按钮。
|
|
||||||
- `boxpieces.png` / `focus16.png`:原版 1.13c NPC 对话弹出菜单边框切片与焦点指示动画。
|
|
||||||
- `quest-bg.png` / `quest-tabs.png`:羊皮纸任务日志背景与 1–5 幕选项卡。
|
|
||||||
- `waypoint-bg.png` / `waypoint-tabs.png` / `waypoint-icons.png`:传送点菜单、各幕选项卡与石碑传送状态图标。
|
|
||||||
- **指示器与动态视觉元素**:
|
|
||||||
- `globe-life.png` / `globe-mana.png` / `globe-poison.png`:经典流体红蓝血球与中毒、法力燃烧覆盖层。
|
|
||||||
- `cursor.png` / `cursor-hand.png`:暗黑手套鼠标指针图集(包含空闲/点击状态机、商人买/卖/修理专用交易光标与辨识卷轴目标十字光标)。
|
|
||||||
- `border-left.png` / `border-right.png` / `overlap-left.png` / `overlap-right.png`:宽屏自适应下的左右面板停靠石柱边框与过渡阴影。
|
|
||||||
- `minipanel.png` / `minipanel-btns.png` / `popbelt.png` / `runbutton.png` / `menubutton.png` / `level-btn.png` / `skillpoints.png`:菜单微型按钮、升级加点按钮、跑步状态切换钮等。
|
|
||||||
- **原版位图字体 (`public/ui/fonts/`)**:
|
|
||||||
- 提供 6 套暗黑 II 经典字体纹理:`font6.png`、`font8.png`、`font16.png`、`font30.png`、`fontexocet10.png`、`fontformal12.png`。
|
|
||||||
|
|
||||||
### 2. 技能树背景、技能图标与法术投射物/叠加特效图集 (`public/skills/`、`public/missiles/`、`public/overlays/`)
|
---
|
||||||
|
|
||||||
- **全职业技能树背景切片 (`public/skills/bg_<cls>_<tab>.png`)**:
|
### 3.1 第一步:在 D2GS / PvPGN 机器上设置 TCP-to-WebSocket 桥
|
||||||
- 共 21 张 256×432 px 原版复古羊皮纸技能树背景原画,覆盖 7 大职业各自的 3 大技能分支:
|
|
||||||
- 亚马逊:`bg_ama_0.png`(标枪与长矛)、`bg_ama_1.png`(被动与魔法)、`bg_ama_2.png`(弓与十字弓)
|
|
||||||
- 刺客:`bg_ass_0.png`(武学艺术)、`bg_ass_1.png`(影子训练)、`bg_ass_2.png`(陷阱)
|
|
||||||
- 野蛮人:`bg_bar_0.png`(战吼)、`bg_bar_1.png`(战斗专家)、`bg_bar_2.png`(战斗技能)
|
|
||||||
- 德鲁伊:`bg_dru_0.png`(元素)、`bg_dru_1.png`(变形)、`bg_dru_2.png`(召唤)
|
|
||||||
- 死灵法师:`bg_nec_0.png`(召唤术)、`bg_nec_1.png`(毒素与白骨)、`bg_nec_2.png`(诅咒)
|
|
||||||
- 圣骑士:`bg_pal_0.png`(战斗技能)、`bg_pal_1.png`(攻击灵气)、`bg_pal_2.png`(防御灵气)
|
|
||||||
- 女巫:`bg_sor_0.png`(火焰法术)、`bg_sor_1.png`(闪电法术)、`bg_sor_2.png`(冰冷法术)
|
|
||||||
- **技能图标资产 (`public/skills/icon_*.png` 与 `public/ui/`)**:
|
|
||||||
- 包含 221 个技能的 48×48 px 原版技能图标,细分为普通态(`icon_<id>.png`)与激活/按下高光态(`icon_<id>_active.png`)。
|
|
||||||
- 涵盖七大职业全部 210 个技能,以及 11 个通用技能(普通攻击、踢击、投掷、反召唤、辨识/回城卷轴与书、迪勒瑞姆变身等)。
|
|
||||||
- 动态普通攻击图标:根据当前主手装备自动切换拳头图标(`icon_0_fist.png`)或武器剑图标(`icon_0_sword.png`),并具备投掷(`icon_2.png`)与反召唤(`icon_3.png`)专用图标。
|
|
||||||
- **法术投射物与爆炸图集 (`public/missiles/` & `samples/d2-packs/missiles/`)**:
|
|
||||||
- 由 `scripts/pack-missiles.ts` 结合 `Missiles.txt` 的 `CelFile` 字段从原版 DCC 解包烘焙的 **149 套** 32-bit RGBA PNG 精灵图集与同名 `.json` 帧锚点元数据。
|
|
||||||
- 对魔法投射物(`Trans: 1`)严格执行暗部底色零黑边过滤并在 WebGL 中以加法混合(`blendMode: 'additive'`)渲染,覆盖火焰弹/火球/陨石/九头蛇、冰弹/冰风暴/暴风雪/冰封球、充能弹/闪电链、牙齿/骨矛/骨灵、祝福之锤、标枪/箭矢与全部次生爆炸特效。
|
|
||||||
- **施法叠加层、光环与传送门特效图集 (`public/overlays/` & `samples/d2-packs/overlays/`)**:
|
|
||||||
- 由 `scripts/pack-overlays.ts` 结合 `Overlays.txt` 从原版 DCC 解包烘焙的 **558+ 套**特效图集。
|
|
||||||
- 涵盖各系施法前摇光效(Cast Overlays)、全部 33 个圣骑士进攻/防御光环与通用光环脚底环绕特效、死灵法师诅咒与野蛮人战吼头顶标记、德鲁伊变形/充能球、刺客聚气球,以及双向回城传送门的开启(`OP` 15 帧)与常驻(`ON` 15 帧)双层混合动画。
|
|
||||||
|
|
||||||
### 3. 角色与怪物实体动画包 (`samples/d2-packs/entities/`)
|
由于浏览器只支持 WebSocket (`ws://` / `wss://`) 而不支持直接建立原始 TCP Socket,需要在运行 PvPGN 与 D2GS 的服务器(或同内网网关机)上部署 **`websockify` + Nginx** 反向代理,将浏览器的三路 WebSocket 子路径桥接到对应的原生 TCP 端口:
|
||||||
|
|
||||||
- **七大职业模型**:
|
```text
|
||||||
- 亚马逊(`char-am`)、刺客(`char-ai`)、野蛮人(`char-ba`)、德鲁伊(`char-dz`)、死灵法师(`char-ne`)、圣骑士(`char-pa`)、女巫(`char-so`)。
|
浏览器 Web 客户端 (src/netproto WsStream)
|
||||||
- 由 16 个装备图层复合装配,解包出行走(`wl`)、跑动(`rn`)、待机(`nu`)、近战/远程攻击(`a1`/`a2`)、施法(`sc`)、受击(`gh`)、死亡(`dt`/`dd`)等 8 方向完整序列。
|
│
|
||||||
- 伴随同名 `.r8` 紧凑二进制像素包,用于在 WebGL/Canvas 中零拷贝极速解码渲染。
|
├─ wss://<host>/d2net/bnet ──► Nginx :443 ──► websockify 127.0.0.1:7001 ──► PvPGN bnetd (TCP :6112)
|
||||||
- **怪物与召唤物实体模型(共 78 套实体包)**:
|
├─ wss://<host>/d2net/realm ──► Nginx :443 ──► websockify 127.0.0.1:7002 ──► PvPGN d2cs (TCP :6113)
|
||||||
- 包含沉沦魔(Fallen)、骷髅(Skeleton)、僵尸(Zombie)、血鸟(Blood Raven)、格瑞斯华尔德(Griswold)、安达利尔(Andariel)、督瑞尔(Duriel)、墨菲斯托(Mephisto)、暗黑破坏神(Diablo)、巴尔(Baal)、秘密母牛关地狱母牛(Hell Bovine,`hellbovine`)等各幕常规怪物、固定暗金头目(SuperUniques)及其随从、死灵/德鲁伊/亚马逊/刺客召唤物的完整动画包与 `.r8` 调色板像素数据。
|
└─ wss://<host>/d2net/game ──► Nginx :443 ──► websockify 127.0.0.1:7003 ──► D2GS 1.13c (TCP :4000)
|
||||||
|
```
|
||||||
|
|
||||||
### 4. 场景瓦片图集 (`samples/d2-packs/act[1-5]/`)
|
#### 1) 安装 `websockify`
|
||||||
|
在 Linux 网关/宿主机(例如 Ubuntu/Debian)上安装 `websockify`:
|
||||||
|
```bash
|
||||||
|
sudo apt-get update && sudo apt-get install -y websockify nginx
|
||||||
|
```
|
||||||
|
|
||||||
- 365 个地图场景(65 个预置场景、210 个随机迷宫变体、90 个野外场景变体)分块切片图集,每个图集包含 ≤2048² 尺寸的索引色 PNG 瓦片页(地板层、阴影层、墙体层、屋顶层与场景物件层),附带 PLTE 调色板与透明度表。
|
#### 2) 配置 `systemd` 守护服务管理 3 个桥接端口
|
||||||
|
创建环境变量配置目录 `/etc/d2ws` 及三个端点的配置文件(若 D2GS 运行在另一台内网 Windows 机器上,将 `TARGET` 中的 `127.0.0.1` 替换为对应的内网 IP 即可):
|
||||||
## 结构化数据与 JSON 规范(Data & JSON)
|
|
||||||
|
|
||||||
引擎采用结构化 JSON 与内嵌权威数据表来驱动界面排版、图集映射、场景还原与游戏逻辑:
|
|
||||||
|
|
||||||
### 1. `public/ui/manifest.json` & `src/ui/baked-ui-meta.ts`(UI 与自动地图图集总清单)
|
|
||||||
由 `scripts/pack-ui.ts` 自动烘焙生成,为 UI 与自动地图系统提供像素级定位映射:
|
|
||||||
- `atlasWidth` / `atlasHeight`:`items-atlas.png` 装备与地面物品图集的分辨率规格。
|
|
||||||
- `questsAtlasWidth` / `questsAtlasHeight`:`quests-atlas.png` 任务图集的分辨率规格。
|
|
||||||
- `codeToInvFile` / `itemRects`:物品 3 字母代码到背包图标文件名的映射与 UV 矩形坐标表(`{ x, y, w, h }`),支持戒指、项链、珠宝和护身符的 `VarInvGfx` 多变体定位。
|
|
||||||
- `codeToFlippyFile` / `flippyRects`:物品代码到地面掉落精灵(`flp*.dc6`)的映射与 UV 坐标表,支撑地面真实 2:1 等距物品渲染。
|
|
||||||
- `automapAtlases`:8 张原版自动地图精灵表(`MaxiMap` / `MaxiMapS` / `Act2Map` / `Act2MapS` / `Act4Map` / `Act4MapS` / `ExTnMap` / `ExTnMapS`)的全部帧 UV 与 DC6 基线锚点偏移(`offsetX` / `offsetY`)。
|
|
||||||
- `questRects` & `images`:1–5 幕任务日志切片与各独立 UI 面板背景、边框、按键在 `public/ui/` 下的文件索引。
|
|
||||||
|
|
||||||
### 2. `public/ui/fonts/metrics.json`(位图字体排版度量)
|
|
||||||
- 记录 6 套经典字体(Exocet、Formal、Font6/8/16/30)的字形度量参数。
|
|
||||||
- 包含每个 ASCII 字符在字体图集上的矩形包围盒、字宽(`charWidths`)、字符高度、基线偏移与字间距(Kerning),为游戏内悬浮 Tooltip、装备描述、小地图标签和任务日志提供完全原版的排版效果。
|
|
||||||
|
|
||||||
### 3. `samples/d2-packs/index.json`(全关卡全局场景目录)
|
|
||||||
- 记录全游戏 5 幕 365 个地图块的元数据。
|
|
||||||
- 包含字段:章节编号(Act 1..5)、关卡 ID(Level ID 1..136)、内部场景标识、关卡类型(预置场景 `preset` / 随机迷宫 `maze` / 野外关卡 `wilderness`)、网格尺寸(Grid Bounds)、可用变体数(Variants)与对应的烘焙目录相对路径。
|
|
||||||
|
|
||||||
### 4. `samples/d2-packs/world-graph.json`(世界拓扑连通网络图)
|
|
||||||
- 从 `Levels.txt` 的连接参数(`Vis0..7`、`Warp0..7`)生成的全局世界拓扑图。
|
|
||||||
- 记录场景之间的连通边(Edges)、传送点(Waypoints)分布、楼梯/洞穴出入口(Warps)、野外边界开放开口(Perimeter Openings),支撑自动地图标注与跨关卡无缝切换。
|
|
||||||
|
|
||||||
### 5. `samples/d2-packs/anim/animdata.json`(动画关键帧事件权威表)
|
|
||||||
由 `scripts/pack-animdata.ts` 直接解析 1.13c `AnimData.d2` 二进制文件(570,304 字节,3,558 条记录)生成:
|
|
||||||
- 记录每个动作 Hash 的播放帧率(Frame Speed)、总帧数(Total Frames)。
|
|
||||||
- 精确解析动作事件标志位:`0x01` 判定为近战命中/施法触发判定帧,`0x02` 判定为投射物(Missile)发射事件帧,确保 25Hz 动作逻辑与原版单机完全一致。
|
|
||||||
|
|
||||||
### 6. `samples/d2-packs/anim/monstats2.json`(怪物组件与动画模式配置)
|
|
||||||
- 结构化提取自 `MonStats2.txt`。
|
|
||||||
- 记录所有怪物的身体构成组件、图层合成规则、各武器模式下的动作代码映射(如 `hth`、`1hs`、`2ht`、`bow`)。
|
|
||||||
|
|
||||||
### 7. `samples/d2-packs/entities/char-*.json` 与 `monster-*.json`(实体模型定义)
|
|
||||||
- 描述 7 大角色职业与 71 种怪物/召唤物的骨骼装配结构。
|
|
||||||
- 包含复合图层映射、8 方向动作切片元数据、每帧中心偏移(Pivot),搭配同名 `.r8` 文件在渲染管线中执行高效逐像素着色。
|
|
||||||
|
|
||||||
### 8. `samples/d2-packs/act<N>/<level>/scene.json` & `manifest.json`(单场景规格)
|
|
||||||
- `manifest.json`:当前场景所需的瓦片图集页清单与调色板信息。
|
|
||||||
- `scene.json`:记录等距地图的地板(`floors`)、阴影(`shadows`,`type 13`)、墙体(`walls`)、屋顶(`roofs`)与场景物件(`objectDrawables`)绘制列表、经 `Automap.txt` 规则预映射的自动地图四层单元格数据(`automap`)、采用 RLE 压缩的 5×5 子格碰撞阻挡网格(`grid`),以及出生点、小站、跨图入口与预设怪物群(`monsterPacks`)。
|
|
||||||
|
|
||||||
### 9. `src/data/canonical-*.ts` & `src/render/*-meta.ts`(1.13c 权威内嵌数据表)
|
|
||||||
- `canonical-drop-data.ts`:完整内嵌 `Weapons.txt`、`Armor.txt`、`Misc.txt`、`TreasureClassEx.txt`、`ItemRatio.txt`、`UniqueItems.txt`、`SetItems.txt`、`MagicPrefix/Suffix.txt`、`MonStats.txt` 与 `SuperUniques.txt` 多难度掉落与属性表。
|
|
||||||
- `canonical-tbl-strings.ts`:从原版 `string.tbl`、`expansionstring.tbl`、`patchstring.tbl` 提取的官方物品、词缀、怪物与技能名称字典。
|
|
||||||
- `canonical-vendor-data.ts` & `canonical-quest-data.ts`:各幕城镇 NPC 商人库存生成规则与 1–5 幕任务文本数据。
|
|
||||||
- `missiles-meta.ts` & `overlays-meta.ts`:投射物、爆炸、施法叠加层与光环图集的帧序列及锚点注册表。
|
|
||||||
|
|
||||||
## 部署与使用
|
|
||||||
|
|
||||||
### 1. 前置:自备游戏数据
|
|
||||||
|
|
||||||
把你自己合法拥有的**经典版暗黑破坏神 II(1.13c)** 数据放进 `samples/d2/`,至少需要
|
|
||||||
`d2data.mpq`、`d2char.mpq`、`d2exp.mpq`、`Patch_D2.mpq`。资源包模式(页面默认)只需要
|
|
||||||
`samples/d2-packs/`——它不在 Git 里,按下面的「资源包从哪来」下载解包后,**没有原版数据也能直接运行全部烘焙地图与角色战斗**。
|
|
||||||
|
|
||||||
`samples/d2/` 通常做成软链接,指向一个**磁盘上的持久目录**。切勿链到 `/tmp`——它是内存盘,
|
|
||||||
重启即清空,链接会变死链而角色/怪物退化成占位方块。本机的实际摆放、清单与逆向参考用的原版
|
|
||||||
DLL 见 [`docs/LOCAL_DATA.md`](docs/LOCAL_DATA.md)。
|
|
||||||
|
|
||||||
### 2. 资源包从哪来(不在 Git 里)
|
|
||||||
|
|
||||||
烘焙资源包(365 个地图块 / 136 关、78 套角色与怪物实体、投射物与叠加特效图集、动画表与世界拓扑图)**不在本仓库里**——因为索引色与 RGBA PNG 无法被 git 的 delta 压缩,随代码仓库分发会让每次重烘都使仓库体积暴涨。它放在独立的**图库仓库**,那里刻意**只保留一个提交**(每次重烘 orphan 提交 + force push),体积恒定在「一份快照」:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.projectdiablo2.cn/troytt/diablo2-web-assets.git samples/d2-packs
|
sudo mkdir -p /etc/d2ws
|
||||||
|
|
||||||
|
# 1. BNCS (bnetd, TCP 6112)
|
||||||
|
sudo tee /etc/d2ws/bnet.env >/dev/null <<'EOF'
|
||||||
|
LISTEN=127.0.0.1:7001
|
||||||
|
TARGET=127.0.0.1:6112
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 2. MCP Realm (d2cs, TCP 6113)
|
||||||
|
sudo tee /etc/d2ws/realm.env >/dev/null <<'EOF'
|
||||||
|
LISTEN=127.0.0.1:7002
|
||||||
|
TARGET=127.0.0.1:6113
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 3. D2GS Game Server (D2GS.exe 1.13c, TCP 4000)
|
||||||
|
sudo tee /etc/d2ws/game.env >/dev/null <<'EOF'
|
||||||
|
LISTEN=127.0.0.1:7003
|
||||||
|
TARGET=127.0.0.1:4000
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
只想要一份压缩包(不需要 git):
|
创建模板单元文件 `/etc/systemd/system/d2ws@.service` 并启动服务:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -O https://www.laiseek.xyz/diablo2/assets/d2-packs-2026-09-14.tar.xz
|
sudo tee /etc/systemd/system/d2ws@.service >/dev/null <<'EOF'
|
||||||
sha256sum d2-packs-2026-09-14.tar.xz # 应为 9cdfd0c19ac68de842c6725070b65d056e25f5bcc77f36d6d9a29cd9f1b431e8
|
[Unit]
|
||||||
tar xJf d2-packs-2026-09-14.tar.xz # 解出 samples/d2-packs/
|
Description=Diablo II WebSocket-to-TCP Bridge (%i)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
EnvironmentFile=/etc/d2ws/%i.env
|
||||||
|
ExecStart=/usr/bin/websockify --heartbeat=30 ${LISTEN} ${TARGET}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now d2ws@bnet d2ws@realm d2ws@game
|
||||||
```
|
```
|
||||||
|
|
||||||
仓库里只保留 `.gitignore` 规则与本文档;要自己生成包就照第 3 步从原版 MPQ
|
#### 3) 配置 Nginx `/d2net/*` WebSocket 反向代理
|
||||||
烘焙,再用 `npm run publish:packs` 发布到图库仓库(脚本会自动打包地图、动画、实体、投射物、叠加层与世界图并重建单提交历史)。
|
在 Nginx 站点配置(如 `/etc/nginx/sites-enabled/default`)的 `server` 块中加入 `/d2net/` 路由规则:
|
||||||
|
|
||||||
### 3. 本地跑起来
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install # 仅 vite / typescript / tsx / vitest / @types/node
|
|
||||||
tsx scripts/make-fixtures.ts samples/fixtures # 夹具:DC6 + 调色板 + 文本表
|
|
||||||
tsx scripts/make-map-fixtures.ts samples/fixtures # 夹具:DT1 + DS1 + 夹具 MPQ
|
|
||||||
npm run pack:data # 从 samples/d2/ 烘焙 365 场景图集与 Automap 层 → samples/d2-packs
|
|
||||||
npm run pack:ui # 烘焙 UI 综合图集、地面物品图集、8 张 Automap 图集与 manifest.json
|
|
||||||
npm run pack:animdata # 烘焙 AnimData.d2 与 monstats2.json
|
|
||||||
npm run pack:entities # 多进程并发烘焙 7 大职业模型与 71 套怪物/召唤物实体动画包
|
|
||||||
npm run pack:missiles # 烘焙 149 套法术投射物与爆炸 RGBA 图集及 missiles-meta.ts
|
|
||||||
npm run pack:overlays # 烘焙 558+ 套施法叠加层、光环与传送门图集及 overlays-meta.ts
|
|
||||||
npm run dev # 启动 Vite:http://127.0.0.1:5173/acts.html
|
|
||||||
```
|
|
||||||
|
|
||||||
`pack:*` 系列脚本需要原版 MPQ;只用上面下载来的 `samples/d2-packs/` 可以跳过烘焙步骤直接 `npm run dev`,
|
|
||||||
代价是 `?live=1` 与重新烘焙不可用。
|
|
||||||
|
|
||||||
### 4. 页面与操作
|
|
||||||
|
|
||||||
| 页面 | 用途 |
|
|
||||||
| --- | --- |
|
|
||||||
| `/index.html`(或访问根路径 `/`) | **双语版本选择门户页**:选择简体中文版(`CHI.tbl`)或英文原版(`ENG.tbl`)进入庇护之地 |
|
|
||||||
| `/acts.html` / `/acts-zh.html` / `/acts-en.html` | **战役主场景(中/英双语)**:全屏 WebGL2 画布 + Glide 动态光影 + 等距精灵自动地图/小地图 + HUD 控制底栏 + 左右停靠全套功能面板 + 7 职业漫步战斗与打宝交易 |
|
|
||||||
| `/bnet.html` | **原版前端与战网(Battle.net)7 阶段完整流程页**:800×600 原版片头、主菜单、战网登录、篝火 7 职业角色创建/选择、大厅建房并无缝进入第一幕罗格营地 |
|
|
||||||
|
|
||||||
#### 页面查询参数(`/acts.html`)
|
|
||||||
|
|
||||||
```
|
|
||||||
?hero=so|am|ne|pa|ba|dz|ai 指定初始职业(女巫/亚马逊/死灵/圣骑/野蛮人/德鲁伊/刺客)
|
|
||||||
?act=1..5 指定章节(1..5)
|
|
||||||
?level=<地图块 label> 直接指定细分场景,如 33-act-1-cathedral-cathy3
|
|
||||||
?lighting=auto|noon|morning|sunset|night|cave|hell|eclipse|off 指定场景光照预设
|
|
||||||
?density=0.5|1|2|4|8 指定怪物密度倍率(默认 1,即 1.13c 原版密度)
|
|
||||||
?elite=0.5|1|2|4|all 指定精英怪(头目/金怪)生成倍率
|
|
||||||
?quadrant=<DS1 名> 直读归档模式下指定该关卡的某个 DS1
|
|
||||||
?live=1 不走资源包,直接按 HTTP Range 读 MPQ 解码(慢)
|
|
||||||
?pack=<目录> 换一个资源包目录 ?base=<目录> 换一个归档目录
|
|
||||||
?arena=1&class=<cls>&skill=<id>&slvl=<lvl>&autocast=1 启动竞技场自动验证模式
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 完整操作快捷键
|
|
||||||
|
|
||||||
- **移动、交互与视口**:
|
|
||||||
- **鼠标左键点击**:A* 自动寻路移动、近战/左键技能攻击怪物、拾取地面掉落物品/金币、点击城镇 NPC 弹出对话菜单(交谈/交易/赌博/修理)、点击储物箱/小站/双向传送门交互、**点击楼梯/洞穴口(Warp / Entrance)切换关卡**
|
|
||||||
- **鼠标右键点击**:向鼠标方向施放当前选中的右手技能;在背包中**右击回城之书/卷轴**开启双向回城传送门,**右击辨识之书/卷轴**切换为辨识十字光标后左击未鉴定装备完成鉴定,**右击药水**直接饮用
|
|
||||||
- 方向键(当全屏自动地图未开启时):按等距屏幕方向移动角色
|
|
||||||
- 鼠标滚轮 或 `+` / `-`:视口无级缩放;`0`:缩放复位
|
|
||||||
- **自动地图与小地图(Automap & Minimap)**:
|
|
||||||
- `Tab` / `M`:开启 / 关闭自动地图(默认开启右上角缩略小地图)
|
|
||||||
- `V`:在**右上角缩略小地图(Corner Minimap,`nDivisor=20`)**与**全屏自动地图(Full-Screen Automap,`nDivisor=10`)**之间切换
|
|
||||||
- `F9`:循环切换自动地图 3 档透明度(`100%` → `75%` → `50%`)
|
|
||||||
- `F10`:开启 / 关闭自动地图上的友方名称与出口目的地文字标签
|
|
||||||
- 方向键(全屏自动地图开启时):平移全屏自动地图视口(每步 `±8px`);`Home`:重置自动地图平移偏移
|
|
||||||
- **功能面板(宽屏左右停靠)**:
|
|
||||||
- `I` / `B`:开启 / 关闭背包与装备纸娃娃面板(右停靠)
|
|
||||||
- `A` / `C`:开启 / 关闭角色属性面板(左停靠)
|
|
||||||
- `T` / `S`:开启 / 关闭技能树面板(右停靠,3 系垂直选项卡切换与加点)
|
|
||||||
- `Q`:开启 / 关闭任务日志面板(左停靠,按幕查看真实任务状态)
|
|
||||||
- `P`:快捷施放双向回城传送门(Town Portal)
|
|
||||||
- `Esc` / `Space`:关闭当前开启的所有停靠面板、商人界面与弹出层
|
|
||||||
- **战斗与技能快捷栏**:
|
|
||||||
- 点击底栏左 / 右技能槽图标:打开向上展开的 Speedbar 技能选择弹窗(按技能树行序排列)
|
|
||||||
- 鼠标悬浮在 Speedbar 技能上按 `F1` ~ `F8`:绑定技能快捷键;在游戏过程中按 `F1` ~ `F8`:即时切换对应技能
|
|
||||||
- `Shift`(按住):强制原地站立攻击 / 施法(Force Stand Still)
|
|
||||||
- `1` ~ `4`:快捷饮用腰带第 1 ~ 4 列药水;`~` / `` ` ``:展开 / 折叠 4×4 腰带弹窗
|
|
||||||
- `Alt`(按住)或鼠标悬浮地面物品:高亮显示地面掉落物品名称标签(带防重叠阶梯排布)
|
|
||||||
- `R`:切换跑步 / 走路模式
|
|
||||||
- `W`:主副手武器切换(`I` / `II` 套)
|
|
||||||
- **控制台与调试功能**:
|
|
||||||
- `Enter`:打开游戏内聊天/控制台输入框,支持输入 `/players 1` ~ `/players 8` 动态调整游戏人数难度与掉落率
|
|
||||||
- 顶部工具栏下拉菜单:实时热切换 **7 大职业(`#hero`)**、**章节与细分场景**、**9 档场景光照预设(`#lighting`)**、**怪物密度(`#density`)** 与 **精英倍率(`#elite`)**
|
|
||||||
- `K` / `L`:快速保存 / 读取 `localStorage` 角色快照存档
|
|
||||||
|
|
||||||
### 5. 部署到服务器
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build:game # → dist-game/(base=/diablo2/)
|
|
||||||
rm -rf /var/www/d2web && mkdir -p /var/www/d2web && cp -r dist-game/. /var/www/d2web/
|
|
||||||
rm -rf /var/www/d2packs && mkdir -p /var/www/d2packs && cp -r samples/d2-packs/. /var/www/d2packs/
|
|
||||||
mkdir -p /var/www/d2data && ln -f samples/d2/*.mpq /var/www/d2data/ # 只有 ?live=1 用得到
|
|
||||||
```
|
|
||||||
|
|
||||||
nginx(`/etc/nginx/sites-enabled/default`):
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
location = /diablo2 { return 301 /diablo2/; }
|
# BNCS (端口 6112)
|
||||||
location = /diablo2/ { rewrite ^ /diablo2/acts.html last; }
|
location = /d2net/bnet {
|
||||||
location /diablo2/ { alias /var/www/d2web/; autoindex off; add_header Cache-Control 'no-store'; }
|
proxy_pass http://127.0.0.1:7001;
|
||||||
|
proxy_http_version 1.1;
|
||||||
location /diablo2/packs/ { # 资源包:可缓存
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
alias /var/www/d2packs/;
|
proxy_set_header Connection "upgrade";
|
||||||
autoindex off;
|
proxy_set_header Host $host;
|
||||||
add_header Cache-Control 'public, max-age=3600';
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
proxy_buffering off;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/diablo2/data/(?<d2file>[A-Za-z0-9_.-]+\.mpq)$ { # 只暴露 .mpq,不列目录
|
# MCP Realm (端口 6113)
|
||||||
alias /var/www/d2data/$d2file;
|
location = /d2net/realm {
|
||||||
autoindex off;
|
proxy_pass http://127.0.0.1:7002;
|
||||||
add_header Accept-Ranges bytes;
|
proxy_http_version 1.1;
|
||||||
add_header Cache-Control 'public, max-age=3600';
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# D2GS Game Server (端口 4000)
|
||||||
|
location = /d2net/game {
|
||||||
|
proxy_pass http://127.0.0.1:7003;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
proxy_buffering off;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
要点:归档必须支持 **Range**(否则页面会退化成整文件下载);`/root` 是 0700,所以用硬链接暴露给 nginx。
|
重载 Nginx 配置并验证服务状态:
|
||||||
部署后跑 `npm run verify:deploy` 自检。
|
```bash
|
||||||
|
sudo nginx -t && sudo systemctl reload nginx
|
||||||
|
systemctl is-active d2ws@bnet d2ws@realm d2ws@game
|
||||||
|
```
|
||||||
|
|
||||||
### 6. 自检命令
|
> **提示**:客户端的 `createWsBridgeResolver`(位于 [`src/netproto/transport/endpoint.ts`](./src/netproto/transport/endpoint.ts))会自动根据协议握手阶段返回的端口(`6112`、`6113`、`4000`)将连接重写至 `<wsBridgeUrl>/bnet`、`/realm` 与 `/game`,因此无需修改 D2GS 内部下发的 IP,只需确保 PvPGN 的 `realm.conf` / `address_translation.conf` 中配置的端口保持标准 `6113` 与 `4000` 即可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 第二步:如何烘焙离线美术资源(Offline Asset Baking)
|
||||||
|
|
||||||
|
Web 客户端运行所需的瓦片地图图集、角色/怪物 DCC 精灵、HUD 面板与动画速度表均通过 `src/baker` 从原版 1.13c MPQ 离线烘焙生成到 `public/` 目录。
|
||||||
|
|
||||||
|
#### 1) 安装项目依赖
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2) 放置原版 1.13c MPQ 文件
|
||||||
|
将原版 **Diablo II: Lord of Destruction v1.13c** 的 MPQ 文件放入(或软链接至)`samples/d2/` 目录:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run verify:deploy # 线上:页面 / 资源包索引 / 图集 / Range 206 / 旧入口 410
|
mkdir -p samples/d2
|
||||||
npm run verify:packs # 资源包与"现读现解"逐项比对(绘制序、阴影层、碰撞栅格逐字节、每帧像素哈希)
|
# 确保以下 4 个核心 MPQ 存在(音频 MPQ 如 d2sfx.mpq / d2music.mpq / d2xmusic.mpq 可选):
|
||||||
npm run verify:entity-packs # 校验 7 大职业与全部怪物实体动画包及 .r8 像素数据完整性
|
ls -lh samples/d2/
|
||||||
npm run verify:generators # 校验 1:1 D2MOO DRLG 迷宫与野外地图生成器(缺瓦片率 0.00%,连通可达率 100%)
|
# d2data.mpq d2char.mpq d2exp.mpq Patch_D2.mpq
|
||||||
npm run verify:world-graph # 校验全 5 幕世界拓扑连通图(Vis0..7 / Warp0..7 / 小站与边界开口)
|
|
||||||
npm run verify:world-walk # 校验跨关卡行走、楼梯切图、双向回城传送门与小站传送网络
|
|
||||||
npm run verify:monsters # 校验 Levels.txt 怪物群生成、头目/金怪精英配比与 SuperUniques 固定头目
|
|
||||||
npm run verify:tiles # 每个槽位画的是不是该有的瓦片类型(地面=type 0)+ 位置公式
|
|
||||||
npm run verify:alignment # 墙 / 地面基线、屋顶偏移与引擎公式一致
|
|
||||||
npm run verify:object-lookup # DS1 对象 id → token/mode 与 Objects.txt 交叉核对
|
|
||||||
npm run verify:acts # 关卡表 → DS1 → DT1 → 等距场景 + 碰撞
|
|
||||||
npm run verify:d2 # 真 MPQ 数据端到端解码
|
|
||||||
npm run verify:implode # PKWARE implode 解码器(全成员)
|
|
||||||
npm run verify:all # 综合校验:战斗 / 物品 / 任务 / 存档 / 网络 / 碰撞方向 / TBL / 音频 / 格式
|
|
||||||
tsx scripts/verify-automap.ts # 校验 1.13c 等距精灵自动地图(Automap.txt 映射、8 图集烘焙、双模式渲染与交互)
|
|
||||||
npm run typecheck # tsc --noEmit(0 errors 门禁)
|
|
||||||
npm test # 运行 Vitest 完整测试套件
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 数据与许可
|
#### 3) 执行全量烘焙与契约校验
|
||||||
|
```bash
|
||||||
|
# 一键烘焙全部离线资源到 public/act-packs/ 并生成 public/asset-manifest.json
|
||||||
|
npm run bake -- all
|
||||||
|
|
||||||
- 仓库**不含**暴雪美术:原版 MPQ、`reference/` 下的第三方参考源码都不入库(规则写在 `.gitignore` 与
|
# 烘焙完成后执行严格完整性校验(验证 233+3 个 DT1 瓦片、实体图集与 0 缺失文件)
|
||||||
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md));`samples/fixtures/`(本项目自产)与
|
npm run bake:verify
|
||||||
`samples/d2-packs/`(派生数据)只作为 `/diablo2/assets/` 下的归档发布,不进 Git 历史。
|
```
|
||||||
图集包每次重烘都会让 Git 仓库再长 ~60 MB(PNG 无法 delta 压缩),所以不再入库。
|
|
||||||
- 使用本引擎需要你自己合法拥有的游戏数据。生成类关卡(70 个随机迷宫 + 31 个野外关卡)严格移植自 D2MOO / 1.13c `D2Common.dll` 官方参数表与 DRLG 算法复现。
|
|
||||||
|
|
||||||
|
如果需要单独重新烘焙某一部分资源,也可以使用细粒度命令:
|
||||||
|
- `npm run pack:tiles`:仅烘焙全部 5 幕瓦片图集与 `drlg-bundle.{json,bin}`
|
||||||
|
- `npm run pack:frontend`:仅烘焙战网登录、角色选择与大厅前置界面资源
|
||||||
|
- `npm run pack:ui`:仅烘焙游戏内 HUD 面板、技能图标与鼠标指针
|
||||||
|
- `npm run pack:animdata`:仅提取 `AnimData.d2` 动画帧率表
|
||||||
|
- `npm run pack:entities`:仅烘焙怪物、SuperUniques(含随从)与场景交互物图集
|
||||||
|
- `npm run pack:missiles` / `npm run pack:overlays`:仅烘焙投射物或光环/状态覆盖层特效
|
||||||
|
- `npm run pack:manifest`:重新扫描 `public/` 并更新 `public/asset-manifest.json`(触发客户端 Service Worker 增量更新)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 第三步:如何启动服务与连接游戏
|
||||||
|
|
||||||
|
#### 方式 A:本地开发模式启动(Vite Dev Server)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
- 启动后浏览器访问 **`http://127.0.0.1:5173/play.html`**(访问根路径 `/` 也会自动重写到 `/play.html`)。
|
||||||
|
- **默认代理配置**:[`vite.config.ts`](./vite.config.ts) 已内置 `/d2net` WebSocket 代理(默认转发至远端测试服 `wss://www.laiseek.xyz/d2net/*`),因此本地启动后可直接登录进入游戏。
|
||||||
|
- **自定义切换 D2GS 服务器地址**:
|
||||||
|
1. **URL 参数方式**:访问 `http://127.0.0.1:5173/play.html?wsBridge=wss://your-d2gs-domain.com/d2net`(或本地桥 `ws://127.0.0.1:8080/d2net`)。
|
||||||
|
2. **UI 设置面板方式**:点击画面顶部 32px 工具栏右侧的 **⚙ Settings** 按钮,修改 **WS Bridge URL** 并保存刷新。
|
||||||
|
|
||||||
|
#### 方式 B:生产环境构建与静态部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 全仓类型检查(同时校验 common / netproto / server / client / baker 五套 tsconfig)
|
||||||
|
npm run typecheck
|
||||||
|
|
||||||
|
# 2. 构建生产静态产物(输出至 dist/,若需部署在 /diablo2/ 子路径下可执行 npm run build:game 输出至 dist-game/)
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 3. 本地预览生产构建包
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
在生产环境 Nginx 中,只需将构建生成的 `dist/` 目录挂载为静态站点根目录(或子路径 `/diablo2/`),并与 **3.1 节** 中的 `/d2net/{bnet,realm,game}` WebSocket 反向代理配置在同一个域名下,即可通过浏览器直接访问完整的在线暗黑 II 体验。
|
||||||
|
|
||||||
|
#### 方式 C:使用命令行无头 Bot 快速验证服务连通性
|
||||||
|
|
||||||
|
无需打开浏览器,可在终端使用 [`tools/d2-bot.ts`](./tools/d2-bot.ts) 直接测试 TCP 桥与 D2GS 建房/进图流程:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run bot -- --bridge wss://your-d2gs-domain.com/d2net --user <账号> --pass <密码> --char <角色名>
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# `src/baker` — 离线 MPQ 美术资产与数据表烘焙管线
|
||||||
|
|
||||||
|
`src/baker` 是运行在 Node.js 环境下的离线资产烘焙(Baking)工具链,负责将原版 **Diablo II: Lord of Destruction (v1.13c)** 的 MPQ 归档文件(`d2data.mpq`、`d2char.mpq`、`d2exp.mpq`、`Patch_D2.mpq` 等)解码、调色板转换、合批打包并生成供浏览器客户端零 MPQ 开销直接消费的静态资产包(输出至 `public/`)。
|
||||||
|
|
||||||
|
## 1. 模块职责与架构边界
|
||||||
|
|
||||||
|
- **TypeScript 工程约束(`tsconfig.baker.json`)**:
|
||||||
|
- `lib: ["ES2022"]`, `types: ["node"]` —— **纯 Node.js CLI 模块,严禁包含任何浏览器 DOM API**。
|
||||||
|
- 仅依赖 `src/common`(共享 MPQ 读取器、二进制格式解析器与 `pack-contract` 校验契约),严禁导入 `src/client`、`src/server` 或 `src/netproto`。
|
||||||
|
- **统一 CLI 入口**:[`src/baker/cli.ts`](./cli.ts)(通过 `npm run bake -- <target>` 调用)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/baker/
|
||||||
|
├── cli.ts # 统一命令行入口,支持分项烘焙、全量烘焙 (all) 与契约校验 (verify)
|
||||||
|
├── packers/ # 核心美术与数据打包器 (瓦片、实体、投射物、覆盖层、UI、前置界面、动画表、字体等)
|
||||||
|
├── extract/ # 1.13c 权威 TXT/BIN 数据表与 D2Net/D2MOO 常量提取脚本
|
||||||
|
├── io/ # PNG/WebP 图像编码、SHA-256 资产清单生成 (asset-manifest.ts) 与发布辅助工具
|
||||||
|
└── audit/ # Fail-Fast 烘焙产物完整性校验器 (verify-packs, verify-tiles, verify-entity-packs)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 烘焙目标与产物对照表
|
||||||
|
|
||||||
|
运行 `npm run bake -- <target>`(或对应 `npm run pack:*` 快捷命令)将从 `samples/d2/` 下的 MPQ 文件提取并生成以下静态资产:
|
||||||
|
|
||||||
|
| 烘焙子命令 (`cli.ts`) | 对应 `npm run` 快捷脚本 | 核心实现文件 | 输出目录 / 产物 (`public/`) | 说明 |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| `tiles` | `npm run pack:tiles` | `packers/pack-tiles.ts` | `public/act-packs/tiles/` | 烘焙全部 5 幕共 233 个关卡 DT1 + 3 个通用 DT1 (`Blank.dt1`, `InvisWal.dt1`, `Warp.dt1`) 瓦片图集及 `drlg-bundle.{json,bin}` |
|
||||||
|
| `ui` | `npm run pack:ui` | `packers/pack-ui.ts` | `public/act-packs/ui/` | 烘焙游戏内 HUD 底栏、面板背景、按钮、7 职业技能图标、鼠标指针与物品栏网格 DC6 精灵图 |
|
||||||
|
| `frontend` | `npm run pack:frontend` | `packers/pack-frontend-ui.ts` | `public/act-packs/frontend/` | 烘焙战网登录界面、角色选择营火背景、7 职业创建角色动画与大厅 UI 资源 |
|
||||||
|
| `animdata` | `npm run pack:animdata` | `packers/pack-animdata.ts` | `public/act-packs/animdata.json` | 提取 `data/global/AnimData.d2` 全量 COF 动画帧数、速度与关键帧触发事件表 |
|
||||||
|
| `entities` | `npm run pack:entities` | `packers/pack-entity-assets.ts` | `public/act-packs/entities/` | 烘焙全部怪物、SuperUniques(自动捆绑其随从 Minions)、NPC 与场景交互 Object 的 DCC/DC6/COF 图集 |
|
||||||
|
| `missiles` | `npm run pack:missiles` | `packers/pack-missiles.ts` | `public/act-packs/missiles/` | 烘焙 `Missiles.txt` 全部投射物 DCC 图集与发光混合模式元数据 |
|
||||||
|
| `overlays` | `npm run pack:overlays` | `packers/pack-overlays.ts` | `public/act-packs/overlays/` | 烘焙 `Overlays.txt` 全部光环、诅咒、Buff、命中特效与升级光柱 DCC 图集 |
|
||||||
|
| `acts` | `npm run pack:acts` | `packers/pack-act-assets.ts` | `public/act-packs/act1..act5/` | 按幕聚合关卡音频、环境调色板 (`PL2`)、物品掉落图标与角色纸娃娃分层 (`pack-char-so-layers.ts`) |
|
||||||
|
| `manifest` | `npm run pack:manifest` | `io/asset-manifest.ts` | `public/asset-manifest.json` | 递归扫描 `public/` 计算所有资产的字节大小与 SHA-256 哈希,供客户端 Service Worker 增量更新使用 |
|
||||||
|
| `verify` | `npm run bake:verify` | `audit/verify-packs.ts` | *(控制台校验报告)* | 执行 `src/common/pack-contract` 严格校验,确保零缺失文件 (`missingFiles === 0`) 且通用 DT1 完整 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 使用方法
|
||||||
|
|
||||||
|
### 4.1 准备原版 1.13c MPQ 文件
|
||||||
|
在执行烘焙前,请将原版 **Diablo II: Lord of Destruction v1.13c** 的 MPQ 文件放置在仓库根目录下的 `samples/d2/` 目录中(支持软链接):
|
||||||
|
|
||||||
|
```text
|
||||||
|
samples/d2/
|
||||||
|
├── d2data.mpq # 必需:基础数据、Act 1-4 瓦片、怪物、UI、音效
|
||||||
|
├── d2char.mpq # 必需:角色纸娃娃分层 DCC/COF 动画
|
||||||
|
├── d2exp.mpq # 必需:毁灭之王资料片 (Act 5、德鲁伊/刺客、扩展暗金/符文)
|
||||||
|
├── Patch_D2.mpq # 必需:1.13c 最终补丁数据表 (Levels.txt, Skills.txt, SuperUniques.txt 等)
|
||||||
|
├── d2sfx.mpq # 可选:音效资源
|
||||||
|
├── d2music.mpq # 可选:Act 1-4 背景音乐
|
||||||
|
└── d2xmusic.mpq # 可选:Act 5 背景音乐
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 执行全量或分项烘焙
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 一键执行全量离线资产烘焙 (tiles -> ui -> frontend -> animdata -> entities -> missiles -> overlays -> acts -> manifest)
|
||||||
|
npm run bake -- all
|
||||||
|
|
||||||
|
# 或者按需单独烘焙某一类资源(例如仅重打包瓦片或前端 UI):
|
||||||
|
npm run pack:tiles
|
||||||
|
npm run pack:frontend
|
||||||
|
npm run pack:entities
|
||||||
|
npm run pack:manifest
|
||||||
|
|
||||||
|
# 烘焙完成后执行严格完整性校验(Fail-Fast 契约检查)
|
||||||
|
npm run bake:verify
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
# `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`](../../play.html) $\rightarrow$ [`src/client/main.ts`](./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. 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
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/`)
|
||||||
|
1. **战网前置流程 (`FrontendRenderer` + `D2OnlineFlow`)**:
|
||||||
|
- 启动后加载 `/act-packs/frontend/frontend-ui.json`,渲染原版风格登录界面、角色选择界面(支持 7 职业动态纸娃娃预览)与战网大厅(Create Game / Join Game 房间列表)。
|
||||||
|
- 通过 `wsBridgeUrl`(默认 `/d2net`,可通过 URL 参数 `?wsBridge=...` 或顶部工具栏 Settings 面板配置)依次握手 BNCS (`/bnet`) 与 MCP (`/realm`)。
|
||||||
|
2. **进入游戏 (`OnlineSession` + `ClientWorld`)**:
|
||||||
|
- 拿到 MCP 颁发的 `GameHash` 与 `GameToken` 后,连接 D2GS (`/game`) 并创建 `D2gsServerAdapter`。
|
||||||
|
- `OnlineSession` 订阅全部 37 种 `ServerEvent`,实时更新 `ClientWorld` 中的本地玩家属性、背包/穿戴物品、周围怪物/NPC 状态、地面掉落与任务/小站进度。
|
||||||
|
|
||||||
|
### 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. 常用开发与验证命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动本地开发服务器 (默认监听 http://127.0.0.1:5173/play.html)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# 单独对 src/client 进行严格类型检查
|
||||||
|
npx tsc -p tsconfig.client.json --noEmit
|
||||||
|
|
||||||
|
# 构建生产环境客户端静态包
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
# `src/common` — 纯 TypeScript 共享底座模块
|
||||||
|
|
||||||
|
`src/common` 是 **Diablo II: Lord of Destruction (v1.13c)** Web 移植版的纯计算与数据结构底座,1:1 对齐原版 `D2Common.dll`、`Storm.dll` 与 `D2Lang.dll` 的核心逻辑。
|
||||||
|
|
||||||
|
## 1. 模块职责与架构边界
|
||||||
|
|
||||||
|
- **对应原版 DLL**:`D2Common.dll`(DRLG 地图生成、数据表、碰撞掩码、单位/技能/物品基础公式、64 位随机数)、`Storm.dll`(MPQ 归档解析与 PKWARE/Huffman/Adpcm 解压)、`D2Lang.dll`(`.tbl` 字符串表与本地化)。
|
||||||
|
- **TypeScript 工程约束(`tsconfig.common.json`)**:
|
||||||
|
- `lib: ["ES2022"]`, `types: []` —— **零 DOM 依赖、零 Node.js API 依赖、零外部运行时依赖**。
|
||||||
|
- 严禁依赖 `src/client`、`src/server`、`src/baker` 或 `src/netproto`(由 `tests/arch/boundaries.test.ts` 强制门禁校验)。
|
||||||
|
- 所有文件 I/O 均通过依赖注入的 `ArchiveSource` 接口完成,确保本模块可在浏览器主线程、WebWorker 与 Node.js 离线工具中无差别运行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/common/
|
||||||
|
├── mpq/ # Storm.dll MPQ 归档读取器、Hash/Block 表解密、多算法解压扇区
|
||||||
|
├── formats/ # 原生二进制格式解析器 (DC6, DCC, DT1, DS1, COF, PL2, PAL, CEL, PCX, TBL, AnimData, Bitstream)
|
||||||
|
├── data/ # D2DataRegistry 数据表注册中心与 TXT/JSON 数据模型定义
|
||||||
|
├── drlg/ # D2Common.dll 1.13c DRLG 随机地图生成器与碰撞/光照网格
|
||||||
|
├── world/ # 跨端共享的地图/关卡几何拓扑与寻路网格辅助计算
|
||||||
|
├── items/ # 物品基础属性、词缀、品质、孔数与符文之语公共计算逻辑
|
||||||
|
├── skills/ # 技能基础公式、协同加成 (Synergy) 与等级曲线解析
|
||||||
|
├── units/ # 单位属性 (StatList)、帧率驱动、状态位 (States) 与怪物基础数据
|
||||||
|
├── i18n/ # D2Lang.dll 字符串哈希与中英文双语 TBL 查找表
|
||||||
|
├── rng/ # D2Rng (64-bit Carry-Multiply 0x6FDAA9E0) 与 SplitMix64 空间哈希
|
||||||
|
└── pack-contract/ # 烘焙管线 (Baker) 与客户端 (Client) 共享的离线资产包 Schema 及校验契约
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 核心子系统详解
|
||||||
|
|
||||||
|
### 3.1 MPQ 与二进制格式解析 (`mpq/`, `formats/`)
|
||||||
|
- **`mpq-reader.ts`**:完整实现 MPQ v1 归档格式解析,支持 Hash Table / Block Table 加密种子计算、单文件与多扇区 PKWARE DCL / Zlib / Huffman 组合解压。
|
||||||
|
- **`dc6-parser.ts` / `dcc-parser.ts`**:解析 UI/物品/怪物/角色序列帧图像及方向图层数据,还原 DCC 变长比特流(Cell 缓冲与 EqualCells/PixelMask 双阶段编码)。
|
||||||
|
- **`dt1-parser.ts` / `ds1-parser.ts`**:解析地面/墙壁/屋顶瓦片(256×128 Isometric Diamond 与 RLE 子块)以及预制地图块(Floor/Wall/Shadow/Object/Substitution 图层与 NPC 巡逻路径)。
|
||||||
|
- **`cof-parser.ts` / `animdata-parser.ts`**:解析复合对象动画帧数、16 图层优先级组合顺序、关键帧触发事件(攻击命中、投射物释放、音效帧)及 `AnimData.d2` 动画速度表。
|
||||||
|
- **`pl2-parser.ts` / `pal-parser.ts`**:解析各幕 256 色调色板、光照衰减表、阴影混合表与色彩变换矩阵(染色/冰冻/毒素/暗金变色)。
|
||||||
|
|
||||||
|
### 3.2 数据注册中心 (`data/`)
|
||||||
|
- **`D2DataRegistry` (`data/index.ts`)**:集中加载并索引 `Levels.txt`、`LvlTypes.txt`、`LvlPrest.txt`、`LvlMaze.txt`、`LvlSub.txt`、`MonStats.txt`、`MonStats2.txt`、`SuperUniques.txt`、`Missiles.txt`、`Overlays.txt`、`Objects.txt`、`Skills.txt`、`Armor/Weapons/Misc.txt` 等全量 1.13c 数据表。
|
||||||
|
- 支持注入内存 JSON 快照或基于 `ArchiveSource` 的 MPQ 实时解析。
|
||||||
|
|
||||||
|
### 3.3 1.13c DRLG 地图生成引擎 (`drlg/`)
|
||||||
|
严格复刻 `D2Common.dll` 的确定性关卡生成流水线:
|
||||||
|
- **通用 DT1 强制加载 (`drlg-room-tiles.ts`)**:遵循 `DRLGROOM_LoadDt1Files` (`0x6fdb8400`),所有关卡无条件挂载 `Act1/Outdoors/Blank.dt1`、`InvisWal.dt1`(含 `style=49, sequence=7` 隐形碰撞地板)与 `Warp.dt1`。
|
||||||
|
- **三种生成拓扑**:
|
||||||
|
- `drlg-preset.ts`:固定预设关卡(如罗格营地、鲁·高因、崔斯特瑞姆、混沌避难所等)。
|
||||||
|
- `drlg-maze.ts`:地牢迷宫房间拼接算法(如墓穴、修道院地下城、塔拉夏古墓、憎恨囚牢等)。
|
||||||
|
- `drlg-outdoors.ts`:野外随机边界、道路、河流、预设营地塞入与主题墙壁围合(如鲜血荒地、冰冷之原、库拉斯特丛林等)。
|
||||||
|
- **变体选择与碰撞构建 (`tile-library.ts`, `collision.ts`)**:
|
||||||
|
- 使用 SplitMix64 空间哈希 `pickVariant(worldX, worldY, orient, style, seq)` 彻底消除 45° 机械条纹伪影。
|
||||||
|
- 稀疏/未填充子格严格打上 `COLLIDE_MASK_INVALID` (`COLLIDE_BLANK | COLLIDE_WALL`),防止角色出生或穿墙掉入虚空。
|
||||||
|
|
||||||
|
### 3.4 确定性随机数 (`rng/`)
|
||||||
|
- **`D2Rng` (`rng/d2-rng.ts`)**:1:1 复刻 `D2Common.dll` 64 位进位乘法 PRNG(`seed = (0x6AC690C5 * low32 + carry) >>> 0`),保证给定相同的 32 位地图种子与难度,生成的地图拓扑与原生 C++ D2GS 完全一致。
|
||||||
|
|
||||||
|
### 3.5 离线资产契约 (`pack-contract/`)
|
||||||
|
- **`schemas.ts` / `validators.ts`**:定义 `public/act-packs/` 下所有离线资产包(`tiles`、`entities`、`missiles`、`overlays`、`ui`、`frontend`、`animdata`)的 JSON Schema 与 Fail-Fast 校验器(强制要求 `missingFiles === 0` 且三大通用 DT1 齐全)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 常用验证命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 单独对 src/common 进行严格无 DOM / 无 Node 类型检查
|
||||||
|
npx tsc -p tsconfig.common.json --noEmit
|
||||||
|
|
||||||
|
# 运行架构边界与 DRLG / 格式解析单元测试
|
||||||
|
npx vitest run tests/arch/boundaries.test.ts tests/drlg/
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# `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,默认 TCP `6112`)握手、CheckRevision 校验、CD-Key 哈希、XSHA-1 密码认证、账户注册与大厅聊天频道。
|
||||||
|
- `D2MCPClient.dll`:MCP(Realm Server / `d2cs`,默认 TCP `6113`)领域登录、角色列表读取、角色创建/删除、游戏房间创建 (`0x03`) 与加入 (`0x04`)。
|
||||||
|
- `D2Net.dll` + `Fog.dll`:D2GS(Game Server,默认 TCP `4000`)帧头解析、动态 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`](./index.ts) 导入符号,禁止跨入子目录深层路径导入(由 `tests/arch/boundaries.test.ts` 强制守护)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
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`)**:
|
||||||
|
1. `BncsClient` 完成 `SID_AUTH_INFO (0x50)` $\rightarrow$ `SID_AUTH_CHECK (0x51)` $\rightarrow$ `SID_LOGONRESPONSE2 (0x3A)` $\rightarrow$ `SID_LOGONREALMEX (0x3E)` 获取 64 字节 MCP Cookie。
|
||||||
|
2. `McpClient` 携带 Cookie 连接 `d2cs`,执行 `MCP_STARTUP (0x01)` $\rightarrow$ `MCP_CHARLIST2 (0x19)` $\rightarrow$ `MCP_CHARLOGON (0x07)` $\rightarrow$ `MCP_CREATEGAME (0x03)` / `MCP_JOINGAME (0x04)` 获取 D2GS GameHash 与 GameToken。
|
||||||
|
3. 自动交接至 `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. 常用验证命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 单独对 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>
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
# `src/server` — 1.13c 权威游戏模拟引擎 (`D2Game.dll`)
|
||||||
|
|
||||||
|
`src/server` 是 **Diablo II: Lord of Destruction (v1.13c)** 的确定性服务端权威逻辑实现,1:1 复刻原版 `D2Game.dll` 的 25fps (40ms/tick) 帧循环、战斗管线、221 个技能、怪物 AI、掉落表(TreasureClass)与存档系统。
|
||||||
|
|
||||||
|
## 1. 模块职责与架构边界
|
||||||
|
|
||||||
|
- **对应原版 DLL**:`D2Game.dll`。
|
||||||
|
- **TypeScript 工程约束(`tsconfig.server.json`)**:
|
||||||
|
- `lib: ["ES2022", "WebWorker"]`, `types: []` —— **严禁使用任何浏览器 DOM API 或 Node.js API**。
|
||||||
|
- **纯确定性模拟(Deterministic Simulation)**:模块内严禁调用 `Math.random`、`Date.now` 或 `performance.now`;所有随机性必须由种子的 `D2Rng` 驱动,所有时间推进必须由 25fps 离散帧号(`tickCount`)驱动。
|
||||||
|
- 仅允许依赖 `src/common` 与 `src/netproto`(门面入口),严禁导入 `src/client` 或 `src/baker`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/server/
|
||||||
|
├── engine/ # 25fps 核心模拟引擎 (GameEngine, combat-pipeline, missile-engine, aura-scanner, summon-manager, stat-list)
|
||||||
|
├── ai/ # 怪物 AI 决策树、仇恨/索敌、视野碰撞与动态房间流式加载 (room-streamer)
|
||||||
|
├── skills/ # 七大职业共 221 个技能与通用技能服务端执行器 (Amazon, Sorceress, Necromancer, Paladin, Barbarian, Druid, Assassin)
|
||||||
|
├── items/ # 1.13c 掉落管线 (TC NoDrop/Quality/Affix)、符文之语、宝石镶嵌、赫拉迪克方块合成与 NPC 商店服务
|
||||||
|
├── world/ # 场景交互物体 (神殿/宝箱/传送门/小站)、任务状态机 (Quests)、NPC 对话与治疗/赌博交易
|
||||||
|
├── save/ # 原版 1.13c .d2s 二进制角色存档读写器 (Checksum, Attributes, Skills, QuestData, Waypoints, ItemList)
|
||||||
|
├── scene/ # 服务端关卡实例生命周期与跨幕切换管理
|
||||||
|
└── adapter/ # LocalLoopbackAdapter:将 GameEngine 封装为标准 GameServerAdapter 契约接口
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 核心子系统详解
|
||||||
|
|
||||||
|
### 3.1 25fps 核心引擎与战斗管线 (`engine/`)
|
||||||
|
- **`GameEngine` (`engine/game-engine.ts`)**:维护权威世界状态,按 40ms 固定步长推进:
|
||||||
|
1. 玩家输入指令队列消费(移动、普通攻击、技能施放、拾取/穿戴/药水、NPC 交互)。
|
||||||
|
2. 状态持续时间衰减(中毒、冰冻、诅咒、战吼、神殿 Buff)与生命/法力自然回复。
|
||||||
|
3. 光环扫描器 (`aura-scanner.ts`) 周期性范围索敌与属性挂载。
|
||||||
|
4. 投射物引擎 (`missile-engine.ts`) 步进碰撞检测与子投射物分裂。
|
||||||
|
5. 怪物与召唤物 (`summon-manager.ts`) AI 决策与动作帧推进。
|
||||||
|
6. 状态总线 (`state-bus.ts`) 收集本帧脏状态并生成增量事件。
|
||||||
|
- **战斗伤害管线 (`combat-pipeline.ts`)**:严格遵循 1.13c 命中率公式(AR vs DR + 等级差修正)、盾牌格挡判定、物理/魔法/元素(火/电/冰/毒)六系伤害结算、抗性穿透/上限、碾压性打击 (Crushing Blow)、致命一击 (Deadly Strike / Critical Strike) 与撕开伤口 (Open Wounds)。
|
||||||
|
|
||||||
|
### 3.2 全职业技能系统 (`skills/`)
|
||||||
|
- **`skill-table.ts` & 各职业模块**:基于 `Skills.txt` 的 `srvdofunc` / `srvstfunc` 分发机制,完整实现亚马逊、法师、死灵法师、圣骑士、野蛮人、德鲁伊、刺客七大职业共 **221 个技能**(含协同加成公式、施法延迟 Cooldown、法力消耗、多段投射物生成与尸体交互)。
|
||||||
|
|
||||||
|
### 3.3 怪物 AI 与房间流式激活 (`ai/`)
|
||||||
|
- **`monster-ai.ts`**:基于 `MonStats.txt` 的 AI 参数(`aidel`, `aip1..aip8`)驱动沉沦魔复活、巫师远程风筝、冥河娃娃自爆、精英怪暗金词缀(闪电强化、特别快速、狂热灵气、免疫计算)及 Act Boss 专属 AI。
|
||||||
|
- **`room-streamer.ts`**:围绕玩家所在子格坐标按九宫格动态激活/休眠 DRLG 房间并按 `MonDen` 与 `SuperUniques.txt` 刷怪。
|
||||||
|
|
||||||
|
### 3.4 1.13c 物品掉落与存档系统 (`items/`, `save/`)
|
||||||
|
- **掉落管线 (`items/drop-pipeline.ts`)**:完整复刻 `TreasureClassEx.txt` 递归寻路、多人难度 `NoDrop` 指数衰减、MF (Magic Find) 边际递减有效值转换(Unique / Set / Rare / Magic 四级判定)以及 `MagicPrefix.txt` / `MagicSuffix.txt` 词缀池权重抽样。
|
||||||
|
- **`.d2s` 存档兼容 (`save/d2s-reader.ts`, `save/d2s-writer.ts`)**:支持直接导入或导出与原版 Diablo II v1.13c 二进制逐字节兼容的 `.d2s` 角色存档(含 `0xAA55AA55` 文件头、循环移位累加校验和、`gf` 属性比特流、`if` 技能表与 `JM` 物品列表)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 常用验证命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 单独对 src/server 进行类型检查(验证零 DOM / 零 Node 依赖)
|
||||||
|
npx tsc -p tsconfig.server.json --noEmit
|
||||||
|
|
||||||
|
# 运行服务端战斗、技能、掉落与存档单元测试
|
||||||
|
npx vitest run tests/server/ tests/skills/ tests/items/
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
# `tools` — 开发者调试、协议重放与自动化验证工具集
|
||||||
|
|
||||||
|
`tools/` 目录收录了围绕 **Diablo II Web (v1.13c)** 的命令行辅助工具、无头协议测试机器人、封包回放分析器、存档修改器以及全谱系浏览器自动化验证脚本。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 核心工具概览
|
||||||
|
|
||||||
|
| 脚本文件 | 运行命令示例 | 功能说明 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| [`d2-bot.ts`](./d2-bot.ts) | `npm run bot -- --help` | 无头 (Headless) 战网/D2GS 协议测试机器人。基于 `src/netproto` 直接通过原生 TCP 或 WebSocket 桥走完 BNCS 登录 $\rightarrow$ MCP 选人/建房 $\rightarrow$ D2GS 进图移动/施法全流程,无需启动浏览器即可验证服务端连通性。 |
|
||||||
|
| [`netproto-replay.ts`](./netproto-replay.ts) | `npx tsx tools/netproto-replay.ts <file.d2cap>` | `.d2cap` 网络抓包录制文件离线重放与解析工具。逐帧还原 Huffman 解压后的 S2C/C2S 十六进制流与解码后的 `ServerEvent` 明细,用于排查协议死锁或未知操作码。 |
|
||||||
|
| [`d2s-unlock.ts`](./d2s-unlock.ts) | `npx tsx tools/d2s-unlock.ts <char.d2s>` | 原版 1.13c `.d2s` 角色存档一键解锁工具。支持修改角色等级、属性点、技能点、金币,一键点亮全部三难度(Normal / Nightmare / Hell)全部 5 幕小站 (Waypoints) 与通关任务状态,并自动重算 `.d2s` 校验和。 |
|
||||||
|
| [`audit-levels-browser.ts`](./audit-levels-browser.ts) | `npx tsx tools/audit-levels-browser.ts` | **全谱系 136 关卡无头浏览器审计工具**。驱动 Playwright 遍历 `Levels.txt` 中全部 136 个关卡 ID,校验 DRLG 地图生成、通用 DT1 加载、出生点连通性(非虚空)与 WebGL2 瓦片渲染零报错。 |
|
||||||
|
| [`drlg-diff.ts`](./drlg-diff.ts) | `npx tsx tools/drlg-diff.ts` | DRLG 确定性差分对比工具。给定相同的 `mapSeed` 与 `areaId`,对比本仓库 DRLG 输出与 `D2Common.dll` Ground Truth 房间拓扑、瓦片 Style/Sequence 及碰撞网格的一致性。 |
|
||||||
|
| [`render-drlg-compare.ts`](./render-drlg-compare.ts) | `npx tsx tools/render-drlg-compare.ts` | 将 DRLG 生成的关卡碰撞网格、房间边界与瓦片图层渲染为可视化对比 PNG 图像,便于直观排查墙壁接缝与门洞连通性。 |
|
||||||
|
| [`verify-play.ts`](./verify-play.ts) | `npx tsx tools/verify-play.ts` | 端到端 `play.html` 冒烟验证脚本:使用 Playwright 启动客户端,验证战网前端 UI 加载、WebGL2 上下文初始化、静态资产零 404 以及 HUD 交互响应。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 专项回归验证脚本 (`tools/verify-*.ts`)
|
||||||
|
|
||||||
|
除了上述日常开发工具外,`tools/` 下还包含针对关键子系统的专项无头验证脚本:
|
||||||
|
|
||||||
|
- **`verify-360-comprehensive.ts` / `verify-all-features.ts`**:客户端 360° 全功能特性巡检(面板开关、小地图、技能栏、物品提示框、音效与设置面板)。
|
||||||
|
- **`verify-act-transitions.ts` / `verify-waypoints.ts`**:跨幕传送与全部 5 幕小站传送门跳转验证。
|
||||||
|
- **`verify-combat-vfx.ts` / `verify-lighting.ts`**:投射物、覆盖层特效 (Overlays) 与分幕环境光照着色器渲染验证。
|
||||||
|
- **`verify-monsters.ts` / `verify-save.ts`**:怪物/暗金 Boss 纸娃娃图集加载与 `.d2s` 存档导入导出闭环验证。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 典型使用示例
|
||||||
|
|
||||||
|
### 使用 `d2-bot.ts` 测试远端 D2GS 连通性
|
||||||
|
```bash
|
||||||
|
# 通过 WebSocket 桥连接远端战网并自动登录角色创建房间
|
||||||
|
npm run bot -- \
|
||||||
|
--bridge wss://www.laiseek.xyz/d2net \
|
||||||
|
--user myaccount \
|
||||||
|
--pass mypassword \
|
||||||
|
--char MySorceress \
|
||||||
|
--game test01
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 `netproto-replay.ts` 分析客户端录制的 `.d2cap`
|
||||||
|
在浏览器顶部工具栏点击 **Packet Inspector** 导出 `.d2cap` 文件后,可在终端离线回放:
|
||||||
|
```bash
|
||||||
|
npx tsx tools/netproto-replay.ts ./captures/session-2026.d2cap
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue