hanfuit da502b3524 docs:补上 90CN.dll 自校验 CRC 工具的文档说明
- 新增 docs/客户端补丁与CRC校验.md:SelfCrcSlot 结构、CRC32 算法与种子坑、
  槽位为什么只在 .data/.rdata 里找、info/verify/patch 用法与退出码、
  build_90cn.ps1 集成、与「服务端 DLL 指纹」的区别、六类故障排查
- 新增 client-patch/tools/README.md:脚本清单与常用命令速查
- docs/README.md:文档索引与上手路径补一条
- 根 README:关键设计说明补「客户端自校验(CRC32)」小节,文档索引补一行
- 90CN.cpp:清掉过期的重复注释(旧的 patch_selfcrc.py / .text 段说法),与实现对齐
2026-11-05 16:40:33 +08:00

DNF90 灵宝小竹单机版 · 源码仓库

《地下城与勇士》90 级版本的本地单机模拟器(非私服、不联网、不开服)完整源码 monorepo:服务端、客户端补丁、整合启动器、游戏内 GM 控制台,以及 PVF 解析套件。

  • 当前版本:v2026.11.05
  • 维护:汉服电脑宅团队(灵宝仙尊 联合 淡竹茹 开发)
  • 官方 QQ 群:1128511524
  • 成品下载:百度网盘(提取码 s33r,链接已内置)
  • 仓库只存源码,不含 exe/dll、美术与 PVF 资源;发布包另走网盘

本模拟器资源禁止倒卖,请到官方微信公众号或社群下载。


一、它由哪几块组成

