侧边栏壁纸
  • 累计撰写 12 篇文章
  • 累计创建 36 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

从 QQ 到 Minecraft:我如何主导开发一套服务器管理与消息桥接系统

项目名称:MC × QQ 管理平台
当前服务端版本:8.8.2
Minecraft 插件版本:1.1.4
项目地址:https://github.com/SZYInnovationStudio/mcqqmodule

前言

这个项目最初源于一个很实际的需求:我希望直接在 QQ 群里查询 Minecraft 服务器状态、管理玩家绑定关系,并实现 QQ 与 Minecraft 之间的消息互通。

随着使用需求增加,项目逐渐加入了 QQ/OpenID 登记、AQQBot 数据查询、RCON 管理、服务器日志查看、玩家进出服通知、每日签到经济模块等功能,最终形成了一套相对完整的 Minecraft 与 QQ 管理平台。

整个项目由我主导设计和开发,GPT 作为辅助开发工具参与其中。功能需求、业务规则、安全边界、界面方向、测试标准和最终验收都由我确定。GPT 主要负责根据我的要求生成部分代码、补充测试、分析问题以及整理文档。

简单来说,这是一次“人工主导、GPT 辅助”的协作开发实践,而不是将整个项目直接交给 AI 自动生成。


一、项目要解决的问题

在传统的 Minecraft QQ 群管理中,机器人、绑定插件、RCON 和服务器后台通常是相互独立的。

管理员可能需要同时处理以下系统:

  • QQ 官方机器人
  • Minecraft 服务端
  • RCON 控制台
  • AQQBot 玩家绑定数据
  • 玩家 QQ 与 OpenID 的登记关系
  • 服务器日志
  • 签到、经济等扩展功能

这些功能分散之后,会出现一些实际问题:

  1. 玩家不知道自己绑定了哪些 Minecraft 账号。
  2. 管理员难以统一查询 QQ、OpenID 和玩家名称。
  3. QQ 群消息转发与服务器控制命令容易混在一起。
  4. 服务器启动、关闭和插件重载可能产生错误通知。
  5. 修改一个功能时容易影响已经稳定运行的其他功能。
  6. 旧版插件与新版服务端之间存在兼容问题。
  7. 直接公开项目时,密钥和用户数据存在泄漏风险。

因此,我决定把这些能力整合到一个统一的管理平台中。


二、技术范围

这个项目主要涉及以下技术范围。

1. Node.js 服务端

管理平台服务端使用 Node.js 开发,主要负责:

  • 对接 QQ 官方 Bot
  • 解析 QQ 群命令
  • 管理 QQ 与 OpenID 登记
  • 调用 Minecraft RCON
  • 接收 Minecraft 插件心跳
  • 接收玩家聊天与进出服事件
  • 接收只读服务器日志
  • 加载增量功能模块
  • 提供后台管理接口
  • 输出连接状态和版本信息

Node.js 适合处理机器人消息、HTTP 请求、定时任务和插件长轮询等 I/O 密集型工作。

2. Minecraft Bukkit 插件

Minecraft 端使用 Java 编写 Bukkit 插件。

插件负责:

  • Minecraft 聊天转发
  • 玩家进入和离开服务器通知
  • 插件连接心跳
  • 服务端启动与停止事件上报
  • 只读获取 logs/latest.log
  • 读取 AQQBot 的 data.yml
  • 上报插件版本
  • 接收 QQ 转发到 Minecraft 的安全消息

插件不会接收并执行任意后台控制台命令。TPS、玩家列表和管理员命令统一通过受控的 RCON 通道处理。

3. Bukkit 兼容体系

最初的插件直接依赖 Paper API,其中使用了:

  • AsyncChatEvent
  • Adventure Component
  • Paper 专属插件元数据接口

这导致插件只能可靠运行在特定 Paper 版本上。

后续我将插件改为只使用 Bukkit 公共 API:

  • 使用 AsyncPlayerChatEvent
  • 使用 Bukkit 的 ChatColor
  • 使用标准 Player#sendMessage
  • 使用 PluginDescriptionFile 获取版本
  • 移除 Paper 和 Adventure 的强制依赖

目前插件以 Spigot 1.13.2 API 编译:

api-version: '1.13'

编译目标为 Java 8 字节码,因此可用于 Minecraft 1.13 至 1.21.11 的 Bukkit API 兼容服务端,包括:

  • CraftBukkit
  • Spigot
  • Paper
  • Purpur
  • Leaves
  • 其他完整实现 Bukkit API 的衍生服务端

需要说明的是,Fabric、Forge 和 NeoForge 原生服务端并不直接实现 Bukkit API,因此不属于当前插件的原生兼容范围。

4. Web 管理后台

