| .github/workflows | ||
| common | ||
| gradle/wrapper | ||
| minecraft-adapter | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| build.gradle | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| icon.svg | ||
| LICENSE | ||
| README.md | ||
| settings.gradle | ||
Discord-MC-Chat (DMCC) 重构设计文档
1. 项目概述
Discord-MC-Chat (DMCC) 是一个 Minecraft 模组,旨在为 Discord 和 Minecraft 服务器之间建立一个功能强大、可高度定制的双向通信桥梁。
本次重构的核心目标是实现一个统一的、基于“服务端-客户端 (Server-Client)”的通信架构。在此架构下,所有模式都将复用同一套核心逻辑,以达到最大程度的代码复用和架构一致性。
项目初期将优先实现对 NeoForge 1.21.10 的兼容。但为了未来能够无缝支持 Fabric,整体架构设计依然严格遵循平台无关原则,所有核心代码中不得含有任何启动器专属的调用,仅通过 Mixin 进行注入。
2. 核心功能需求
2.1 通信功能
- 双向消息转发: 在 Discord 和 Minecraft 之间实时转发聊天消息。
- 格式兼容: 支持 Markdown、Discord 表情符号、提及和超链接在两个平台间的自动转换。
- Webhook 支持: 可选通过 Webhook 以玩家头像发送 Minecraft 消息到 Discord。
- 自定义格式: 允许用户高度自定义所有消息的显示格式。
2.2 事件通知
- 玩家事件: 玩家加入/离开服务器、死亡、获得进度/成就。
- 服务器事件: 服务器启动/关闭。
- 性能监控: 当服务器 MSPT (每 tick 毫秒数) 超过阈值时,在 Discord 发出警告。
2.3 管理功能
- 通过 Discord 查询服务器状态(TPS, MSPT, 在线玩家等)。
- 通过 Discord 执行 Minecraft 控制台命令。
- 通过 Discord 管理白名单。
- 通过 Discord 查看和过滤服务器日志。
- 通过 Discord 重载 DMCC 配置文件。
- 通过 Discord 远程启动/关闭子服务器(仅限多服务器模式)。
2.4 账户链接功能
- 身份绑定: 支持将 Minecraft 玩家账户与 Discord 账户进行一对一关联。
- 角色颜色同步: 游戏内聊天消息显示与玩家 Discord 角色的颜色一致。
- 跨平台提及: 在 Discord 中
@用户时,对应的 Minecraft 玩家会收到游戏内提醒。 - 权限同步: 可选基于 Discord 角色自动授予玩家游戏内的 OP 权限。
3. 系统架构
3.1 统一的“服务端-客户端 (Server-Client)”架构
DMCC 所有运行模式都基于一个统一的通信模型,该模型包含两个核心组件:
- 服务端 (Server): 整个系统的“大脑”。它作为后台服务运行,是唯一负责与 Discord API (通过 JDA) 直接通信的组件。它处理所有核心逻辑,如消息格式化、命令解析和权限验证。此组件在任何情况下都不得包含任何
net.minecraft的导入(反射除外),以确保其可以在没有 Minecraft 环境的情况下独立运行。 - 客户端 (Client): 部署在每个 Minecraft 服务器上的“触手”。它作为 Minecraft 模组运行,负责捕获游戏内的所有事件,并将其发送给 服务端 (Server)。同时,它也接收并执行来自 服务端 (Server) 的指令。
两者之间通过基于 Netty 的 TCP 协议进行通信,使用 JSON 对数据包进行序列化和反序列化。
3.2 运行模式与部署
DMCC 支持三种运行模式,它们是统一架构的不同部署方式:
-
单体服务器模式 (
single_server):- 在此模式下,DMCC 在后台同时启动一个内部服务端和一个内部客户端。内部客户端自动通过本地回环地址 (localhost) 连接到内部服务端。
- 这是为单个 Minecraft 服务器提供的开箱即用的解决方案。
- 支持停止 DMCC 自身的命令,但不支持管理子服务器。
-
多服务器-客户端模式 (
multi_server_client):- 在此模式下,DMCC 只启动一个客户端。
- 此客户端会连接到一个外部独立运行的服务端。
- 用于将多个 Minecraft 服务器连接到一个中央服务端。
-
独立模式 (
standalone):- 在此模式下,DMCC 只启动一个服务端。
- 此服务端会监听一个网络端口,等待一个或多个外部的客户端连接。
- 作为多服务器架构的中央“大脑”而存在,提供最强的稳定性和隔离性。
- 支持管理子服务器的命令(如
/start <server>,/stop <server>)以及停止自身进程的命令。
3.3 配置文件策略
为了降低用户心智负担并保证配置的准确性,采用两步配置流程:
mode.yml: 在 Minecraft 环境中,用户首先在此文件选择一种运行模式。DMCC 会在启动时检查此文件。若在非 Minecraft 环境下直接运行 JAR,则自动认定为standalone模式。config.yml: DMCC 会根据mode.yml中选择的模式,从内部模板生成一份对应的config.yml。此配置文件将被严格验证(版本、结构、数据类型),其注释会清晰地解释所有配置项。
4. 模块化设计
项目在物理上划分为两个 Gradle 子项目,最终合并为一个 JAR 文件进行分发。
4.1 通用模块 (:common)
此模块是项目的核心,完全不依赖 Minecraft。它包含了服务端、网络客户端框架、以及所有共享代码。
- 网络框架 (Netty):
- 服务端:
ServerDMCC,NettyServer,ServerChannelInitializer负责监听连接和处理入站数据。 - 客户端:
ClientDMCC,NettyClient,ClientChannelInitializer负责建立和维持与服务端的连接。 - 协议: 定义了
Packet接口和具体的数据包(如PlayerChatPacket),并使用JsonPacketEncoder/Decoder进行 JSON 序列化。
- 服务端:
- Discord 集成 (
DiscordManager):- 初始化并管理 JDA 实例,监听 Discord 事件(消息、命令)。
- 处理所有与 Discord API 的底层交互。
- 命令系统 (
CommandManager,CommandEventHandler):- 提供一个统一的命令处理入口,支持来自 Discord、游戏内和独立终端的命令。
- 通过
CommandEvents进行解耦。
- 配置与国际化:
ConfigManager,ModeManager: 提供健壮的配置加载和验证机制。I18nManager: 支持从本地和网络加载语言文件,并提供统一的翻译接口。
- 日志系统 (
LoggerImpl,ServiceProvider):- 实现了 SLF4J
ServiceProvider,可在独立运行时输出到文件和控制台,在 Minecraft 环境中则桥接到游戏日志系统。
- 实现了 SLF4J
- 事件总线 (
EventManager):- 提供一个轻量级的发布-订阅事件总线,用于项目内部各组件的解耦。
4.2 Minecraft 适配器模块 (:minecraft-adapter)
此模块是连接 :common 模块与 Minecraft 的桥梁,包含了所有与 Minecraft 相关的代码。
- 模组入口 (
NeoForgeDMCC): 作为 NeoForge 模组的入口点,调用DMCC.init()启动程序。 - 事件捕获 (Mixins):
- 通过一系列 Mixin (
MixinPlayerList,MixinServerGamePacketListenerImpl,MixinMinecraftServer等) 注入 Minecraft,以非侵入式的方式捕获游戏事件。
- 通过一系列 Mixin (
- 事件发布与处理:
- Mixin 捕获到事件后,通过
EventManager.post()发布一个MinecraftEvents中的具体事件。 MinecraftEventHandler订阅这些事件,并将事件数据打包通过网络客户端发送给服务端。
- Mixin 捕获到事件后,通过
- 服务提供者 (
MinecraftServiceImpl):- 实现了
MinecraftService接口,通过 JavaServiceLoader机制被ClientDMCC在运行时发现和调用,实现了与 Minecraft 的完全解耦。
- 实现了
5. 关键设计详解
5.1 权限管理模型 (双轨制)
DMCC 采用一个灵活的双轨权限模型来确定谁是“DMCC 管理员”。
-
路径一:原生继承模型 (Minecraft -> DMCC)
- 来源: 玩家在 Minecraft 中的 OP 等级。
- 运作方式: 在
config.yml中定义dmcc_admin.minecraft_op_level_requirement。任何在游戏中拥有等于或高于此 OP 等级的玩家,都将自动被视为“DMCC 管理员”。 - 目的: 这是成为 DMCC 管理员的基础方式。若 Discord 用户想使用管理命令,其链接的 MC 账户必须满足此要求。
-
路径二:角色同步模型 (Discord -> Minecraft)
- 来源: 用户在 Discord 中的角色。
- 运作方式: 这是一个可选功能。用户可在配置中定义一个 Discord 角色到游戏 OP 等级的映射。服务端模块会周期性地检查已链接用户的角色,并通过向客户端发送指令来自动授予或撤销其在游戏中的 OP 权限。
- 协同作用: 一旦一个玩家通过此路径被授予了足够的 OP 等级,他也会因为路径一的规则而自动成为“DMCC 管理员”。
5.2 账户链接流程
- 发起: 玩家在游戏中执行
/dmcc link命令。 - 生成: 客户端模块生成一个有时效性的一次性链接码,并通知服务端该验证码与当前玩家的 UUID 关联。
- 验证: 玩家在 Discord 中对机器人使用
/link <code>命令。 - 确认: 服务端模块验证链接码是否有效、未过期。验证成功后,将玩家的
Minecraft UUID和Discord User ID保存到持久化存储中(如linked_accounts.json),并通知用户链接成功。
5.3 数据流示例 (Minecraft -> Discord)
- [minecraft-adapter]
MixinServerGamePacketListenerImpl捕获玩家 "Xujiayao" 的聊天事件,消息为 "Hello World"。 - [minecraft-adapter]
EventManager发布一个MinecraftEvents.PlayerChat事件。 - [minecraft-adapter]
MinecraftEventHandler订阅此事件,并从事件中提取数据。 - [common: Client]
NettyClient将数据(玩家名、消息内容等)封装成一个PlayerChatPacket。 - [common: Client]
JsonPacketEncoder将PlayerChatPacket序列化为 JSON 字符串,通过 Netty 发送给 服务端。 - [common: Server]
NettyServer接收到数据,JsonPacketDecoder将其反序列化为PlayerChatPacket对象。 - [common: Server]
ServerBusinessHandler处理此数据包,检查该玩家是否已链接账户,获取其 Discord 角色颜色等信息。 - [common: Server] 根据
config.yml和custom_messages中的模板,生成最终要发送到 Discord 的字符串。 - [common: Server]
DiscordManager通过 JDA 将格式化后的消息发送到指定的 Discord 频道。