项目名称: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 的登记关系
- 服务器日志
- 签到、经济等扩展功能
这些功能分散之后,会出现一些实际问题:
- 玩家不知道自己绑定了哪些 Minecraft 账号。
- 管理员难以统一查询 QQ、OpenID 和玩家名称。
- QQ 群消息转发与服务器控制命令容易混在一起。
- 服务器启动、关闭和插件重载可能产生错误通知。
- 修改一个功能时容易影响已经稳定运行的其他功能。
- 旧版插件与新版服务端之间存在兼容问题。
- 直接公开项目时,密钥和用户数据存在泄漏风险。
因此,我决定把这些能力整合到一个统一的管理平台中。
二、技术范围
这个项目主要涉及以下技术范围。
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 群消息先经过以下检查:
- 是否来自允许的 QQ 群。
- 是否为机器人自己发送的消息。
- 用户是否已经登记 QQ 与 OpenID。
- 是否为允许执行的业务命令。
- 消息参数是否符合格式。
- 是否包含控制字符或注入内容。
通过检查后,普通消息会进入插件消息队列,由 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
评论区