后台采用轻量级 Web 页面实现,主要包含:

  • 管理员账户设置
  • QQ 与 OpenID 登记管理
  • 玩家绑定查询
  • AQQBot 整库只读展示
  • 服务器日志页面
  • RCON 终端
  • 消息模板设置
  • 插件连接设置
  • 模块管理
  • 实时状态查看

后台页面和接口都尽量保持单一职责,避免把所有功能堆在同一个页面中。

5. 模块系统

为了避免每次新增功能都修改核心代码,我设计了增量模块机制。

模块可以提供:

  • 独立页面
  • 独立配置
  • QQ 命令
  • 服务端处理逻辑
  • 版本号
  • 独立启用开关
  • 权限声明

每日签到经济模块就是通过这套机制实现的。

用户发送:

/qd

或者:

/签到

系统查询该 QQ 名下绑定的 Minecraft 玩家。如果存在多个玩家,会要求用户选择:

/qd add 玩家名

确认玩家属于当前 QQ 后,系统通过 RCON 调用经济插件命令,随机发放 1000 至 10000 游戏币,并限制每天领取一次。


三、整体架构

系统主要由四部分组成:

QQ 群
  │
  ▼
QQ 官方 Bot
  │
  ▼
Node.js 管理平台
  ├── QQ/OpenID 登记
  ├── AQQBot 查询
  ├── RCON
  ├── 管理后台
  ├── 模块系统
  └── 插件交换接口
          │
          ▼
Minecraft Bukkit 插件
  ├── 聊天事件
  ├── 玩家进出服
  ├── 生命周期状态
  ├── AQQBot 数据读取
  └── latest.log 只读日志

插件采用主动连接方式。

也就是说,Minecraft 插件定期请求管理平台:

POST /api/plugin/exchange

这种设计不需要在 Minecraft 服务器上额外开放插件端口,部署和防火墙配置相对简单。


四、QQ 与 Minecraft 消息转发

消息转发分为两个方向。

QQ 到 Minecraft

QQ 群消息先经过以下检查:

  1. 是否来自允许的 QQ 群。
  2. 是否为机器人自己发送的消息。
  3. 用户是否已经登记 QQ 与 OpenID。
  4. 是否为允许执行的业务命令。
  5. 消息参数是否符合格式。
  6. 是否包含控制字符或注入内容。

通过检查后,普通消息会进入插件消息队列,由 Minecraft 插件取回并发送给在线玩家。

Minecraft 到 QQ

Minecraft 玩家聊天时,插件获取:

  • 玩家名称
  • 聊天内容
  • 插件运行实例 ID
  • 消息序号

服务端对事件去重后,再发送到允许的 QQ 群。

系统不会把普通群消息直接当成 RCON 或 Minecraft 控制台命令执行。例如群成员发送:

/tp 玩家1 玩家2

不会触发 Minecraft 的 TP 命令。

这是项目中非常重要的安全边界。


五、QQ、OpenID 与玩家绑定

QQ 官方 Bot 使用 OpenID 标识用户,但 AQQBot 数据通常使用真实 QQ 号。

因此系统需要维护以下关系:

QQ 号 <-> OpenID <-> Minecraft 玩家名

后台可以按照以下字段查询:

  • QQ 号
  • OpenID
  • Minecraft 玩家名

管理员可以执行:

  • 新建登记关系
  • 修改 QQ 号
  • 修改 OpenID
  • 查询名下玩家
  • 单个解除绑定
  • 批量解除绑定
  • 批量修改绑定
  • 全选操作
  • 二次确认后清除

Minecraft 玩家名称允许纯数字形式,同时保留前导零,避免将玩家名错误转换成数字。

例如:

001234

必须一直作为字符串处理,不能转换成:

1234

六、AQQBot 整库读取

Minecraft 插件会只读加载:

plugins/AQQBot/data.yml

然后将经过限制和清洗后的 QQ 与玩家绑定关系发送给管理平台。

为了控制风险,我增加了以下限制:

  • 只接受格式正确的 QQ 号
  • 限制最大记录数量
  • 限制单个 QQ 下的玩家数量
  • 校验玩家名称
  • 限制字段长度
  • 后台整库页面默认只读
  • 插件不直接修改 AQQBot 数据

涉及解绑时,系统通过受控命令执行,并根据 AQQBot 的实时查询结果确认操作是否成功。


七、服务器日志功能

插件可以只读访问:

logs/latest.log

日志读取采用增量方式,不会每次上传整个文件。

实现时记录了:

  • 当前文件位置
  • 文件标识
  • 文件大小
  • 单次读取上限
  • 单次最大行数
  • 日志批次编号

日志发生轮转或文件变小时,插件会重新定位读取位置。

