● DNF 私服一站式工具箱

DPForge Next

DNF 私服插件管理 · 模块配置 · 一键生成部署 · GM 工具集。在浏览器里勾选功能、编辑参数、生成 df_game_r.js / Lua / config,并通过 SSH 一键部署到服务器。

100+可选功能插件
在线插件市场免更新
GM角色/账号/邮件/背包
1-ClickSSH 生成部署

核心能力

🧩

插件配置

按分类勾选功能、编辑参数、查看 Hook 地址;改动即入库,重新生成即写入 df_game_r.js。

🌙

Lua 脚本

Lua 道具处理与启动开关,配合 Work_Reload.lua 部署。

生成部署

一键生成 df_game_r.js / Lua / config,SSH 上传到服务器,目标目录自动创建。

🛡️

GM 管理

角色 / 账号 / 邮件 / 背包 / 道具搜索 / 在线玩家,直接读写游戏库。

🖥️

服务器管理

SSH 部署、PVF 上传校验、Web Shell、远程文件在线编辑。

⚙️

系统设置

改口令、初始化代码、frida 配置,兼容 MySQL 5.1–5.7 老库。

为什么要有在线插件市场?

🔄

免更新拿新插件

插件定义与注入代码托管在云端,DPForge 直接拉取最新版,不必重装程序。

🤝

社区共建

任何人都能在「提交插件」页在线投稿,站长审核通过后即刻对所有人可用。

📦

标准化格式

每个插件 = 一个 JSON(元信息 + Hook + 设置项 + 注入代码),可直接导入工具。

常用操作

👤 角色列表✉️ 邮件发放📦 道具搜索 🔑 账号管理🟢 在线玩家🎒 背包编辑

插件市场

从云端加载最新插件,点卡片查看设置项与注入代码,一键复制 JSON 导入 DPForge。想贡献自己的插件?看 开发文档 › 贡献流程

提交插件

在线填写并提交,进入待审核队列;站长审核通过后即刻上架,所有 DPForge 用户可拉取。无需 Git、无需私有部署。提交前请阅读 开发文档安全红线

📥 从 JSON 导入 把 AI 生成的插件 JSON 粘进来,或选择 .json 文件,自动填好下面的表单
提交即表示你确认代码可公开分享、无恶意逻辑。插件会被服务端执行,含后门/外联上传/破坏性写入的会被拒绝。

插件是什么

DPForge 的每个「插件」对应 DNF 服务端进程里的一段 Frida 注入逻辑。工具会把所有已启用插件的代码拼进 df_game_r.js,随服务端加载执行,从而实现登入播报、副本玩法、装备道具、运营管控等功能。

一个插件在云端就是一个 JSON 文件:元信息 + Hook 地址 + 设置项 schema + 注入代码。DPForge 拉取后即可在「插件配置」页勾选、改参数、生成部署。

插件 JSON 结构

把下面的对象保存成 plugins/<id>.json,并在 plugins/index.json 里登记一行即可:

{
  "schema": 1,
  "id": "extra_monster_reward",     // 唯一 id(英文/下划线)
  "cat": "dungeon",                 // 分类 id(见 index.json.categories)
  "name": "副本随机稀有怪",          // 显示名
  "ico": "👹",                       // emoji 图标
  "version": "1.0.0",               // 语义化版本
  "author": "your-name",            // 贡献者
  "initFn": "hook_extra_monster",   // 入口函数名(会被调用)
  "desc": "进房间按概率追加稀有怪并掉落道具。",
  "tags": ["副本玩法"],
  "hooks": [                        // 仅作展示/说明,实际 attach 在 code 内
    { "addr": "0x1234ABCD", "mode": "attach", "dup": false }
  ],
  "settings": [ /* 见「插件设置配置」 */ ],
  "code": "function hook_extra_monster(){ /* Frida 代码 */ }",
  "updatedAt": "2026-07-17"
}
字段说明:id 全局唯一;cat 必须是 index.json 里存在的分类;initFn 必须与 code 中的入口函数同名——DPForge 生成时会调用它。

注入处理逻辑

注入代码就是标准的 Frida JavaScript。约定:把所有逻辑包在一个与 initFn 同名的函数里,在函数内部用 Interceptor.attach 挂目标地址。

最小示例(强制某函数返回 1)

// initFn: HookDsSwordman_SkillSlot
function HookDsSwordman_SkillSlot() {
  Interceptor.attach(ptr(0x08608C98), {   // SkillSlot::checkMoveComboSkillSlot
    onEnter: function (args) { /* args[0]=this, args[1..]=参数 */ },
    onLeave: function (retval) { retval.replace(1) } // 改返回值
  });
}

读取参数 / 调用游戏内函数