进程 / 组件 位置 监听 职责
DNF90启动器.exe launcher/ 127.0.0.1:19527 拉起与停止服务端、内置 GM 工具、换装、游戏设置、更新日志、关于页
DNF90Server.exe server/ 127.0.0.1:18111(Admin) 游戏逻辑、账号角色、背包拍卖行任务副本、SQLite 落库
GM 控制台网页 gmweb/ 127.0.0.1:18112 游戏内嵌页面,/api/* 反代 18111 并注入 admin token
90CN.dll client-patch/ — 客户端补丁,接管游戏自带面板,弹 WebView2 窗口指向 18112

调用关系(从玩家视角):

  1. 玩家双击启动器 → 启动器拉起 DNF90Server.exe,并顺带起 gmweb/serve.py
  2. 登录进游戏 → 客户端加载 90CN.dll,连本地服务端 18111(DLL 指纹不匹配就断开)
  3. 点小井盖 → 补丁弹自己的窗口,打开 http://127.0.0.1:18112/ 的 GM 控制台
  4. 控制台里的所有操作,经 serve.py 反代到服务端 Admin 接口执行

二、目录结构

90CNServer/
├── server/           DNF90 服务端(Go,模块 longheng.io/server)
│   ├── cmd/server/{dnf90,control,doctor}   主程序 / 控制台 / 自检
│   ├── internal/ pkg/                      业务与基础库
│   └── build_verify/                       构建校验脚本(不参与发布)
├── client-patch/     客户端补丁(C++ / MSVC,含 90CN_web.ini)
├── launcher/         整合启动器 + 内置 GM 工具(Python 3.15 + pywebview)
│   └── qr/           关于页二维码(alipay / wechat / gzh / qq)
├── gmweb/            游戏内 GM 控制台网页(纯静态 + serve.py 反代)
│   └── qr/           控制台关于页二维码
├── loadout-tool/     一键换装工具(C# / .NET)
├── gmtool/           GM 工具旧版(FastAPI,已被 launcher 取代,仅留参考)
├── pvf/              PVF 解析套件(Go,模块 pvfine,GPL-3.0)
│   └── cmd/pvfexport/  物品名称表导出工具
├── docs/             开发文档 + 发布物料模板(release/)
└── README.md

三、子项目速览

目录 语言 / 技术栈 说明
server/ Go 1.26.5(longheng.io/server) 服务端主体;Admin/GM HTTP 接口、拍卖行、背包、任务、副本、点券
client-patch/ C++ / MSVC vcxproj 90CN.dll:面板接管、安图恩兼容、蛇腹剑修复、战斗面板布局等
launcher/ Python 3.15(32 位)+ pywebview 6 + PyInstaller 单 EXE 启动器,六页单窗口,内置完整 GM 工具与更新日志
gmweb/ 纯 HTML/CSS/JS + Python 标准库 游戏内 GM 控制台页面,serve.py 反代 18111 并注入 admin token
loadout-tool/ C# / .NET 独立换装工具,通过 Admin API 操作
gmtool/ Python + FastAPI GM 工具旧版,保留参考
pvf/ Go 1.26(pvfine,GPL-3.0) PVF 解析库 + pvfexport 物品名导出

四、快速开始

4.1 只想要能玩的成品

  1. 从百度网盘(提取码 s33r)或官方社群下载发布包,解压到非中文、无空格路径,例如 D:\DNF90
  2. 双击 DNF90启动器.exe
  3. 点「开始」拉起服务端,等日志出现「服务已就绪」再进游戏(首次约 85 秒)
  4. 进游戏后点小井盖即可打开 GM 控制台

4.2 从源码编译

服务端(Go ≥ 1.26.5,建议国内镜像):

go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.google.cn

cd server
go build -buildvcs=false -trimpath -o DNF90Server.exe  ./cmd/server/dnf90
go build -buildvcs=false -trimpath -o DNF90Control.exe ./cmd/server/control
go build -buildvcs=false -trimpath -o DNF90Doctor.exe  ./cmd/server/doctor

启动器(Python 3.15 32 位):

cd launcher
python -m pip install pywebview pythonnet clr-loader pyinstaller
python -m PyInstaller --clean --noconfirm "DNF90启动器.spec"
# 产物:launcher/dist/DNF90启动器.exe

单文件打包有代价:onefile 会先解包再启动,改完源码必须重新打包;旧进程未退出时会继续占用 19527 端口,看到旧界面先确认进程已杀干净。

PVF 物品名导出:

cd pvf
go build ./cmd/pvfexport/
pvfexport -pvf Script.pvf -out dnf_items.json -compact

客户端补丁 / 换装工具:详见 docs/开发文档.md 与 client-patch/、loadout-tool/ 各自的工程文件。

五、启动器要点

  • 单窗口六页:开始 / GM工具 / 一键换装 / 游戏设置 / 游戏更新 / 关于我们,导航栏左侧切换、右侧状态灯
  • 本地端口 19527,被占用时自动 +1 顺延(最多 20 次);页面为本地静态资源,响应统一 Cache-Control: no-store,避免 WebView2 缓存旧页面
  • 更新日志双来源:优先读仓库 Lingbao/90CNServer 的 Release 接口,再用 EXE 同目录的 更新日志.txt 补齐仓库还没发布的版本,按日期去重(仓库优先);断网时只用本地记录并在页面顶部给出黄色提示
  • 当前更新 / 历史更新 分成两个标签页,历史页显示条数
  • 关于我们:四行介绍文案 + 三列二维码(赞助我们:支付宝/微信 · 官方QQ群 · 团队公众号),点任意二维码可放大

六、游戏内 GM 控制台(gmweb/)

  • 由 serve.py 托管在 127.0.0.1:18112,/api/* 反代到服务端 127.0.0.1:18111 并注入 admin token(token 不进页面 JS)
  • 窗口尺寸由 client-patch/90CN_web.ini 决定:width=800 height=720
  • 页面为 IE11 兼容写法:不用 flex,统一 float + box-sizing:border-box;关于页垂直居中用 position:absolute; top:50% + -ms-transform
  • 关于页结构:介绍卡片(712 宽)+ 组合面板三列 赞助我们 353 | 官方QQ群 178 | 团队公众号 179,列间一条竖线
  • 静态资源带 ?v=YYYYMMDDx 版本后缀,改 CSS/JS 后必须加一版,否则 IE11 缓存不刷新

七、二维码与品牌素材替换

位置 用途 说明
launcher/qr/ 启动器「关于我们」 alipay.png / wechat.png / gzh.jpg / qq.png,同名覆盖即替换
gmweb/qr/ 游戏内控制台「关于」 同上四张
launcher/sponsor.png / sponsor_qr.png 旧版赞助页素材 历史遗留,可忽略
  • 图片缺失不会破图:启动器与 GM 页都会显示「二维码未配置 + 期望路径」占位
  • 启动器打包时 qr/ 四张图会进 EXE;同时支持在 EXE 同目录放 qr\ 覆盖(优先级高于内置)
  • launcher/server.py 的 /qr/<name> 是白名单路由,只认这四个文件名,防目录穿越

八、版本号与发布流程

  1. 改版本号:launcher/server.py 的 CURRENT_VERSION(当前 v2026.11.05),游戏内与启动器首页都读它
  2. 写更新日志:在发布包根目录的 更新日志.txt 追加一条(日期 + 条目),启动器会自动合并进「游戏更新」
  3. 构建:服务端三个 exe + 启动器单文件 exe
  4. 打发布包:服务端 runtime、gmweb、启动器、90CN_web.ini 一起收齐;DLL 与 EXE 必须配套(见下)
  5. 发 Release:在本仓库的 Release 里写发布说明(模板见 docs/release/发布说明模板.md)
  6. 网盘地址:docs/release/网盘下载.url 已指向百度网盘真实分享(提取码 s33r),作为 Release 附件上传——十几个 G 的包不适合直传,.url 是最省事的缓兵之计;重新分享后记得同步改模板表格
  7. 验证:启动器首页版本号、更新日志条数、关于页二维码、GM 页三列是否都正常

⚠️ DLL 指纹绑定:90CN.dll 的 SHA-256 在编译期编进 DNF90Server.exe(boundDllSHA256)。换 DLL 必须重编服务端,否则客户端连接会被拒绝。发布包里 DLL 与 EXE 一定要成对。

九、关键设计说明

GM 工具双数据源

  • Native API(服务端在线):127.0.0.1:18111 + X-Admin-Token,实时操作、事务一致
  • SQLite 直读(服务端离线):直接读写 Server/runtime/data/dnf90.db,可预览与批量改
  • 启动器通过探测 18111 是否监听来切换,界面上以状态灯区分

物品名称离线显示

pvf/cmd/pvfexport 从 Script.pvf 提取 item_id → 名称 全量映射导出 dnf_items.json,放在 GM配置/;启动时对比 PVF 与名称表修改时间,PVF 更新则自动重新导出,离线也能显示中文物品名。

GM 拍卖行

服务端实现 /local/dnf-gm/auction/*:免押金上架(Deposit=0)、自动补足上架(背包不足时先发差额)、列背包 / 删除背包行(含穿戴装备)。

客户端自校验(CRC32)

90CN.dll 里有一个 SelfCrcSlot 结构(magic=0xC0DEC0DE + offset + expected),构建后由 client-patch/tools/patch_dll_crc.py 把「整个文件的 CRC32」与槽位偏移写进去;运行时读盘重算并比对,不符就弹框退出——所以「patch 掉校验分支」这条路是堵死的。

  • 编译脚本 build_90cn.ps1 第三步会自动补 CRC,-SkipCrc 出来的 DLL 不要发布
  • 定位槽位只认 .data / .rdata,因为 0xC0DEC0DE 在 .text 里也有一份(MSVC 的比较立即数),扫错会写坏机器码,表现为读槽位后立刻崩
  • 改完 DLL 除了补 CRC,还要重编服务端:DNF90Server.exe 编译期绑定了 DLL 的 SHA-256(boundDllSHA256),指纹不配套会在登录阶段被踢

详见 docs/客户端补丁与CRC校验.md。

十、常见坑

现象 原因 处理
启动器还是旧版本号 / 旧品牌 旧进程没退,19527 被占,页面连到旧服务 任务管理器结束所有 DNF90启动器.exe 后重开
改了 CSS/JS 页面没变 WebView2 或 IE11 缓存 启动器已发 no-store;GM 页需改 ?v= 版本号
二维码显示空框 图片没放进 qr/ 或缺文件名 看占位提示里的期望路径,四个文件名固定
关于页底部被日志栏盖住 内容高度超过可视区 GM 页 #body 的 bottom 必须等于 #log 实高(含 padding/border)
客户端连不上服务端 DLL 与 EXE 指纹不匹配 用配套的一对重新打包,别混用
竖线不显示 CSS 特异性:.cols .box 把 border 清掉了 分隔线写在 .cols .box-r / .cols .box-m 上

十一、文档索引

文档 内容
docs/README.md 文档总索引与上手路径
docs/开发文档.md 启动器 / GM 工具:环境、架构、API 契约、打包部署、常见问题
docs/服务端开发文档.md 服务端架构、GM 接口契约、拍卖行与背包改动
docs/PVF解析开发文档.md pvfine 与 pvfexport、离线名称集成
docs/客户端补丁与CRC校验.md 90CN.dll 自校验 CRC、patch_dll_crc.py 用法、与 DLL 指纹的区别
server/README.md、pvf/README.md、launcher/README.md、gmtool/README.md 各子项目说明
docs/release/ 发布说明模板、网盘下载 .url 模板

十二、许可证与声明

  • server/、client-patch/、launcher/、gmweb/、loadout-tool/、gmtool/:私有 / 闭源,请勿公开分发或倒卖
  • pvf/:源自开源项目 pvfine,遵循 GPL-3.0(见 pvf/LICENSE),注意传染性
  • 本模拟器仅供本地单机体验,禁止用于开服运营;资源禁止倒卖,请到官方微信公众号或社群下载
  • 对外发布服务端时不要附带本机测试用的掉落改动;远程换装工具不要直接暴露 Admin 端口

十三、提交约定

  1. 各子项目独立编译,无跨目录构建依赖
  2. 不提交编译产物:launcher/dist/、launcher/build/、server/build_verify/、__pycache__、*.exe/*.dll、dnf_items.json、*.pvf 均已在 .gitignore
  3. 提交信息用「范围:做了什么」的形式,例如 启动器:游戏更新拆分为当前/历史双子页,新增关于我们页
  4. 服务端 GM 接口有变化时,同步更新 docs/服务端开发文档.md 的 API 契约章节
  5. 改完源码记得回灌运行目录(Z:\90server 与桌面发布包),否则跑的还是旧文件
S
Description
No description provided
Readme
23 MiB
0 Stars 2 Watchers 0 Forks
2026-11-05 15:40:43 +08:00
Languages
Go 89.3%
C++ 3.7%
Vue 3%
TypeScript 2.4%
Python 0.6%
Other 0.9%