为了避免日志无限上传,系统还限制了:

  • 每批最大 64 KB
  • 每批最多 200 行
  • 单行最大长度
  • 重复批次去重
  • 后台独立开关

日志功能只读取文件,不修改 Minecraft 日志。


八、服务器开关状态误报问题

开发过程中遇到过一个比较典型的问题。

QQ群里会连续收到:

[SZYDBOT] 服务器已关闭
[SZYDBOT] 服务器已开启

最初判断是插件“抽风”,后来分析发现,Bukkit 插件在以下情况下都会触发 onDisable():

  • Minecraft 服务器真正关闭
  • 插件热重载
  • 插件管理器重启插件
  • 替换 JAR 后重新加载
  • 服务端执行 reload

旧逻辑把所有 onDisable() 都当成服务器关机,因此插件短暂重载时也会发送关闭通知。

第一版处理

最初增加了 15 秒等待窗口:

收到 stop
  │
  ├── 15 秒内重新启动:取消关闭通知
  └── 15 秒后仍未连接:发送关闭通知

但实际测试发现,一些 Minecraft 服务器重启时间超过 15 秒,而且原来的心跳超时逻辑仍可能绕过这层保护。

最终处理

最终将显式 stop 与心跳超时合并为统一离线确认机制:

插件停止或心跳超时
        │
        ▼
进入 90 秒离线确认期
        │
        ├── 期间收到任意心跳:取消关闭通知
        │
        └── 持续离线:发送“服务器已关闭”

关键逻辑类似:

schedulePluginOffline(lastSeen) {
  if (this.pluginStopTimer) return;

  const remaining = Math.max(
    0,
    lastSeen + this.pluginOfflineConfirmMs - Date.now()
  );

  this.pluginStopTimer = setTimeout(() => {
    this.pluginStopTimer = null;

    if (this.stopped) return;
    if (this.pluginConnection.lastSeen > lastSeen) return;

    void this.sendMcServerStatusToQq('offline');
  }, remaining);
}

任何正常插件交换请求都会取消待处理的关闭通知:

cancelPluginOffline() {
  if (this.pluginStopTimer) {
    clearTimeout(this.pluginStopTimer);
  }

  this.pluginStopTimer = null;
}

这样可以避免服务器短暂重启、插件热加载或网络抖动导致群内连续发送关闭和开启通知。


九、安全设计

这个项目不仅要实现功能,还要防止 QQ 群消息变成服务器控制入口。

1. 群命令白名单

只有明确支持的业务命令才会进入处理流程。

普通用户无法通过构造命令调用任意 RCON 指令。

2. 插件不执行控制台命令

Minecraft 插件只处理聊天、状态、日志和数据读取,不接收后台传来的任意控制台命令。

3. RCON 参数限制

涉及绑定、解绑和经济发放时,服务器只会执行提前定义好的命令格式。

玩家名必须通过格式校验。

4. 插件密钥

插件调用管理平台时需要携带独立密钥:

Authorization: Bearer <PLUGIN_KEY>

密钥要求为 32 至 128 位,只允许安全字符。

5. HTTPS 限制

插件与远程管理平台通信时要求使用 HTTPS。

只有回环地址允许使用 HTTP:

http://127.0.0.1

6. 敏感数据不进入公开 Git

以下内容不会提交到公开仓库:

  • 管理员密码
  • QQ Bot AppSecret
  • 插件 Key
  • RCON 密码
  • 用户登记数据
  • 加密主密钥
  • 运行日志

项目通过 .gitignore 排除:

.env
data/
node_modules/
dist/
minecraft-plugin/target/

十、测试与验证

项目目前使用 Node.js 自带的测试框架。

测试范围包括:

  • 管理员账户
  • QQ/OpenID 登记
  • AQQBot 查询
  • 纯数字玩家名
  • 绑定与解绑
  • 批量操作
  • RCON
  • MOTD
  • TPS
  • 玩家列表
  • 消息转发
  • 命令注入防护
  • 模块安装
  • 每日签到
  • 插件心跳
  • 服务器日志
  • 插件版本上报
  • 开关服状态
  • 插件重载误报
  • 状态命令

执行方式:

npm test

当前完整测试结果:

tests: 58
pass: 58
fail: 0

其中专门增加了插件重载测试:

test('插件重启在离线确认期内恢复时不误报,持续停止才播报关闭', async () => {
  // 模拟插件启动
  // 模拟心跳超时
  // 在确认期内恢复
  // 验证没有发送“服务器已关闭”
  // 再模拟持续停止
  // 验证最终发送关闭通知
});

Minecraft 插件还会检查:

  • Maven 构建是否成功
  • plugin.yml 版本是否正确
  • Java 字节码版本
  • 是否残留 Paper 专属引用
  • 是否错误引入后台控制台命令执行能力

