DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
This commit is contained in:
commit
645b64fe21
4388 files changed
+1405457
No files matched your search
@@ -0,0 +1,129 @@
|
||||
# PVF 解析套件开发文档
|
||||
|
||||
> 覆盖 PVF 解析库(pvfine)、物品名称表导出工具(pvfexport)、以及与 GM 工具的离线名称显示集成。
|
||||
>
|
||||
> 最后更新:2026-11-03
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
DNF 的 `Script.pvf` 是专有的二进制容器(加密 + 压缩),物品名称(`.equ`/`.stk` 的 `[name]` 段)只存在于 PVF 内。为了让 GM 工具**离线(服务端关闭)也能显示物品中文名**,我们引入了一个 PVF 解析方案。
|
||||
|
||||
---
|
||||
|
||||
## 二、pvfine 项目(`pvf/`)
|
||||
|
||||
`pvf/` 是开源项目 **pvfine**(GPL-3.0)的核心源码,一个 Go 编写的 PVF 编辑器/解析套件,支持 86/90/100/110/115/TW 全版本 `Script.pvf`。
|
||||
|
||||
### 结构
|
||||
|
||||
```
|
||||
pvf/
|
||||
├── internal/pvf/ 核心解析包(Open / Find / Text / ScriptMetadata / ParseListText)
|
||||
├── internal/ani/ buildmode/ rendering/ ... pvf 依赖的其他内部包
|
||||
├── internal/mcpserver/ npk/ mod/ script/ ... 编辑器相关
|
||||
├── config/ go:embed 的索引数据(paths.json 等,编译必需)
|
||||
├── cmd/
|
||||
│ ├── annotation-editor/ 注解编辑器
|
||||
│ └── pvfexport/ 物品名称表导出工具(本仓库新增)
|
||||
├── services/ frontend/ 编辑器后端/前端
|
||||
├── main.go 桌面 GUI 入口(Wails)
|
||||
└── go.mod module pvfine, go 1.26.0
|
||||
```
|
||||
|
||||
### 核心 API(`internal/pvf`)
|
||||
|
||||
```go
|
||||
import "pvfine/internal/pvf"
|
||||
|
||||
archive, err := pvf.Open("Script.pvf") // 打开归档(自动识别版本)
|
||||
defer archive.Release()
|
||||
|
||||
idx, found := archive.Find("stackable/stackable.lst") // 找文件索引
|
||||
text, err := archive.Text(idx) // 读脚本文本
|
||||
pairs, err := pvf.ParseListText(text) // 解析 .lst -> [{ID, Path}]
|
||||
|
||||
meta, err := archive.ScriptMetadata(idx) // 读物品元数据(Name/Rarity)
|
||||
// meta.Name 即物品名称
|
||||
```
|
||||
|
||||
> 注意:`internal/pvf` 依赖 `internal/ani`、`internal/buildmode`、`internal/rendering`、
|
||||
> `internal/annotations`、`internal/ruleconfig`、`config` 等包,**不能单独抽出**,
|
||||
> 需要以整个 `pvfine` 模块作为依赖(或直接在其中添加 cmd 子命令)。
|
||||
|
||||
---
|
||||
|
||||
## 三、pvfexport 工具(`pvf/cmd/pvfexport/`)
|
||||
|
||||
从 `Script.pvf` 提取 `item_id → 名称` 全量映射,导出 JSON。
|
||||
|
||||
### 编译
|
||||
|
||||
```bash
|
||||
cd pvf
|
||||
go build -o pvfexport.exe ./cmd/pvfexport/
|
||||
```
|
||||
|
||||
### 用法
|
||||
|
||||
```bash
|
||||
pvfexport -pvf Script.pvf -out items.json # 完整 JSON(含 path/rarity/kind)
|
||||
pvfexport -pvf Script.pvf -out dnf_items.json -compact # 紧凑 {item_id: name}(推荐)
|
||||
```
|
||||
|
||||
- `-compact`:只输出 `{item_id: name}` 映射(仅保留有名称的项),体积约 5.7MB(14.6 万条)。
|
||||
- 完整模式:输出 `{pvf_path, total, items:[{id,name,rarity,path,kind}]}`,约 35MB。
|
||||
|
||||
### 实现逻辑
|
||||
|
||||
1. `pvf.Open` 打开归档。
|
||||
2. 读 `stackable/stackable.lst`(堆叠道具)和 `equipment/equipment.lst`(装备),用 `ParseListText` 解析出 `item_id → 路径`。
|
||||
3. 对每个 item,用 `resolveItemFile` 找文件(路径候选策略复刻服务端 `readDungeonDropText`):
|
||||
- 直接用 lst 里的路径
|
||||
- 尝试 `root/` 前缀(`stackable/` / `equipment/`)
|
||||
- 尝试 `(r)` 修订文件名(90 版本特有)
|
||||
4. `ScriptMetadata` 读 `[name]` 段得到名称。
|
||||
|
||||
---
|
||||
|
||||
## 四、与 GM 工具的集成(离线名称显示)
|
||||
|
||||
### 名称表存放
|
||||
|
||||
名称表 `dnf_items.json` 与 `pvfexport.exe` 放在服务端根目录下的 **`GM配置/`** 目录:
|
||||
|
||||
```
|
||||
90server/
|
||||
└── GM配置/
|
||||
├── pvfexport.exe
|
||||
└── dnf_items.json
|
||||
```
|
||||
|
||||
### 自动重导出
|
||||
|
||||
GM 工具(launcher)启动时,`db.py` 的 `_load_item_names()` 会:
|
||||
|
||||
1. 定位 `GM配置/dnf_items.json` 和 `Client/Script.pvf`。
|
||||
2. 对比两者修改时间:
|
||||
- 名称表**已是最新** → 秒加载(约 0.09 秒)。
|
||||
- **PVF 被更新**(或名称表缺失)→ 自动调 `pvfexport.exe -compact` 重导出(约 5 秒),再加载。
|
||||
3. 加 `_EXPORT_LOCK` 锁防并发重复触发。
|
||||
|
||||
> 因此:**PVF 新增物品后,只需替换 `Client/Script.pvf`,GM 工具下次启动自动重导名称表,
|
||||
> 无需重新打包 GM 工具。**
|
||||
|
||||
### 注入方式
|
||||
|
||||
`server.py` 启动时调用 `db.set_gm_config(GM_CONFIG_DIR, PVF_PATH)` 注入目录与 PVF 路径;
|
||||
`db.py` 的 `item_name(item_id)` 据此惰性加载名称表。
|
||||
|
||||
---
|
||||
|
||||
## 五、许可证与合规
|
||||
|
||||
- `pvf/` 遵循 **GPL-3.0**(见 `pvf/LICENSE`)。
|
||||
- 若将 pvfine 与闭源的 server/launcher 合并发布,需注意 **GPL 传染性**:
|
||||
- 单独分发 pvfexport(独立 Go 进程)可隔离传染;
|
||||
- 若将 `internal/pvf` 直接 link 进闭源服务端,会触发 GPL 义务。
|
||||
- 建议:保持 pvfine 作为**独立子模块/子仓库**,通过 CLI 工具(pvfexport)与主项目解耦。
|
||||
Reference in new issue
Block a user