Github2 天前QQ 驱动的 Minecraft 登录 / 账户认证系统(MQE 开源版 + 增量)。
OpenQQAuth 运行在 Velocity 代理端:玩家未验证身份时被隔离在登录界面(图形化认证界面:dialog / 虚拟箱子菜单 / 虚拟铁砧,全协议版本适配),验证通过后才被放行到后端 Paper 主服。它以 QQ 为每个账户的强制归属凭证,支持三种登录方式:
并额外提供**登录凭证(Token)**能力:安装 Fabric / NeoForge 双端合一 mod 后,玩家可在多人游戏界面点击"用凭证连接",输入由 QQ 群机器人私发的凭证即可免密进服(30 天有效,可吊销)。
领域术语表见
CONTEXT.md,架构决策见docs/adr/,规格见.scratch/qqauth/spec.md,外部 API 事实查证见.scratch/qqauth/api-reference.md。
绑定 <验证码>,发送者 QQ 与目标 QQ 必须一致,防抢答)premiumUuid 固定命中(改名不影响登录);/opa bindpremium 跨名绑定;顶名离线拒绝 + 冒名建号防线/opa bindxbox 继承绑定(基岩绑到 Java 账户共享位置/背包)、Java/基岩互斥在线、/opa unbindxbox 解绑恢复独立身份获取凭证 机器人私发 → mod 端"用凭证连接"免密进服;30 天有效、可吊销;防重放(一次性 nonce 挑战-响应)kick / freeze / unfreeze / ban / unban / list / status / check / exec / reload / reconnecttransfer confirm 确认 → 目标接管(ADR-0007,无强制夺权)PlayerAuthenticatedEvent / AccountBoundEvent / AccountFrozenEvent / AccountBannedEvent 发布,供其他插件经 Bukkit ServicesManager 订阅ReadOnlyAuthApi 供 Paper 端插件(经济 / 领地 / 白名单联动)依赖zh_CN / en_US),全量翻译键覆盖┌──────────────┐ ┌──────────────────────────────┐ ┌──────────────┐
│ Minecraft │────▶│ Velocity (OpenQQAuth 门禁) │────▶│ Paper 主服 │
│ 客户端 │ │ dialog/箱子/铁砧 认证界面 │ │ (只读 API/事件)│
└──────────────┘ │ 登录判定管线 LoginPipeline │ └──────────────┘
│ 加密握手/正版验证/基岩 Floodgate│
└──────────────┬───────────────┘
│ OneBot (WebSocket)
┌──────────────▼───────────────┐
│ QQ 群机器人(绑定/重置/管理/凭证) │
└──────────────────────────────┘
| 模块 | 说明 |
|---|---|
core | 全部领域逻辑:账户/验证码/状态机/登录判定管线/凭证/事件总线/命令框架,平台无关 |
bootstrap/velocity | Velocity 代理插件:门禁、虚拟窗口 UI、协议族编解码、OneBot 接线、mod 登录查询 |
bootstrap/paper | Paper 插件:只读 API 暴露(Bukkit ServicesManager)、领域事件订阅示例 |
bootstrap/bukkit / bungeecord | 模板兼容骨架(当前仅加载占位) |
bootstrap/fabric + bootstrap/neoforge | 双端合一 jar:客户端"用凭证连接" UI 与凭证传输、服务端占位 |
build-logic | Gradle 约定插件(Java/Kotlin 编译、checkstyle、spotless 统一配置) |
gradle --no-daemon :bootstrap:velocity:build # Velocity 插件
gradle --no-daemon :bootstrap:paper:build # Paper 插件
gradle --no-daemon :bootstrap:fabric:build :bootstrap:neoforge:build # mod 双端 jar
产物位于各模块 build/libs/ 下。
velocity/plugins/,paper 插件 jar 放入 paper/plugins/config.yml,按需修改(见配置文件说明)qq-bot.ws-url 与 qq-bot.ws-token,将管理 QQ 加入 qq-bot.admin-qqsreload 或管理员执行 /opa reload 可热重载配置config-version: 1
qq-bot:
ws-url: "ws://127.0.0.1:6700" # OneBot WebSocket 服务地址
ws-token: "" # 访问令牌(如启用鉴权)
admin-qqs: # 管理员 QQ 列表
- "10001"
login:
max-failed-attempts: 5 # 密码连错锁定阈值
lockout-minutes: 1 # 锁定时长(分钟)
storage:
driver: sqlite
sqlite-file: openqqauth.db
所有配置集中在 Velocity 插件目录的 config.yml(QqAuthConfiguration,Configurate 加载)。
qq-bot(OneBot 机器人)| 键 | 默认值 | 说明 |
|---|---|---|
qq-bot.ws-url | ws://127.0.0.1:6700 | OneBot 11 WebSocket 服务地址 |
qq-bot.ws-token | "" | 访问令牌 |
qq-bot.admin-qqs | [] | 管理员 QQ 列表(拥有 ADMIN 权限) |
accounts(账户)| 键 | 默认值 | 说明 |
|---|---|---|
accounts.per-qq-limit | 3 | 单个 QQ 可绑定的最大账户数 |
login(登录判定)| 键 | 默认值 | 说明 |
|---|---|---|
login.fast-login-window | 30 | 快捷登录窗口(分钟):断线重连免密的时间窗 |
login.fast-login-min-online-minutes | 10 | 触发快捷登录要求此前在线满时长(分钟) |
login.fast-login-notify-qq | true | 快捷登录触发时向绑定 QQ 发送通知 |
login.max-failed-attempts | 5 | 密码连错锁定阈值 |
login.lockout-minutes | 1 | 锁定时长(分钟) |
login.max-sessions-per-ip | 3 | 每 IP 并发连接上限(超额拒绝) |
login.bind-frequency-per-minute | 3 | 绑定频率限制(每分钟) |
login.session-timeout-seconds | 300 | 会话超时踢出(秒) |
login.bind-timeout-seconds | 180 | 绑定流程超时(秒) |
login.inherit-bind-window-minutes | 5 | 基岩继承绑定窗口(分钟) |
login.max-name-length | 30 | 改名输入长度上限 |
verify-code(验证码)| 键 | 默认值 | 说明 |
|---|---|---|
verify-code.length | 4 | 验证码长度 |
verify-code.expire-seconds | 180 | 验证码有效期(秒) |
token(登录凭证)| 键 | 默认值 | 说明 |
|---|---|---|
token.enabled | true | 是否启用凭证登录路径 |
token.ttl-days | 30 | 凭证有效期(天) |
sync-groups(群聊互通)| 键 | 默认值 | 说明 |
|---|---|---|
sync-groups.enabled | false | 启用消息同步 |
sync-groups.group-ids | [] | 参与同步的群 ID 列表 |
sync-groups.game-to-group | true | 游戏内 → 群 转发 |
sync-groups.group-to-game | true | 群 → 游戏内 转发 |
sync-groups.merge-window-seconds | 5 | 合并窗口(秒) |
sync-groups.max-forwards-per-minute | 10 | 每分钟最大转发条数 |
storage(存储)| 键 | 默认值 | 说明 |
|---|---|---|
storage.driver | sqlite | 存储驱动(当前支持 SQLite) |
storage.sqlite-file | openqqauth.db | SQLite 数据库文件路径 |
premium(正版检测)| 键 | 默认值 | 说明 |
|---|---|---|
premium.enabled | true | 启用正版检测 |
premium.name-query-cache-hours | 24 | 名字→UUID 查询缓存时长(小时) |
premium.http-timeout-seconds | 5 | Mojang API 超时(秒) |
premium.rate-limit-per-window | 600 | 限速窗口内最大查询数 |
premium.rate-limit-window-minutes | 10 | 限速窗口(分钟) |
premium.bind-wait-minutes | 5 | 正版绑定等待标记时长(分钟) |
命令由 QQ 群机器人接收。权限分级见权限模型。
BOUND_MEMBER)| 命令 | 说明 |
|---|---|
kick | 踢出发送者名下全部在线账户(自助踢出异常登录) |
freeze | 冻结发送者名下账户(临时冻结,本人可解) |
unfreeze | 解冻发送者名下账户 |
status | 查看发送者名下账户信息与验证状态 |
list | 查看在线列表 |
获取凭证 | 为发送者名下账户签发新登录凭证并私发(重复获取覆盖旧凭证) |
吊销凭证 [<账户名>] | 立即作废名下账户的凭证 |
| 命令 | 说明 |
|---|---|
绑定 <验证码> | 确认 QQ 绑定(游戏内界面显示的验证码) |
重置 <验证码> | 确认密码重置(铁砧灰色混凝土发起) |
解绑正版 <验证码> | 解绑正版身份关联 |
解绑基岩 <验证码> | 解绑基岩账户(恢复独立身份) |
ADMIN)| 命令 | 说明 |
|---|---|
bind 1 <QQ> <玩家名> | 强制绑定账户(随后自动私发登录凭证) |
bind 2 <QQ> | 重置账户密码(新密码打印控制台) |
ban @<目标> [名字] / unban | 封禁 / 解封账户(持久,仅管理员可解) |
freeze @<目标> [名字] / unfreeze | 冻结 / 解冻任意账户(临时可逆) |
check | 查看任意玩家完整信息与服务器概况 |
exec <服务器> <指令> | 远程执行后端服务器命令(前后自动审计留痕) |
transfer confirm <账户> <目标QQ> <正版名> | 确认自愿移交(原主解绑后) |
transfer list | 查看待确认移交队列 |
reload | 热重载配置 |
reconnect | 重连 QQ 机器人 |
游戏内使用 /opa 前缀(Velocity 命令注册):
| 命令 | 说明 |
|---|---|
/opa bindpremium <名字> | 跨名正版绑定(正版身份接管原离线账户) |
/opa bindxbox <名字> | 发起基岩继承绑定(基岩账户绑到指定 Java 账户,共享位置/背包) |
/opa unbindxbox | 解绑基岩继承(恢复独立身份,数据保留) |
/opa reload | 热重载配置(管理员) |
绑定 <验证码>(发送者 QQ 必须与填写的 QQ 一致,防抢答)重置 <验证码> 确认绑定正版 <验证码> 完成 QQ 第二因素premiumUuid 命中账户并做身份替换,改名不影响)/opa bindpremium 手动跨名绑定绑定 <验证码> 确认 → 绑定即放行(无密码)/opa bindxbox:将基岩账户继承绑定到 Java 账户(共享位置/背包数据),Java/基岩互斥在线/opa unbindxbox 或群内 解绑基岩:恢复独立身份(QQ 账户数未达上限时数据保留)fast-login-notify-qq 可关)获取凭证 → 机器人私发 30 天有效的登录凭证吊销凭证 作废openqqauth:token)发送凭证,Velocity 端以 128 位随机 nonce 做挑战-响应防重放TokenLoginChecker):凭证 + 账户绑定关系 + 未过期 + 未吊销 → 命中即免密放行save-token 开关,关闭即清除)启用 sync-groups.enabled 后:
group-to-game)game-to-group)/opa at @ 群成员、/opa re 回复群消息| 权限级 | 含义 | 获得方式 |
|---|---|---|
ANY | 任意群成员 | 默认 |
BOUND_MEMBER | 已绑定账户的玩家 | 完成 QQ 绑定 |
ADMIN | 管理员 | 配置 qq-bot.admin-qqs |
管理员指令(bind / ban / exec / check / transfer / reload / reconnect 等)执行前后自动写入 CommandAuditLog 审计留痕。
# 全模块编译 + 测试 + checkstyle + spotless
gradle --no-daemon build
# 仅编译某模块
gradle --no-daemon :core:compileJava
gradle --no-daemon :bootstrap:velocity:compileJava
gradle --no-daemon :bootstrap:paper:compileJava
gradle --no-daemon :bootstrap:fabric:compileJava
gradle --no-daemon :bootstrap:neoforge:compileJava
# 跑某模块测试
gradle --no-daemon :core:test
gradle --no-daemon :bootstrap:velocity:test
# 代码风格校验
gradle --no-daemon :core:checkstyleMain :core:spotlessCheck
系统需安装 Gradle 9.6.1(不使用 wrapper);构建内存建议
-Xmx2G(见gradle.properties)。
.scratch/<feature>/(spec 与编号票据),见 docs/agents/issue-tracker.mdneeds-triage / needs-info / ready-for-agent / ready-for-human / wontfix,见 docs/agents/triage-labels.mdCONTEXT.md(账户 / QQ / 绑定 / 门禁 / 登录界面 / 正版绑定 / 继承绑定等)docs/adr/0001~0008(虚拟铁砧门禁、离线正版检测、OneBot 11、登录界面分层、登录凭证、固定账户键、名字冲突、快捷登录信任模型)CLAUDE.md(worktree 隔离、影响面验证、按票据提交、并发上限等)core/src/main/java/dev/nmouzh/openqqauth/
├── account/ # 账户模型、SQLite 仓储
├── anvil/ # 铁砧窗口状态机(UI 无关核心)
├── api/ # 只读查询 API(供 Paper 插件)
├── bedrock/ # 基岩支持(表单发送、绑定流程)
├── configuration/# 配置模型(Configurate)
├── event/ # 领域事件总线(SimpleDomainEventBus)
├── gate/ # 登录判定管线 LoginPipeline、会话、锁定、快捷登录
├── i18n/ # TranslationKey 枚举 + 中英双语资源
├── mojang/ # Mojang API 客户端(名字→UUID、hasJoined)
├── onebot/ # OneBot 11 客户端(WebSocket 消息收发)
├── password/ # 密码哈希(jBCrypt)
├── qq/ # QQ 域:绑定/重置/解绑状态机、群命令、审计日志、自愿移交
├── token/ # 登录凭证:签发/吊销/校验、传输协议、mod 通道
├── util/ # 工具类
└── verify/ # 验证码服务
Q:提示"机器人离线"无法绑定?
A:新玩家绑定前置检查机器人在线状态(BotOnlineProvider),机器人离线时绑定类操作降级为提示并踢出。确认 OneBot 已连接(reconnect 可重连)。
Q:1.12.2 等旧版本客户端无法登录?
A:铁砧协议与物品序列化已按协议族参数化支持旧版族(1.7.21.12.2,理论下限;1.12.2 承诺可用)。1.13 族内更早子版本与 1.7.21.12.1 的包 ID 漂移按"理论下限不承诺"处理;真实 Velocity 连接接线(内部 MinecraftConnection 桥接)为独立后续票据。
Q:凭证校验失败会怎样? A:不影响密码登录路径——校验失败仅记录日志,玩家回到密码输入界面,可正常用密码登录。
Q:如何让其他插件读取账户信息?
A:Paper 端经 Bukkit ServicesManager 获取 ReadOnlyAuthApi(账户/会话查询),并可订阅领域事件(PlayerAuthenticatedEvent 等)。集成示例见 bootstrap/paper 的 PaperAuthEvents。
Q:数据存储在哪里?
A:默认 SQLite 文件 openqqauth.db(storage.sqlite-file 可改路径)。
Q:名字冲突如何处理?
A:遵循 ADR-0007"过去先到先得、未来正版优先":冲突双方可走自愿移交(原主解绑 → 管理员 transfer confirm 确认 → 目标接管),系统不提供强制夺权路径。
本项目采用 CC0 1.0 Universal 许可,你可按需自由使用(包括修改许可用于自己的项目)。
Github2 天前QQ 驱动的 Minecraft 登录 / 账户认证系统(MQE 开源版 + 增量)。
OpenQQAuth 运行在 Velocity 代理端:玩家未验证身份时被隔离在登录界面(图形化认证界面:dialog / 虚拟箱子菜单 / 虚拟铁砧,全协议版本适配),验证通过后才被放行到后端 Paper 主服。它以 QQ 为每个账户的强制归属凭证,支持三种登录方式:
并额外提供**登录凭证(Token)**能力:安装 Fabric / NeoForge 双端合一 mod 后,玩家可在多人游戏界面点击"用凭证连接",输入由 QQ 群机器人私发的凭证即可免密进服(30 天有效,可吊销)。
领域术语表见
CONTEXT.md,架构决策见docs/adr/,规格见.scratch/qqauth/spec.md,外部 API 事实查证见.scratch/qqauth/api-reference.md。
绑定 <验证码>,发送者 QQ 与目标 QQ 必须一致,防抢答)premiumUuid 固定命中(改名不影响登录);/opa bindpremium 跨名绑定;顶名离线拒绝 + 冒名建号防线/opa bindxbox 继承绑定(基岩绑到 Java 账户共享位置/背包)、Java/基岩互斥在线、/opa unbindxbox 解绑恢复独立身份获取凭证 机器人私发 → mod 端"用凭证连接"免密进服;30 天有效、可吊销;防重放(一次性 nonce 挑战-响应)kick / freeze / unfreeze / ban / unban / list / status / check / exec / reload / reconnecttransfer confirm 确认 → 目标接管(ADR-0007,无强制夺权)PlayerAuthenticatedEvent / AccountBoundEvent / AccountFrozenEvent / AccountBannedEvent 发布,供其他插件经 Bukkit ServicesManager 订阅ReadOnlyAuthApi 供 Paper 端插件(经济 / 领地 / 白名单联动)依赖zh_CN / en_US),全量翻译键覆盖┌──────────────┐ ┌──────────────────────────────┐ ┌──────────────┐
│ Minecraft │────▶│ Velocity (OpenQQAuth 门禁) │────▶│ Paper 主服 │
│ 客户端 │ │ dialog/箱子/铁砧 认证界面 │ │ (只读 API/事件)│
└──────────────┘ │ 登录判定管线 LoginPipeline │ └──────────────┘
│ 加密握手/正版验证/基岩 Floodgate│
└──────────────┬───────────────┘
│ OneBot (WebSocket)
┌──────────────▼───────────────┐
│ QQ 群机器人(绑定/重置/管理/凭证) │
└──────────────────────────────┘
| 模块 | 说明 |
|---|---|
core | 全部领域逻辑:账户/验证码/状态机/登录判定管线/凭证/事件总线/命令框架,平台无关 |
bootstrap/velocity | Velocity 代理插件:门禁、虚拟窗口 UI、协议族编解码、OneBot 接线、mod 登录查询 |
bootstrap/paper | Paper 插件:只读 API 暴露(Bukkit ServicesManager)、领域事件订阅示例 |
bootstrap/bukkit / bungeecord | 模板兼容骨架(当前仅加载占位) |
bootstrap/fabric + bootstrap/neoforge | 双端合一 jar:客户端"用凭证连接" UI 与凭证传输、服务端占位 |
build-logic | Gradle 约定插件(Java/Kotlin 编译、checkstyle、spotless 统一配置) |
gradle --no-daemon :bootstrap:velocity:build # Velocity 插件
gradle --no-daemon :bootstrap:paper:build # Paper 插件
gradle --no-daemon :bootstrap:fabric:build :bootstrap:neoforge:build # mod 双端 jar
产物位于各模块 build/libs/ 下。
velocity/plugins/,paper 插件 jar 放入 paper/plugins/config.yml,按需修改(见配置文件说明)qq-bot.ws-url 与 qq-bot.ws-token,将管理 QQ 加入 qq-bot.admin-qqsreload 或管理员执行 /opa reload 可热重载配置config-version: 1
qq-bot:
ws-url: "ws://127.0.0.1:6700" # OneBot WebSocket 服务地址
ws-token: "" # 访问令牌(如启用鉴权)
admin-qqs: # 管理员 QQ 列表
- "10001"
login:
max-failed-attempts: 5 # 密码连错锁定阈值
lockout-minutes: 1 # 锁定时长(分钟)
storage:
driver: sqlite
sqlite-file: openqqauth.db
所有配置集中在 Velocity 插件目录的 config.yml(QqAuthConfiguration,Configurate 加载)。
qq-bot(OneBot 机器人)| 键 | 默认值 | 说明 |
|---|---|---|
qq-bot.ws-url | ws://127.0.0.1:6700 | OneBot 11 WebSocket 服务地址 |
qq-bot.ws-token | "" | 访问令牌 |
qq-bot.admin-qqs | [] | 管理员 QQ 列表(拥有 ADMIN 权限) |
accounts(账户)| 键 | 默认值 | 说明 |
|---|---|---|
accounts.per-qq-limit | 3 | 单个 QQ 可绑定的最大账户数 |
login(登录判定)| 键 | 默认值 | 说明 |
|---|---|---|
login.fast-login-window | 30 | 快捷登录窗口(分钟):断线重连免密的时间窗 |
login.fast-login-min-online-minutes | 10 | 触发快捷登录要求此前在线满时长(分钟) |
login.fast-login-notify-qq | true | 快捷登录触发时向绑定 QQ 发送通知 |
login.max-failed-attempts | 5 | 密码连错锁定阈值 |
login.lockout-minutes | 1 | 锁定时长(分钟) |
login.max-sessions-per-ip | 3 | 每 IP 并发连接上限(超额拒绝) |
login.bind-frequency-per-minute | 3 | 绑定频率限制(每分钟) |
login.session-timeout-seconds | 300 | 会话超时踢出(秒) |
login.bind-timeout-seconds | 180 | 绑定流程超时(秒) |
login.inherit-bind-window-minutes | 5 | 基岩继承绑定窗口(分钟) |
login.max-name-length | 30 | 改名输入长度上限 |
verify-code(验证码)| 键 | 默认值 | 说明 |
|---|---|---|
verify-code.length | 4 | 验证码长度 |
verify-code.expire-seconds | 180 | 验证码有效期(秒) |
token(登录凭证)| 键 | 默认值 | 说明 |
|---|---|---|
token.enabled | true | 是否启用凭证登录路径 |
token.ttl-days | 30 | 凭证有效期(天) |
sync-groups(群聊互通)| 键 | 默认值 | 说明 |
|---|---|---|
sync-groups.enabled | false | 启用消息同步 |
sync-groups.group-ids | [] | 参与同步的群 ID 列表 |
sync-groups.game-to-group | true | 游戏内 → 群 转发 |
sync-groups.group-to-game | true | 群 → 游戏内 转发 |
sync-groups.merge-window-seconds | 5 | 合并窗口(秒) |
sync-groups.max-forwards-per-minute | 10 | 每分钟最大转发条数 |
storage(存储)| 键 | 默认值 | 说明 |
|---|---|---|
storage.driver | sqlite | 存储驱动(当前支持 SQLite) |
storage.sqlite-file | openqqauth.db | SQLite 数据库文件路径 |
premium(正版检测)| 键 | 默认值 | 说明 |
|---|---|---|
premium.enabled | true | 启用正版检测 |
premium.name-query-cache-hours | 24 | 名字→UUID 查询缓存时长(小时) |
premium.http-timeout-seconds | 5 | Mojang API 超时(秒) |
premium.rate-limit-per-window | 600 | 限速窗口内最大查询数 |
premium.rate-limit-window-minutes | 10 | 限速窗口(分钟) |
premium.bind-wait-minutes | 5 | 正版绑定等待标记时长(分钟) |
命令由 QQ 群机器人接收。权限分级见权限模型。
BOUND_MEMBER)| 命令 | 说明 |
|---|---|
kick | 踢出发送者名下全部在线账户(自助踢出异常登录) |
freeze | 冻结发送者名下账户(临时冻结,本人可解) |
unfreeze | 解冻发送者名下账户 |
status | 查看发送者名下账户信息与验证状态 |
list | 查看在线列表 |
获取凭证 | 为发送者名下账户签发新登录凭证并私发(重复获取覆盖旧凭证) |
吊销凭证 [<账户名>] | 立即作废名下账户的凭证 |
| 命令 | 说明 |
|---|---|
绑定 <验证码> | 确认 QQ 绑定(游戏内界面显示的验证码) |
重置 <验证码> | 确认密码重置(铁砧灰色混凝土发起) |
解绑正版 <验证码> | 解绑正版身份关联 |
解绑基岩 <验证码> | 解绑基岩账户(恢复独立身份) |
ADMIN)| 命令 | 说明 |
|---|---|
bind 1 <QQ> <玩家名> | 强制绑定账户(随后自动私发登录凭证) |
bind 2 <QQ> | 重置账户密码(新密码打印控制台) |
ban @<目标> [名字] / unban | 封禁 / 解封账户(持久,仅管理员可解) |
freeze @<目标> [名字] / unfreeze | 冻结 / 解冻任意账户(临时可逆) |
check | 查看任意玩家完整信息与服务器概况 |
exec <服务器> <指令> | 远程执行后端服务器命令(前后自动审计留痕) |
transfer confirm <账户> <目标QQ> <正版名> | 确认自愿移交(原主解绑后) |
transfer list | 查看待确认移交队列 |
reload | 热重载配置 |
reconnect | 重连 QQ 机器人 |
游戏内使用 /opa 前缀(Velocity 命令注册):
| 命令 | 说明 |
|---|---|
/opa bindpremium <名字> | 跨名正版绑定(正版身份接管原离线账户) |
/opa bindxbox <名字> | 发起基岩继承绑定(基岩账户绑到指定 Java 账户,共享位置/背包) |
/opa unbindxbox | 解绑基岩继承(恢复独立身份,数据保留) |
/opa reload | 热重载配置(管理员) |
绑定 <验证码>(发送者 QQ 必须与填写的 QQ 一致,防抢答)重置 <验证码> 确认绑定正版 <验证码> 完成 QQ 第二因素premiumUuid 命中账户并做身份替换,改名不影响)/opa bindpremium 手动跨名绑定绑定 <验证码> 确认 → 绑定即放行(无密码)/opa bindxbox:将基岩账户继承绑定到 Java 账户(共享位置/背包数据),Java/基岩互斥在线/opa unbindxbox 或群内 解绑基岩:恢复独立身份(QQ 账户数未达上限时数据保留)fast-login-notify-qq 可关)获取凭证 → 机器人私发 30 天有效的登录凭证吊销凭证 作废openqqauth:token)发送凭证,Velocity 端以 128 位随机 nonce 做挑战-响应防重放TokenLoginChecker):凭证 + 账户绑定关系 + 未过期 + 未吊销 → 命中即免密放行save-token 开关,关闭即清除)启用 sync-groups.enabled 后:
group-to-game)game-to-group)/opa at @ 群成员、/opa re 回复群消息| 权限级 | 含义 | 获得方式 |
|---|---|---|
ANY | 任意群成员 | 默认 |
BOUND_MEMBER | 已绑定账户的玩家 | 完成 QQ 绑定 |
ADMIN | 管理员 | 配置 qq-bot.admin-qqs |
管理员指令(bind / ban / exec / check / transfer / reload / reconnect 等)执行前后自动写入 CommandAuditLog 审计留痕。
# 全模块编译 + 测试 + checkstyle + spotless
gradle --no-daemon build
# 仅编译某模块
gradle --no-daemon :core:compileJava
gradle --no-daemon :bootstrap:velocity:compileJava
gradle --no-daemon :bootstrap:paper:compileJava
gradle --no-daemon :bootstrap:fabric:compileJava
gradle --no-daemon :bootstrap:neoforge:compileJava
# 跑某模块测试
gradle --no-daemon :core:test
gradle --no-daemon :bootstrap:velocity:test
# 代码风格校验
gradle --no-daemon :core:checkstyleMain :core:spotlessCheck
系统需安装 Gradle 9.6.1(不使用 wrapper);构建内存建议
-Xmx2G(见gradle.properties)。
.scratch/<feature>/(spec 与编号票据),见 docs/agents/issue-tracker.mdneeds-triage / needs-info / ready-for-agent / ready-for-human / wontfix,见 docs/agents/triage-labels.mdCONTEXT.md(账户 / QQ / 绑定 / 门禁 / 登录界面 / 正版绑定 / 继承绑定等)docs/adr/0001~0008(虚拟铁砧门禁、离线正版检测、OneBot 11、登录界面分层、登录凭证、固定账户键、名字冲突、快捷登录信任模型)CLAUDE.md(worktree 隔离、影响面验证、按票据提交、并发上限等)core/src/main/java/dev/nmouzh/openqqauth/
├── account/ # 账户模型、SQLite 仓储
├── anvil/ # 铁砧窗口状态机(UI 无关核心)
├── api/ # 只读查询 API(供 Paper 插件)
├── bedrock/ # 基岩支持(表单发送、绑定流程)
├── configuration/# 配置模型(Configurate)
├── event/ # 领域事件总线(SimpleDomainEventBus)
├── gate/ # 登录判定管线 LoginPipeline、会话、锁定、快捷登录
├── i18n/ # TranslationKey 枚举 + 中英双语资源
├── mojang/ # Mojang API 客户端(名字→UUID、hasJoined)
├── onebot/ # OneBot 11 客户端(WebSocket 消息收发)
├── password/ # 密码哈希(jBCrypt)
├── qq/ # QQ 域:绑定/重置/解绑状态机、群命令、审计日志、自愿移交
├── token/ # 登录凭证:签发/吊销/校验、传输协议、mod 通道
├── util/ # 工具类
└── verify/ # 验证码服务
Q:提示"机器人离线"无法绑定?
A:新玩家绑定前置检查机器人在线状态(BotOnlineProvider),机器人离线时绑定类操作降级为提示并踢出。确认 OneBot 已连接(reconnect 可重连)。
Q:1.12.2 等旧版本客户端无法登录?
A:铁砧协议与物品序列化已按协议族参数化支持旧版族(1.7.21.12.2,理论下限;1.12.2 承诺可用)。1.13 族内更早子版本与 1.7.21.12.1 的包 ID 漂移按"理论下限不承诺"处理;真实 Velocity 连接接线(内部 MinecraftConnection 桥接)为独立后续票据。
Q:凭证校验失败会怎样? A:不影响密码登录路径——校验失败仅记录日志,玩家回到密码输入界面,可正常用密码登录。
Q:如何让其他插件读取账户信息?
A:Paper 端经 Bukkit ServicesManager 获取 ReadOnlyAuthApi(账户/会话查询),并可订阅领域事件(PlayerAuthenticatedEvent 等)。集成示例见 bootstrap/paper 的 PaperAuthEvents。
Q:数据存储在哪里?
A:默认 SQLite 文件 openqqauth.db(storage.sqlite-file 可改路径)。
Q:名字冲突如何处理?
A:遵循 ADR-0007"过去先到先得、未来正版优先":冲突双方可走自愿移交(原主解绑 → 管理员 transfer confirm 确认 → 目标接管),系统不提供强制夺权路径。
本项目采用 CC0 1.0 Universal 许可,你可按需自由使用(包括修改许可用于自己的项目)。