Go to file
troytt 6f935bccf6 feat(debug): add monster density and elite chance selectors to acts.html (Fixes #450) 2026-09-24 14:50:27 +00:00
.gitea/workflows test: 引入 Vitest 测试框架、覆盖率统计与 CI 流水线 (fixes #14) 2026-09-14 12:25:28 +00:00
docs feat(lighting): implement authentic Diablo II v1.13c Glide dynamic lighting system 2026-09-24 08:02:29 +00:00
public feat(paladin): Milestone M6 — 1.13c Paladin assets packaging & metadata registry 2026-09-24 11:30:34 +00:00
samples/fixtures feat(skills): authentic 1.13c Cast Overlay system and elemental spell animations (Fixes #386) 2026-09-23 03:53:57 +00:00
scripts fix(monsters): enforce 1.13c champion [2,4] and unique [3,6] minion pack sizes (Fixes #448) 2026-09-24 14:01:16 +00:00
src feat(debug): add monster density and elite chance selectors to acts.html (Fixes #450) 2026-09-24 14:50:27 +00:00
tests feat(debug): add monster density and elite chance selectors to acts.html (Fixes #450) 2026-09-24 14:50:27 +00:00
tools/go-oracle fix(collision): 修复 DT1 碰撞网格方向与朝向对齐 (fixes #4) 2026-09-14 07:54:38 +00:00
.gitignore chore(m5): stabilize full-suite test timeouts and track project/test docs 2026-09-22 04:20:32 +00:00
AGENTS.md docs(agents): require isolated git worktree for all changes, merge to main, then clean up 2026-09-24 06:07:28 +00:00
PROJECT.md docs(m5): mark M5 milestone DONE in PROJECT.md 2026-09-22 04:27:03 +00:00
README.md docs: update README with art assets, JSON data specifications, and UI parity 2026-09-22 13:12:25 +00:00
ROADMAP.md chore: 移除 index.html、net.html、walk.html 历史原型入口并优化根路径路由 2026-09-18 12:04:07 +00:00
TEST_INFRA.md chore(m5): stabilize full-suite test timeouts and track project/test docs 2026-09-22 04:20:32 +00:00
TEST_READY.md chore(m5): stabilize full-suite test timeouts and track project/test docs 2026-09-22 04:20:32 +00:00
THIRD_PARTY_NOTICES.md 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖) 2026-09-13 18:10:28 +08:00
acts.html feat(debug): add monster density and elite chance selectors to acts.html (Fixes #450) 2026-09-24 14:50:27 +00:00
arena.html chore: 移除 index.html、net.html、walk.html 历史原型入口并优化根路径路由 2026-09-18 12:04:07 +00:00
boss.html feat(ui/controls): 实现完整 UI/HUD 系统、操作快捷键对齐与装备词条染色 (fixes #134, fixes #135, fixes #136, fixes #137, fixes #138, fixes #139, fixes #140) 2026-09-21 11:09:10 +00:00
loot.html feat(boss): 新建幕Boss击杀模拟与真实属性掉落页面 (boss.html) 2026-09-19 03:42:32 +00:00
package-lock.json chore(scripts): 使用 tsx 运行 TypeScript 脚本,解除对特定 Node 运行时的依赖 (fixes #12) 2026-09-14 11:44:43 +00:00
package.json test(drop): end-to-end deterministic drop tests and headless browser audit (Fixes #408) 2026-09-24 11:13:35 +00:00
skills.html feat(ui/controls): 实现完整 UI/HUD 系统、操作快捷键对齐与装备词条染色 (fixes #134, fixes #135, fixes #136, fixes #137, fixes #138, fixes #139, fixes #140) 2026-09-21 11:09:10 +00:00
tsconfig.json test: 引入 Vitest 测试框架、覆盖率统计与 CI 流水线 (fixes #14) 2026-09-14 12:25:28 +00:00
vite.config.ts feat(ui/controls): 实现完整 UI/HUD 系统、操作快捷键对齐与装备词条染色 (fixes #134, fixes #135, fixes #136, fixes #137, fixes #138, fixes #139, fixes #140) 2026-09-21 11:09:10 +00:00
vitest.config.ts test: 引入 Vitest 测试框架、覆盖率统计与 CI 流水线 (fixes #14) 2026-09-14 12:25:28 +00:00

README.md

d2web

从零实现的暗黑破坏神 II 引擎(纯 TypeScript + Vite + WebGL2,零运行时依赖),在浏览器里读取 用户自备的经典版 D2 归档(MPQ),渲染等距地图、驱动角色走动、释放 221 个原版技能,并支持把地图与模型离线烘焙成 web 原生格式。

  • 仓库不含任何暴雪资源:没有 .mpq / .dc6 / .dt1 / 图集 PNG;原版数据要自己放进 samples/d2/。
  • 代码可复现一切:格式解码、地图构建、资源包烘焙、角色合成都在这份代码里,脚本可重跑。
  • 路线图、实现细节、验证方法论与未完成项在 ROADMAP.md(README 只做总览与部署使用)。

总览

能力 说明
等距地图渲染 DS1 + DT1 投影(2:1 dimetric,格 80×40 px),地板 / 墙 / 屋顶 三层分别绘制;逐格按 RarityFrameIndex 加权随机选瓦片变体;画家序排序
碰撞系统 每格 5×5 个 sub-tile 标志位(一层内所有层做 OR 合并,含 type 13 影子层),角色按 sub-tile 判定走位,支持沿梯度脱困
真实关卡 已烘焙 365 张地图,覆盖 5 个 act:35 个预置关卡(罗格营地、修道院、大教堂、地下墓穴、鲁高因、库拉斯特码头、哈洛加斯…)+ 70 个随机迷宫 + 31 个野外关卡(生成逻辑移植自 D2MOO,按官方参数表复现)
七大职业与角色合成 完整支持亚马逊(Amazon)、刺客(Assassin)、野蛮人(Barbarian)、德鲁伊(Druid)、死灵法师(Necromancer)、圣骑士(Paladin)、女巫(Sorceress)七大职业的 DCC + COF 16 层组件装配与 8 方向动画,支持游戏中实时切换职业与初始专属装备
全技能系统(221 技能) 210 个各职业技能(每职业 3 系 × 10 技能)与 11 个通用玩家技能(普攻/踢击/投掷/反召唤/辨识/回城等),严格复现 1.13c 公式、协同加成(Synergies)、投射物引擎、光环扫描与延迟机制
完整 UI / HUD 交互 800×600 原版底栏控制台(红蓝血球与中毒覆盖、技能快捷槽、腰带)、左/右宽屏 400px 停靠面板(背包、纸娃娃、属性面板、技能树、储物箱、方块、任务日志、传送点菜单)、动态鼠标指针、Alt 物品高亮等
资源包(离线烘焙) 索引色 PNG 图集页(≤2048²,PLTE + tRNS 取自该 act 的 pal.pl2)+ scene.json(绘制列表、碰撞 RLE、出生点、对象元数据)+ manifest.json
按需读归档 也可不烘焙,直接用 HTTP Range 只拉需要的 MPQ 字节当场解码(?live=1,慢,作为回退路径)
三级关卡选择器 章节 → 场景 → 细分场景(如 第一章 / 罗格营地 / 北);中文场景名见 src/game/level-names-zh.ts

开发进展:当前底层引擎、七大职业表现、221 技能完整实现与全套 UI 面板已全面打通。下一步将深入完善野外怪物密度与 AI 行为、装备词缀掉落平衡与 .d2s 官方存档双向互通,详见 ROADMAP.md。

代码结构

src/mpq/       MPQ v1 容器:hash/block 表、Storm 加密、分扇区编解码、PKWARE implode/explode、Range 读取
src/formats/   dc6 / ds1 / dt1 / pal / pl2 / cel / pcx / tbl / sprite / dcc / cof / bitstream
src/game/      等距场景与碰撞、关卡表解析、DCC+COF 角色合成、对象与物品解析、确定性 RNG
  engine/      1.13c 真实战斗引擎、AST 公式求值器、状态机、投射物调度、光环与召唤物管理
  skills/      221 个技能的具体实现模块(uni / ama / sor / nec / pal / bar / dru / ass)
src/ui/        完整 UI / HUD 模块:背包、属性面板、技能树、控制底栏、传送点、储物箱、任务日志、字体、鼠标指针
src/render/    WebGL2 渲染器(多图集;纹理切换时 flush 以保画家序)
src/scene/     页面级装配(资源包优先,失败回退到直读归档)
src/data/      技能目录、Gitea 跟踪 Issue 数据库、掉落表与任务官方文本数据
scripts/       资源包烘焙、格式/数据/部署校验、无头浏览器检查、夹具生成
*.html         主入口页面:acts.html(游戏全功能主页面)、arena.html(数值与技能验证竞技场)

美术资源与图集资产(Assets)

项目在离线烘焙和客户端运行时划分了清晰的美术资产目录结构,所有视觉素材均可从 1.13c 原版 MPQ 自动导出与打包:

1. UI 界面图集与面板切片 (public/ui/)

  • 综合图集 (Atlases):
    • items-atlas.png:装备与物品大图集,覆盖所有武器、防具、饰品(戒指、护身符、珠宝)、符文、药水等,完整支持大/中/小护身符与首饰的原版 VarInvGfx 多视觉外观变体。
    • quests-atlas.png:1–5 幕全部任务状态图标图集(未触发、进行中、已完成)。
    • skill-tree-tabs.png:七大职业技能树的 3 系专属垂直选项卡图集(激活/未激活切片)。
  • 经典功能面板背景与控件:
    • ctrlpnl-800.png:800×600 原版底栏控制台面板(包含技能槽底框、经验槽、腰带槽)。
    • inv-sheet.png / inv-tab-0.png / inv-tab-1.png:装备纸娃娃界面与 10×4 背包网格、主副手武器切换 Tab。
    • char-sheet.png:角色属性与抗性详情面板。
    • stash-bg.png:营地私人储物箱面板(6×8 格子)。
    • cube-bg.png:赫拉迪克方块(3×4 合成面板)。
    • vendor-bg.png / buysellbtn.png: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/ui/)

  • 全职业技能树背景切片 (public/skills/bg_<cls>_<tab>.png):
    • 共 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)专用图标。

3. 角色与怪物实体动画包 (samples/d2-packs/entities/)

  • 七大职业模型:
    • 亚马逊(char-am)、刺客(char-ai)、野蛮人(char-ba)、德鲁伊(char-dz)、死灵法师(char-ne)、圣骑士(char-pa)、女巫(char-so)。
    • 由 16 个装备图层复合装配,解包出行走、跑动、各种武器攻击、施法、受击、死亡等 8 方向完整序列。
    • 伴随同名 .r8 紧凑二进制像素包,用于在 WebGL/Canvas 中零拷贝极速解码渲染。
  • 怪物实体模型:
    • 包含沉沦魔(Fallen)、骷髅(Skeleton)、僵尸(Zombie)、血鸟(Blood Raven)、督瑞尔(Duriel)、安达利尔(Andariel)、墨菲斯托(Mephisto)、暗黑破坏神(Diablo)、巴尔(Baal)等数十种怪物的完整动画包与 .r8 调色板像素数据。

4. 场景瓦片图集 (samples/d2-packs/act[1-5]/)

  • 365 个地图场景分块切片图集,每个图集包含 ≤2048² 尺寸的索引色 PNG 瓦片页(地板层、墙体层、屋顶层),附带 PLTE 调色板与透明度表。

结构化数据与 JSON 规范(Data & JSON)

引擎采用结构化 JSON 数据来驱动界面排版、图集映射、场景还原与游戏逻辑:

1. public/ui/manifest.json(UI 资源与图集总清单)

由 scripts/pack-ui.ts 自动烘焙生成,为 UI 系统提供像素级定位映射:

  • atlasWidth / atlasHeight:items-atlas.png 装备图集的分辨率规格。
  • questsAtlasWidth / questsAtlasHeight:quests-atlas.png 任务图集的分辨率规格。
  • codeToInvFile:物品 3 字母代码(如 rin、amu、cm1、hpot)到原版 MPQ 图像文件名的映射表。
  • itemRects:所有物品及装备的 UV 矩形坐标表({ x, y, w, h }),针对戒指、项链、珠宝和护身符支持 VarInvGfx 多图集变体定位。
  • questRects:1–5 幕任务日志在图集中的坐标切片。
  • images:各种独立 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)、内部场景标识、关卡类型(预置场景 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 大角色职业与数十种怪物的骨骼装配结构。
  • 包含复合图层映射、8 方向动作切片元数据、每帧中心偏移(Pivot),搭配同名 .r8 文件在渲染管线中执行高效逐像素着色。

8. samples/d2-packs/act<N>/<level>/scene.json & manifest.json(单场景规格)

  • manifest.json:当前场景所需的瓦片图集页清单与调色板信息。
  • scene.json:记录等距地图的地板(Floor)、墙体(Wall)、屋顶(Roof)多层瓦片绘制列表与深度排序,采用 RLE 压缩的 5×5 子格碰撞阻挡网格(Collision Grid),以及预置对象(储物箱、石碑、传送门、出生点)。

9. src/data/gitea-skill-issues.json(技能跟踪数据库)

  • 建立 221 个技能与开发追踪系统的双向索引映射,包含 Skill ID、英文名称、职业缩写、Slug 标识与对应的 Issue/Milestone 编号。

部署与使用

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。

2. 资源包从哪来(不在 Git 里)

图集包(62 个地图块 / 35 关,索引色 PNG + scene.json)不在本仓库里——它是 ~66 MB 的索引色 PNG,每次重烘几乎全部文件都变,而 PNG 无法被 git 的 delta 压缩,随仓库分发会让每烘焙一次仓库再长 ~60 MB。它放在图库仓库,那里刻意只保留一个提交(每次重烘 orphan 提交 + force push), 体积恒定在「一份快照」:

git clone https://git.projectdiablo2.cn/troytt/diablo2-web-assets.git samples/d2-packs

只想要一份压缩包(不需要 git):

curl -O https://www.laiseek.xyz/diablo2/assets/d2-packs-2026-09-14.tar.xz
sha256sum d2-packs-2026-09-14.tar.xz   # 应为 9cdfd0c19ac68de842c6725070b65d056e25f5bcc77f36d6d9a29cd9f1b431e8
tar xJf d2-packs-2026-09-14.tar.xz     # 解出 samples/d2-packs/

仓库里只保留 .gitignore 规则与本文档;要自己生成包就照第 3 步 npm run pack:data 从原版 MPQ 烘焙,再用 npm run publish:packs 发布到图库仓库(脚本会重建单提交历史)。

3. 本地跑起来

npm install                                          # 仅 vite / typescript / @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 场景图集 → samples/d2-packs
npm run pack:ui                                      # 烘焙 UI 综合图集与 manifest.json
npm run pack:animdata                                # 烘焙 AnimData.d2 与 monstats2.json
npm run pack:entities                                # 烘焙 7 大职业模型与怪物实体动画包
npm run dev                                          # 启动 Vite:http://127.0.0.1:5173/acts.html

pack:data 需要原版 MPQ(约 2 分钟);只用上面下载来的 samples/d2-packs/ 可以跳过它, 代价是 ?live=1 与重新烘焙不可用。

4. 页面与操作

页面 用途
/acts.html(或访问根路径 /) 主游戏页面:全屏 WebGL2 画布 + HUD 控制条 + 左右停靠全套功能面板 + 7 职业漫步战斗
/arena.html 战斗数值与技能测试竞技场:攻防数值数学模型、技能加成、伤害计算器(1.13c 原版公式验证)

页面查询参数

?act=1..5                章节
?level=<地图块 label>     直接指定细分场景,如 33-act-1-cathedral-cathy3
?quadrant=<DS1 名>       直读归档模式下指定该关卡的某个 DS1
?live=1                  不走资源包,直接按 HTTP Range 读 MPQ 解码(慢)
?pack=<目录>             换一个资源包目录      ?base=<目录>   换一个归档目录
?arena=1&class=<cls>&skill=<id>&slvl=<lvl>&autocast=1   启动竞技场自动验证模式

完整操作快捷键

  • 移动与视口:
    • WASD / 方向键:移动角色(按等距屏幕方向)
    • 鼠标滚轮 或 + / -:视口无级缩放;0:缩放复位
  • 功能面板(宽屏左右停靠):
    • I / B:开启 / 关闭背包与装备纸娃娃面板(右停靠)
    • A / C:开启 / 关闭角色属性面板(左停靠)
    • T:开启 / 关闭技能树面板(右停靠,3 系垂直选项卡切换与加点)
    • Q:开启 / 关闭任务日志面板(左停靠,按幕查看真实任务状态)
    • V:开启 / 关闭传送点网络菜单(左停靠,各幕传送点导航)
    • Esc:关闭当前开启的所有停靠面板与弹出层
  • 战斗与技能快捷栏:
    • 鼠标左键 / 右键:施放当前选中的左 / 右手技能
    • S 或点击底栏技能图标:打开 Speedbar 技能选择菜单
    • 鼠标悬浮在 Speedbar 技能上按 F1 ~ F8:绑定快捷键;在游戏过程中按 F1 ~ F8:即时切换技能
    • 1 ~ 4:快捷使用腰带对应列药水;~:展开 / 折叠腰带
    • Alt(按住):高亮显示地面掉落物品标签
    • R:切换跑步 / 走路模式
    • W:主副手武器切换(I / II 套)
  • 测试与调试功能:
    • 键盘数字 1 ~ 7:一键热切换 7 大职业(亚马逊、刺客、野蛮人、德鲁伊、死灵法师、圣骑士、女巫)并自动装配初始专属套装与储物箱
    • K / L:快速保存 / 读取角色快照存档

5. 部署到服务器

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):

location = /diablo2  { return 301 /diablo2/; }
location = /diablo2/ { rewrite ^ /diablo2/acts.html last; }
location /diablo2/   { alias /var/www/d2web/; autoindex off; add_header Cache-Control 'no-store'; }

location /diablo2/packs/ {                       # 资源包:可缓存
    alias /var/www/d2packs/;
    autoindex off;
    add_header Cache-Control 'public, max-age=3600';
}

location ~ ^/diablo2/data/(?<d2file>[A-Za-z0-9_.-]+\.mpq)$ {   # 只暴露 .mpq,不列目录
    alias /var/www/d2data/$d2file;
    autoindex off;
    add_header Accept-Ranges bytes;
    add_header Cache-Control 'public, max-age=3600';
}

要点:归档必须支持 Range(否则页面会退化成整文件下载);/root 是 0700,所以用硬链接暴露给 nginx。 部署后跑 npm run verify:deploy 自检。

6. 自检命令

npm run verify:deploy         # 线上:页面 / 资源包索引 / 图集 / Range 206 / 旧入口 410
npm run verify:packs          # 资源包与"现读现解"逐项比对(绘制序、碰撞栅格逐字节、每帧像素哈希)
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 typecheck             # tsc --noEmit
npm test                      # 运行 Vitest 完整测试套件

数据与许可

  • 仓库不含暴雪美术:原版 MPQ、reference/ 下的第三方参考源码都不入库(规则写在 .gitignore 与 THIRD_PARTY_NOTICES.md);samples/fixtures/(本项目自产)与 samples/d2-packs/(派生数据)只作为 /diablo2/assets/ 下的归档发布,不进 Git 历史。 图集包每次重烘都会让 Git 仓库再长 ~60 MB(PNG 无法 delta 压缩),所以不再入库。
  • 使用本引擎需要你自己合法拥有的游戏数据。将来落地的生成类关卡(迷宫 / 野外)会在页面与文档中标注为 "按官方参数表复现,非引擎原版布局"(生成逻辑移植自 D2MOO)。