服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
5.7 KiB
DNF90 服务端开发文档
覆盖服务端(Go)的架构、GM 接口契约、编译部署、以及本次新增的拍卖行 / 背包管理改动。
最后更新:2026-11-03
一、架构概览
服务端是 Go 单模块(module longheng.io/server),采用分层结构:
server/
├── cmd/
│ ├── server/dnf90/ 产品入口(主服务进程,产出 DNF90Server.exe)
│ ├── server/control/ 部署控制器(DNF90Control.exe,start/stop/configure)
│ ├── server/doctor/ 部署预检(DNF90Doctor.exe)
│ ├── companionpvf/ PVF 伴随进程
│ └── devtools/ scratch/ 开发调试工具(非产品)
├── internal/
│ ├── app/dnf90/ 单一组合根(路由注册、依赖装配)
│ ├── services/dnfbridge/ 客户端传输 + GM bridge 层(本次改动重点)
│ ├── modules/dnf/ DNF 领域模块(auction、dungeon、character 等)
│ ├── platform/ 框架层(含 platform/pvf PVF 解析)
│ ├── services/logic/dnf/ MySQL 仓储装配
│ └── ...
└── pkg/ 对外包
关键入口:
- 主服务:
cmd/server/dnf90/main.go - GM 路由:
internal/app/dnf90/gm_tool_compat.go(兼容层,/local/dnf-gm/*) - GM bridge:
internal/services/dnfbridge/gm_*.go
二、编译与部署
环境要求
- Go ≥ 1.26(
go.mod声明go 1.26.5) - 依赖走国内镜像(加速):
GOPROXY=https://goproxy.cn,direct、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
编译产物部署到 90server/Server/runtime/bin/。
若
go build报 "package unsafe is not in std",说明本地 Go SDK 的 src 不完整, 需改用完整 toolchain(见docs/开发文档.md的「Go 环境问题」章节)。
三、GM 接口契约(/local/dnf-gm/*)
GM 接口由 internal/app/dnf90/gm_tool_compat.go 注册,bridge 层实现在 internal/services/dnfbridge/。
认证
所有接口走 admin HTTP 端口(默认 127.0.0.1:18111),请求头带 X-Admin-Token(token 来自 instance.json 的 adminToken)。
返回结构
统一约定:{"ok": true, "data": <结果>};错误时 {"error": "<msg>"}。
拍卖行接口(本次新增)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /local/dnf-gm/auction/listings |
列出所有挂单,返回 {listings, escrow_gold} |
| POST | /local/dnf-gm/auction/list |
上架(支持自动补足) |
| POST | /local/dnf-gm/auction/cancel |
下架 |
上架请求体(GMAuctionListRequest):
{
"seller_id": "角色ID",
"item_id": 10001,
"count": 1,
"unit_price": 10000,
"start_price": -1, // 每件起拍价,-1=不设竞拍
"buyout_price": -1, // 每件一口价,-1=不设一口价
"duration_hours": 24, // 24 或 48
"grant_if_missing": true // 背包不足时自动凭空发放差额再上架
}
背包管理接口(本次新增)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /local/dnf-gm/inventory/list?character_id=xxx |
列角色背包 + 穿戴装备,每行 {collection, entry_key, item_id, count, bind, item_name} |
| POST | /local/dnf-gm/item/delete |
删除指定背包行(entry_key + collection,支持 slots/wear) |
四、本次关键改动说明
1. GM 拍卖行(线上上架通道)
- 新增
internal/services/dnfbridge/gm_auction.go:GMAuctionListings/GMAuctionList/GMAuctionCancel三个方法。- 直接调用
dnfauction.Owner的纯数据层Register/Cancel/LoadListing,不依赖玩家 session。
- 新增
GMInventoryList方法(列背包全部道具 + 穿戴装备)。
2. 上架免押金
gm_auction.go 的 GMAuctionList 中,Register 的 Deposit 设为 0(原为 dnfauction.ListingDepositGold = 10000)。
服务端 owner.go 里是 if cmd.Deposit > 0 才扣款,因此 Deposit=0 直接跳过押金逻辑。
3. 自动补足上架(发放式)
GMAuctionList 支持 grant_if_missing:卖家背包物品不足时,先调 GMGrantItem(dnfdungeon.Owner.GrantPickupItem)凭空发放差额到背包,再 Register 上架。实现「像发放道具那样直接上架」。
4. 路由层
gm_tool_compat.go 新增常量与路由:
gmAuctionListingsPath/gmAuctionListPath/gmAuctionCancelPathgmInventoryListPath
五、GM bridge 层约定
- GM 方法都在
internal/services/dnfbridge/包,方法签名形如func (s *Service) GMXxx(ctx, req) (resp, error)。 - 数据访问用
s.repositoryGroup()(返回dnfrepo.Group,含Inventory、Equipment、Character等仓储)。 - 物品名解析用
s.currentPVFItemCatalog()(dnfpvf目录),ResolveItem(itemID)得到definition.Name。
六、常见坑
go 1.26.5版本声明:装 ≥1.26 即可,GOTOOLCHAIN=auto会自动下载所需 toolchain。- GM 接口路由:
gm_tool_compat.go里gmToolPost包装 POST 接口,GET 接口用HandleFunc+writeGMJSON。 - 服务端
Register的校验:buyout_price必须等于unit_price(或"不设一口价"),start_price在[0, unit_price]或"不设竞拍",时长只能是 24/48。 - 对外发布:不要附带本机测试用的深渊掉落修改;远程换装工具不要公开 Admin 端口。