diablo2-web/scripts/browser
troytt 897b3735d6 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖)
内容概览
- 归档层:MPQ v1 容器(hash/block 表、Storm 加密、分扇区编解码),含 PKWARE
  implode/explode 移植;支持 HTTP Range 只读取所需字节。
- 格式层:dc6 / ds1 / dt1 / pal / pl2 / cel / pcx / tbl / sprite,以及 dcc / cof / bitstream。
- 地图层:等距投影场景构建(地板/墙/屋顶分层、逐格瓦片变体加权随机、sub-tile 碰撞),
  资源包(索引色 PNG 图集 + scene.json)离线烘焙与逐像素差分校验。
- 角色层:DCC + COF 合成(8 方向),法师行走/站立替换占位棋子。
- 页面:acts.html 全屏画布 + 三级选择器(章节 / 场景 / 细分场景),资源包优先、
  可回退到直读归档(?live=1)。
- 验证脚本:verify:all / implode / acts / d2 / packs / dcc / deploy / listfile /
  object-lookup / alignment / tiles / generators 等,均带断言与退出码。

数据与许可
- 游戏数据(samples/)与第三方参考源码(reference/)不入库:体积大且无再分发许可,
  见 THIRD_PARTY_NOTICES.md。
- 生成关卡(70 迷宫 + 31 野外)尚未烘焙,现状与修复清单见 HANDOVER.md §4f。
2026-09-13 18:10:28 +08:00
..
checks 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖) 2026-09-13 18:10:28 +08:00
README.md 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖) 2026-09-13 18:10:28 +08:00
inspect-page.mjs 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖) 2026-09-13 18:10:28 +08:00
many-pages.mjs 初始提交:从零实现的暗黑破坏神 II WebGL2 引擎(TypeScript + Vite,零运行时依赖) 2026-09-13 18:10:28 +08:00

README.md

浏览器验证工具(零依赖)

这些脚本用 Node 内置的 WebSocket 直接讲 CDP(Chrome DevTools Protocol), 不需要 puppeteer/playwright 这类依赖。目的只有一个:给"页面里到底发生了什么"留下证据, 因为像素和截图的判断在这套环境里不可靠(模型读不了图,readPixels 在合成后会返回清空缓冲)。

inspect-page.mjs —— 单页检查

CHROME=/root/.cache/ms-playwright/chromium-1223/chrome-linux64/chrome
node scripts/browser/inspect-page.mjs "$CHROME" \
  "http://127.0.0.1:5173/map.html?data=samples/fixtures" \
  scripts/browser/checks/map-save-load.js --screenshot /tmp/map.png

它会启动一个 headless Chromium(SwiftShader 软件 WebGL2),打开 URL,等待页面加载, 把 check 脚本的返回值打印成 JSON,可选截图。

many-pages.mjs —— N 页同时跑(联机用)

node scripts/browser/many-pages.mjs "$CHROME" \
  "http://127.0.0.1:5173/net.html?data=samples/fixtures&ws=ws://127.0.0.1:8787&peers=3&peer=0" \
  "http://127.0.0.1:5173/net.html?data=samples/fixtures&ws=ws://127.0.0.1:8787&peers=3&peer=1" \
  "http://127.0.0.1:5173/net.html?data=samples/fixtures&ws=ws://127.0.0.1:8787&peers=3&peer=2" \
  --seconds 20 --shot /tmp/coop

每一页是一个独立的 Chromium 实例(标签页级复用在这套 CDP 流程里会把两次导航混在一起, 曾经导致"两页都跑成了 peer 0"这种假象)。它按页分发不同的方向键,让每个角色只受本页按键驱动, 结束时打印每页的 window.__d2web* 状态。判定靠状态字段,不靠看图。

checks/ —— 页面内脚本

文件 目标页面 做什么
map-save-load.js map.html 走位砍怪 → 存档 → 继续跑 → 读档,比较存档点与恢复后的位置/击杀/金币/地面/等级
walk-state.js walk.html 读真实 MPQ(暗黑1 spawn.mpq)后的就绪状态、tick、drawCalls、glError
net-state.js net.html 单机模式的状态:世界 tick、角色数、怪物数、tps
act-state.js acts.html(?live=1) 读归档路径:归档是否读入、DS1 象限、格数、瓦片引用缺失数、图集尺寸,以及按键后的位移与朝向
act-pack-state.js acts.html(默认) 资源包路径:是否走 pack、首帧装了几页(证明懒加载)、出画面毫秒数、按键位移与朝向