十一、版本与构建产物管理

插件构建产物按照新版和历史版分类:

public/
├── new/
│   └── szydmc-chat-bridge-1.1.4.jar
└── old/
    ├── szydmc-chat-bridge-1.1.3.jar
    └── szydmc-chat-bridge-1.0.0.jar

其中:

版本 类型 说明
1.1.4 新版 Bukkit 公共 API 通用版
1.1.3 历史版 原 Paper 1.21.11 构建
1.0.0 历史版 根据 Git 历史源码重新构建

没有独立源码记录的版本不会人为伪造构建产物。

每个发布包都会生成 SHA-256,方便检查下载文件是否完整。


十二、我是如何与 GPT 协作开发的

GPT 在这个项目中承担的是辅助角色。

我负责的部分

我主要负责:

  • 提出真实使用需求
  • 决定功能优先级
  • 设计用户操作流程
  • 明确安全边界
  • 决定哪些命令允许执行
  • 设计后台页面结构
  • 确定版本规划
  • 提供实际运行反馈
  • 检查群聊展示效果
  • 判断功能是否符合服务器实际情况
  • 审核代码和测试结果
  • 决定最终是否发布

很多问题只有在真实 QQ 群和 Minecraft 服务器中才能发现。例如开关服误报、插件超时、玩家名称格式、AQQBot 数据变化等,都需要人工结合实际使用场景判断。

GPT 辅助的部分

GPT 主要用于:

  • 根据需求编写部分代码
  • 分析错误日志
  • 搜索代码调用关系
  • 补充自动化测试
  • 检查遗漏的版本号
  • 整理安装教程
  • 生成构建和打包命令
  • 协助重构兼容代码
  • 检查公开包是否包含敏感数据
  • 根据人工反馈快速迭代

为什么人工必须占主导

GPT 可以快速生成代码,但它不了解服务器的全部实际环境。

例如:

  • 插件重载是否应该算服务器关闭
  • QQ 群内哪些命令允许执行
  • 绑定关系以哪一方数据为准
  • 是否允许批量解绑
  • 哪些数据能够公开
  • 页面怎样分类更适合管理员使用
  • 某次错误究竟是代码问题还是部署问题

这些决策不能只依靠自动生成。

我的开发方式通常是:

人工提出需求
    │
    ▼
GPT 协助分析和实现
    │
    ▼
人工检查代码与界面
    │
    ▼
自动化测试
    │
    ▼
真实服务器验证
    │
    ▼
人工确认后发布

GPT 提高了编码和排查效率,但项目方向、业务逻辑和最终质量仍由人工负责。


十三、部署方式

管理平台

安装 Node.js 22 或更高版本:

npm install
npm start

默认访问地址:

http://127.0.0.1:2556

Minecraft 插件

将 JAR 放入:

plugins/

启动一次服务器后编辑:

plugins/SZYDMCChatBridge/config.yml

示例:

bridge-url: 'http://127.0.0.1:2556/api/plugin/exchange'
key: '后台生成的至少32位插件Key'
aqqbot-data-path: '../AQQBot/data.yml'
server-log-path: '../../logs/latest.log'

管理平台与 Minecraft 不在同一台服务器时,应使用 HTTPS 反向代理或安全隧道。


十四、目前的不足与后续计划

当前项目仍有一些可以继续改进的地方:

  • 增加更多 Bukkit 服务端的实际启动测试
  • 完善模块权限隔离
  • 增加更清晰的运行监控
  • 改进错误日志分类
  • 增加配置导入与导出
  • 研究 Telegram 接入
  • 研究减少对 AQQBot 的依赖
  • 增加更完整的升级与回滚工具
  • 将部分固定时间参数改成后台可配置项

技术项目不可能一次完成。相比盲目增加功能,我更倾向于先保证已有功能稳定,再逐步扩展。


结语

这个项目从一个简单的 QQ 与 Minecraft 消息桥接需求,逐渐发展成包含机器人、后台、插件、RCON、日志、绑定和模块系统的综合管理平台。

在开发过程中,我负责提出需求、制定规则、检查实际效果并决定最终实现;GPT 帮助我提高编码、测试和排查问题的效率。

这次实践让我感受到,GPT 很适合作为开发助手,但它不能代替项目负责人对需求、安全和真实使用场景的判断。

真正决定项目质量的,仍然是人工对问题的理解、持续测试以及每一次具体的技术取舍。

如果你也在开发 Minecraft 服务器工具、QQ 机器人或管理后台,希望这篇文章能提供一些参考。


作者:ZHANGZHAORUI
项目仓库:https://github.com/SZYInnovationStudio/mcqqmodule

1

评论区

播放音乐