function hook_user_inout_game_world() {
  Interceptor.attach(ptr(0x86C4E50), {          // GameWorld::reach_game_world
    onEnter: function (args) { this.user = args[1]; },
    onLeave: function () {
      var name = api_CUserCharacInfo_getCurCharacName(this.user);
      sendWelcomeMessage(this.user, name);      // 复用框架已有的公共函数
    }
  });
}
Hook 地址(0x…)与服务端二进制版本强绑定,跨版本需重新定位。贡献插件时请注明适用的服务端版本,并尽量把地址、魔法数写成显式常量。

内存补丁(无 Hook)

// initFn: baitan14  —— 放开个人摆摊格子上限到 14
function baitan14() {
  Memory.protect(ptr(0xXXXXXXX), 4, 'rwx');
  ptr(0xXXXXXXX).writeU8(14);
}

hooks[] 声明(元数据,非代码)

把 code 里每个 Hook 的地址在 hooks 里登记一条,供 DPForge 做冲突检测与展示——它不生成代码。

字段说明
addr目标地址,与 code 里 ptr(0x…) 一致
modeattach=Interceptor.attach(观察/改参/改返回,可共存);replace=Interceptor.replace(替换整函数,独占);patch=Memory 写字节(独占,同址=字节冲突)
dup可选,true=已知与其它模块共用该地址(抑制重复告警)
冲突规则:同址多个 patch → 🔴 报错;多个 replace → 🟠 警告;多个 attach → 标 dup(通常可共存)。

插件设置配置

把可调参数写进 settings 数组,DPForge 会在「基本设置」里自动渲染成输入框 / 开关,并把用户填的值替换进代码中的 {{key}} 占位符。

"settings": [
  { "key": "boss_start_hour", "label": "开启时间(点)", "type": "number",
    "default": 21, "description": "每天几点整开启活动 (0-23)" },
  { "key": "phase2_dungeon_name", "label": "二阶段副本名", "type": "text",
    "default": "罗特斯宫殿", "description": "广播文案中显示的副本名称" },
  { "key": "phase1_unique_team", "label": "一阶段队伍去重", "type": "toggle",
    "default": false, "description": "同一队伍多次通关只计一次" }
]
字段说明
key参数名,同时是代码里的占位符 {{key}}
label界面显示名
typenumber/text/toggle/select/itemId/table/json(高级)
default默认值(原来写死的那个值)
advanced可选,true 标为「高级」参数(json 类推荐加)
description参数说明(显示在输入框旁)

高级参数(数组 / 对象)用 type:"json"

{ "key": "phase1_dungeons", "label": "一阶段地图列表", "type": "json", "advanced": true,
  "default": [ { "dgn_id": 161, "name": "鲨鱼栖息地", "team_target": 5 } ],
  "description": "[{dgn_id, name, team_target}, ...] 支持任意张图" }

在代码里使用占位符(都裸写

var START_HOUR = {{boss_start_hour}};    // number → 21
var DUNGEON    = {{phase2_dungeon_name}}; // text → "罗特斯宫殿"(自动带引号!)
var DUNGEONS   = {{phase1_dungeons}};    // json → [{...}]
if ({{phase1_unique_team}}) { }          // toggle → true / false
⚠️ 生成时 {{key}} 被替换成该值的 JSON 字面量json.Marshal)。文本会自动带引号,所以模板里写 name = {{k}}不要"{{k}}"(否则变成双引号,语法错误)。number/toggle/json 同理,一律裸写。
把"参数写死"的插件改造成模块化的完整步骤 + AI 改造 Prompt,见知识库 plugin-dev/插件模块化改造指南.md

在 DPForge 中使用在线插件

DPForge 客户端已内置指向本站,无需任何配置:

  1. 打开 DPForge → 插件配置 → 点右上角 🌐 在线插件
  2. 在列表里选插件,点 导入 / 更新(已安装的会显示「更新」)。
  3. 导入后到对应分类里勾选启用,再「⚡ 生成部署」即可。

也可在本站插件详情里「📋 复制插件 JSON」手动保存备份。

提交插件(在线投稿)

不需要 Git、不需要自己部署。直接在本站 提交插件 页填写并提交:

  1. 打开 提交插件,填 id / 分类 / 名称 / initFn / 说明 / 设置项 / 注入代码(可点「填入示例」参考)。
  2. 点「提交审核」,你的插件进入待审核队列。
  3. 审核通过后即刻上架,所有 DPForge 用户可在「🌐 在线插件」里拉取。
  4. 想更新已上架的插件?用同一个 id 再提交一次,审核通过即覆盖为新版。
安全提示:插件是会被服务端执行的原生注入代码。请勿提交带后门、外联上传、破坏性内存写入的代码;审核会重点检查 Interceptor 目标、网络请求与内存写入,可疑代码一律拒绝。