跳到主要内容

RhythMC-Reborn 网络架构文档

目录

  1. 架构概述
  2. 核心组件
  3. 通信协议
  4. 安全机制
  5. 流程图

架构概述

RhythMC-Reborn 采用 双通道通信架构,结合 HTTP/2 和 WebSocket 实现高效可靠的网络通信:

设计原则

原则描述
安全优先/server/login 使用 bootstrap Bearer 建立服务器身份,后续业务接口使用短期 access token
异步非阻塞所有网络操作使用 CompletableFuture
自动重连WebSocket 支持指数退避重连
资源完整性优先使用 SHA256 校验,缺失时回退 SHA1
短期令牌刷新serverAccessToken 10 分钟有效,WS 掉线后优先刷新
离线容错网络故障时自动降级为离线模式

核心组件

1. NetworkManager (网络管理器)

位置: cn.frkovo.rhythmcv2.Network.NetworkManager

职责: 网络模块的总入口,协调所有网络组件

核心字段:

字段类型描述
okHttpClientOkHttpClientHTTP/WebSocket 共享客户端
httpClientHttpClientHTTP 请求封装
webSocketClientWebSocketClientWebSocket 连接管理
serverSessionServerSession服务器会话状态
rivalUpdateManagerRivalUpdateManager对手同步管理
resourceIntegrityManagerResourceIntegrityManager资源完整性管理

生命周期:

NetworkManager 登录成功后,会把资源完整性校验、收藏品同步、ResourcePackManager.init() 远程资源包列表加载并行执行;三者全部成功才进入在线模式。资源包列表现在由 GET /resources/packmanifest 直接返回 urlsize 字段,插件不再额外请求单独的资源包 URL 接口;账户设置中的资源包菜单会使用这些元数据展示 FULL 包和各 Chapter 包的可读大小。若服务器登录第一步失败,或后续任一初始化任务失败,则会先注册 ResourcePackManager 的本地 song-pack fallback,再切换到离线模式。


2. HttpClient (HTTP客户端)

位置: cn.frkovo.rhythmcv2.Network.HttpClient

职责: 封装 OkHttp 提供异步 HTTP 请求

支持的方法:

方法返回类型描述
get(url)CompletableFuture<String>GET 请求
post(url, jsonBody)CompletableFuture<String>POST JSON 请求
postWithStatus(url, jsonBody)CompletableFuture<HttpResult>POST 并返回状态码
download(url, dest, progress)CompletableFuture<Path>文件下载(支持进度回调)

认证: NetworkManager/server/login 使用 Authorization: Bearer <serverBootstrapToken> 完成服务器登录。登录成功后,仅对受保护后端接口自动注入 Authorization: Bearer <serverAccessToken>;Mojang API、资源下载直链与外部 CDN 请求不会携带该头。

令牌生命周期: serverAccessToken 为 10 分钟短期令牌。NetworkManager 在 WebSocket 非预期断开后调用 /server/refresh 获取新的 accessToken;若刷新失败,则使本地 token 失效并执行完整重登录。


3. WebSocketClient (WebSocket客户端)

位置: cn.frkovo.rhythmcv2.Network.WebSocketClient

职责: 管理实时双向通信

特性:

  • 自动重连: 支持指数退避重连策略
  • 消息分发: 基于监听器模式的消息分发
  • 状态管理: 维护连接状态 (OFFLINE/CONNECTING/ONLINE/LAGGING)
  • Bearer 鉴权: 握手请求携带 Authorization: Bearer <serverAccessToken>
  • 断线恢复: 瞬时断链时持续重连 WebSocket;仅在握手返回 401/403/server/refresh 失败后才整套重新登录

重连策略:

重连延迟计算: delay = reconnectDelayMs * 2^min(retryCount, maxRetry - 1),达到退避上限后继续按该上限间隔重试,不会仅因 WebSocket 中断直接进入离线模式。


4. ServerSession (服务器会话)

位置: cn.frkovo.rhythmcv2.Network.ServerSession

职责: 存储服务器连接状态信息

字段:

字段类型描述
sessionIDString本地运行时标识
serverIDint服务器在远程的注册ID
serverNameString服务器名称
assetServerString资源服务器地址
accessTokenString短期 Bearer 令牌(登录响应后赋值)
wsServerStringWebSocket服务器地址
statusNetworkStatus网络状态

通信协议

双通道设计

通道协议用途特点
HTTP通道HTTP/2 + JSON登录、资源下载、数据上传可靠、有序、支持重试
WebSocket通道WebSocket + JSON实时游戏同步低延迟、双向、实时

安全机制

服务器登录与运行时 Bearer

登录配置:

配置项
传输协议HTTPS (TLSv1.3)
登录凭证net.server-login-token
发送方式/server/login 请求头中的 Authorization: Bearer <serverBootstrapToken>
后续鉴权Authorization: Bearer <serverAccessToken>

作用范围: bootstrap token 仅用于 /server/login 阶段,完成服务器身份建立。登录成功后的业务请求依赖短期 Bearer access token;资源下载与第三方接口不复用 bootstrap token。

配置要求:

# config.yml
net:
server-login-token: "eyJhbGciOiJIUzI1NiJ9..."

流程图

整体初始化流程

掉线恢复流程

登录认证流程

WebSocket 消息流程

离线模式切换流程


配置说明

必需配置项

net:
# 游戏服务器地址
game-server: "https://api.rhythmc.example.com"

# WebSocket重连配置
max-retry: 5
reconnect-delay-ms: 1000

# 服务器 bootstrap token
server-login-token: "eyJhbGciOiJIUzI1NiJ9..."

# 资源包回退配置
resource-pack-fallback:
url: "https://fallback.rhythmc.example.com/pack.zip"
auth-type: "token"
token: "your-token"

网络状态枚举

NetworkStatus

状态显示描述
OFFLINE🔴离线模式
CONNECTING🟡连接中
ONLINE🟢在线
LAGGING🟠延迟较高

PlayerNetStatus

状态描述
OFFLINE离线模式 (不上传数据)
LOGIN登录中
CONNECTED_OFFLINE盗版登录
CONNECTED_ONLINE正版登录

2026-03-16 Update: Active Chart Catalog

NetworkManager.initialize() now includes one more authenticated bootstrap request:

  • GET /server/charts

The startup pipeline now treats the following as parallel initialization tasks after /server/login succeeds:

  • resource integrity verification
  • /server/collections
  • remote resource pack manifest loading
  • /server/charts

The chart-directory response is converted into an ActiveChartCatalog and stored in ConfigManager.

Runtime effect:

  • if the catalog is unavailable, the client keeps the old behavior and loads every local chart under Data/Charts
  • if the catalog is available, RawSongDeserializer only loads songs and difficulty slots that are marked active by the backend

This keeps the backend focused on active chart metadata only. Manifest-heavy fields stay in local chart files after resource sync.

See also: