Files
90CNServer/README.md
T

199 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DNF90 灵宝小竹单机版 · 源码仓库
《地下城与勇士》90 级版本的**本地单机模拟器**(非私服、不联网、不开服)完整源码 monorepo:服务端、客户端补丁、整合启动器、游戏内 GM 控制台,以及 PVF 解析套件。
- 当前版本:**v2026.11.05**
- 维护:汉服电脑宅团队(灵宝仙尊 联合 淡竹茹 开发)
- 官方 QQ 群:**1128511524**
- 仓库只存源码,不含 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. 从官方渠道下载发布包(网盘),解压到**非中文、无空格**路径,例如 `D:\DNF90`
2. 双击 `DNF90启动器.exe`
3. 点「开始」拉起服务端,等日志出现「服务已就绪」再进游戏(首次约 85 秒)
4. 进游戏后点小井盖即可打开 GM 控制台
### 4.2 从源码编译
**服务端**(Go ≥ 1.26.5,建议国内镜像):
```bash
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 位):
```bash
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 物品名导出**:
```bash
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` 里的占位地址换成真实分享链接,作为附件上传——十几个 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`)、自动补足上架(背包不足时先发差额)、列背包 / 删除背包行(含穿戴装备)。
## 十、常见坑
| 现象 | 原因 | 处理 |
|------|------|------|
| 启动器还是旧版本号 / 旧品牌 | 旧进程没退,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/README.md) | 文档总索引与上手路径 |
| [docs/开发文档.md](docs/开发文档.md) | 启动器 / GM 工具:环境、架构、API 契约、打包部署、常见问题 |
| [docs/服务端开发文档.md](docs/服务端开发文档.md) | 服务端架构、GM 接口契约、拍卖行与背包改动 |
| [docs/PVF解析开发文档.md](docs/PVF解析开发文档.md) | pvfine 与 pvfexport、离线名称集成 |
| `server/README.md`、`pvf/README.md`、`launcher/README.md`、`gmtool/README.md` | 各子项目说明 |
| [docs/release/](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` 与桌面发布包),否则跑的还是旧文件