跳到主要内容

代理网络(BungeeCord / Waterfall / Velocity)

ResourcePackManager 可以运行在代理网络上。只有一个 jarResourcePackManager.jar — 你在每个后端以及代理上安装的都是同一个 jar。在后端上它以后端角色运行(合并、托管、推送、转换);在 Velocity 或 BungeeCord/Waterfall 代理上,同一个 jar 会自动检测平台加载器并以代理角色运行(网络侧的基岩版分发)。两种角色会通过共享的 plugins/floodgate/key.pem 文件自动发现彼此——没有单独的代理 jar,没有需要解压的 proxy-extension,也没有需要粘贴的密钥。

本页中“代理插件”是对这个以代理角色运行的同一个 ResourcePackManager.jar 的简称。

代理插件的职责

代理插件的工作是基岩版资源包的合并与分发。在拥有多个后端的网络中,每个后端会生成自己的基岩版资源包(其合并后的 Java 资源包的转换版本)。代理插件会:

  1. 每 5 秒轮询一次每个后端的小型 HTTP 服务器上的 /bedrock.zip/mappings.json,使用 If-Modified-Since,因此未变化的文件几乎不消耗带宽。每个后端都会公告它实际绑定的确切 HTTP 端口,所以代理通常会自动命中正确的端口(参见 后端 HTTP 端口解析)。
  2. 等待收件箱状态稳定——一旦相邻两次轮询观察到相同的文件哈希集合,它就会立即合并。
  3. 将每个后端的基岩版资源包合并为一个全网络统一的资源包。
  4. 把合并后的 Geyser 自定义映射文件复制到代理上的 plugins/Geyser-*/custom_mappings/
  5. 在基岩版客户端接入时通过 Geyser 的 SessionLoadResourcePacksEvent 分发合并后的资源包。

**代理插件只对基岩版玩家有用。**网络上 Java 资源包的分发仍由各后端通过常规的 setResourcePack / addResourcePack API 完成——Java 客户端看到的是各自所在后端选择发送的资源包。如果你的网络只面向 Java 玩家,根本用不上代理插件。

安装 — 两步走

第 1 步:在代理和每个后端上都安装 Floodgate

Floodgate 是基岩版玩家在代理上完成认证所必需的。RSPM 借用 Floodgate 的 plugins/floodgate/key.pem 来派生网络身份——该文件必须在代理和每个后端上逐字节一致。Floodgate 本身就要求这一点用于基岩版认证,所以如果基岩版玩家目前能在你的网络中正常工作,这一步其实已经完成了。

如果你还没装 Floodgate,请在每个组件上都安装它,然后把一份规范的 key.pem 复制到其余每个组件,再继续下一步。

第 2 步:把 ResourcePackManager.jar 复制到代理

只有一个 jar。你在 Bukkit/Paper 后端上安装的同一个 ResourcePackManager.jar 也就是代理插件——它把 Velocity 和 BungeeCord/Waterfall 的实现一并打进一个 shaded jar,并自动检测自己运行在哪个平台上。没有单独的、按平台区分的代理 jar 需要解压。

把同一个 ResourcePackManager.jar 复制到你代理的 plugins/ 文件夹:

代理软件使用此 jar
VelocityResourcePackManager.jar
BungeeCordResourcePackManager.jar
Waterfall(Bungee 分支)ResourcePackManager.jar

你随时可以在后端运行 /rspm status 来确认这一点;其中的 Proxy deployment 部分会打印 Network proxy jar: ResourcePackManager.jar 以及 Use the same jar on Bukkit/Paper, Velocity, and BungeeCord/Waterfall.

重启代理。就这么简单。

故意不留任何需要编辑的配置项、也不需要粘贴密钥。代理插件会在启动时读取代理上的 plugins/floodgate/key.pem 并从中派生网络身份。由于 Floodgate 本身就要求该文件在每个后端与代理上一致,派生出的密钥自动与每个后端的匹配。

代理的首次轮询会在启动约 2 秒后触发,之后每 5 秒一次。结合单周期稳定性门控,在代理至少能看到一个已经在生产内容的后端之后,首次合并大约会在 7 秒后发布。

验证是否工作正常

代理控制台

重启代理大约 10 秒内(假设后端正在运行),你应能看到:

[ResourcePackManager] Network-key auto-derived from Floodgate key.pem ✓
[ResourcePackManager] NetworkSync starting (poll interval 5000 ms, network-http-offset 1 - endpoint announcements preferred, fallback HTTP port = mcPort + offset)
[ResourcePackManager] NetworkSync: inbox stabilized — merging 2 Bedrock zip(s) and 2 mappings file(s) across 2 backend(s).
[ResourcePackManager] Merged Bedrock pack published at .../merged/Bedrock.zip (sha1=...).
[ResourcePackManager] ✔ Network resource pack is now ready (... KB, sha1 ABCD1234)

在代理上运行 /rspm status

打印一份快照:后端列表、各后端各路径的拉取结果(200 / 304 / 404 / CONNECT_FAILED)、连续空轮询计数器、当前合并资源包路径与大小、network-http-offset,以及代理上是否检测到 Floodgate / Geyser。需要 resourcepackmanager.command.statusresourcepackmanager.* 权限。控制台总是同时拥有两者;若希望玩家也能运行,请通过你的权限插件授予其一。输出不会泄露任何机密(网络密钥会被遮蔽,没有任何认证令牌),所以可以放心宽松授权。

在后端上运行 /rspm status

Deploy mode 一行应当显示 network-backendNetwork key 一行应显示遮蔽后的密钥(只露出最后 4 个字符)——把它与代理上遮蔽后的密钥对比,确认两端一致。

基岩版客户端

用基岩版客户端连接。你应当在进入世界之前看到资源包下载提示。自定义物品会显示为其应有的模型,而不是普通的盔甲架。

配置项参考

后端 plugins/ResourcePackManager/config.yml

网络模式是自动检测的——没有什么 networkMode: true 开关需要设置。检测信号(任一即可):

  1. 存在 Floodgate,但不存在 Geyser-Spigot — 针对基岩版-经由代理场景最强的信号。
  2. spigot.yml: settings.bungeecord: true — 旧式 BungeeCord / Waterfall 的 IP 转发开关。
  3. paper-global.yml: proxies.velocity.enabled: true — 现代 Velocity 转发。

针对网络模式真正有意义的唯一旋钮是 networkHttpOffset-v2,它控制代理将在每个后端轮询的回退 HTTP 端口(即代理在某个后端尚未公告其实际绑定端口之前所猜测的端口)。默认值 1 在几乎所有托管环境下都能用。完整的端口解析说明请参阅 Self-hosting

在正常运行中,每个后端都会自动把它真实的 HTTP 端口公告给代理(通过 magmaguy.com 端点注册表),所以该偏移仅在启动/失败时作为回退被参考。参见下文的 后端 HTTP 端口解析

代理 plugins/ResourcePackManager/config.yml

代理插件在首次启动时会写入一份最简默认配置:

# 强制客户端接受资源包(拒绝则踢出)。默认:false。
force-resource-pack: false

# 回退偏移:在某个后端尚未公告其真实的 ResourcePackManager HTTP 端口之前,
# 该代理会把这个偏移加到该后端的 Minecraft 端口上,以推导出它将访问
# /bedrock.zip 与 /mappings.json 的 HTTP 端口。默认 1。
# 正常运行中后端会公告它实际绑定的确切端口,所以这个值仅在启动时或公告
# 失败时才会被用到——但一旦被用到,它应当与每个后端的 networkHttpOffset-v2 一致。
network-http-offset-v2: 1

故意不提供 network-key 条目——该条目在发布前就已被取消,因为手动粘贴是配置错误的主要来源(拼写错误会悄无声息地破坏 proxy↔backend 链接)。密钥会从 plugins/floodgate/key.pem 自动派生。

后端 HTTP 端口解析

代理需要知道在每个后端上轮询 /bedrock.zip/mappings.json 时该用哪个 HTTP 端口。它按以下顺序解析该端口:

  1. 后端公告的端点(优先)。 每个后端会把它实际绑定的确切 HTTP 端口上传到 magmaguy.com 端点注册表,以网络密钥为键。每次轮询时代理会刷新这份列表,并通过 Minecraft 端口(以及可用时的主机名)把某个后端公告的端口与服务器列表条目匹配起来。这意味着无论管理员在某个后端上显式设置了 selfHostPort,还是该后端自动落在 mcPort + 1 上,处理方式都完全相同——代理使用后端实际绑定的端口。
  2. mcPort + network-http-offset-v2(回退)。 仅在没有匹配的公告可用时使用(例如任何后端公告之前的第一次轮询,或端点注册表短暂不可达时)。这就是为什么如果你依赖回退,两端的偏移仍应保持一致。

代理特意把端口扫描后端作为回退手段——那在托管商看来像是滥用行为。当直连拉取根本无法工作时,中继路径(见下文)才是根本性的解决办法。

代理上的 /rspm status 会针对每个后端显示选用了哪个端口,以及它是来自公告还是来自偏移回退。

稳定性与合并节奏

代理在合并前会等待收件箱状态稳定:第一次轮询确定基线文件哈希集合,下一次观察到相同集合的轮询会触发合并(单周期稳定性门控)。在约 2 秒的初始延迟和 5 秒轮询间隔下,这意味着当代理至少能看到一个后端在生产内容之后,首次合并大约会在 7 秒后发生。后续只有在收件箱文件的 SHA-1 集合发生变化时才会重新打包,所以长时间静默几乎零开销。

后端会把它们的 bedrock.zip 写入一个临时文件,然后原子性地重命名,因此 /bedrock.zip 路由始终提供一个完整的 zip——代理永远不必防范读到写了一半的文件,这也是门控只需单周期而非两周期的原因。

直连拉取 vs 中继回退

默认路径是直连拉取:代理对每个后端发起 http://<backend-host>:<mcPort + offset><path> 的 HTTP GET。

如果代理无法直接访问某个后端的 HTTP 端口(在共享 / 托管 Minecraft 服务上很常见,MC 端口对外开放但相邻端口被防火墙屏蔽),后端会在网络命名空间(由 Floodgate 密钥派生)下把 bedrock.zipmappings.json 推送到 magmaguy.com 上的中继端点。当直连拉取硬性失败时,代理会列出并从中继下载。

两条路径最终都汇入同一个合并步骤,因此运维人员无需在两者之间做选择——优先使用直连拉取(对 magmaguy.com 带宽成本为零),需要时中继会透明启用。

中继在服务端有 30 分钟的 TTL。后端每 25 分钟推送一次以保持条目存活;正常关闭会立即丢弃条目,而不必等待 TTL 过期。

常见问题排查

启动时报 "Floodgate key.pem missing"

代理插件找不到 plugins/floodgate/key.pem,进入空转状态。没有它 RSPM 无法链接任何后端。

修复方法:在代理上安装 Floodgate,然后确保代理上的 plugins/floodgate/key.pem 与每个后端上的同名文件逐字节一致。Floodgate 默认会为每次安装自动生成不同的密钥——把任意后端上的一份规范 key.pem 复制到所有其他组件上,再重启所有节点。

大约 20 秒后出现 "No merged pack content" 警告

在连续 4 轮空轮询之后,代理会一次性记录一条多行警告,列出它轮询过的每个后端、尝试访问的 URL,以及结果。警告会解释最常见的修复方法:

  • 每个后端都返回 CONNECT_FAILED — 代理根本无法访问后端 HTTP 端口。检查 velocity.toml / config.yml 中的地址是不是代理真正能访问到的(而不是诸如 Docker 内部名之类、从代理网络解析不到的地址),并确认代理与后端之间后端的 HTTP 端口是放通的。警告会针对每个后端打印它尝试访问的确切 HTTP host:port,以及该端口是来自后端的公告还是来自 mcPort + networkHttpOffset-v2 回退。如果你完全没有办法放通该端口(托管型服务),请参阅上文的中继回退一节——后端应当会自动上传到中继。
  • 每个后端都返回 NOT_FOUND_404 — 后端已就绪但没有生成基岩版资源包。在每个后端运行 /rspm status;Bedrock Pack 诊断块会告诉你原因(最常见的是:合并后的资源包里没有物品定义,或第一次合并周期还没完成)。

该警告每个卡住期只触发一次。至少有一个后端重新开始返回内容时,会记录一行 NetworkSync: recovered

第一次启动代理时基岩版玩家看不到任何自定义模型

Geyser 只在代理启动时注册其自定义物品表。如果代理在任何后端生成基岩版资源包之前就启动了,Geyser 就会带着空的映射表运行,并在整个会话期间保持空表。

修复方法:在后端日志中出现第一行 Merged Bedrock pack published 之后,重启一次代理。RSPM 会在每次代理启动时预先部署上一次运行的映射,所以这种情况只会在全新安装时碰到一次——后续启动时 Geyser 扫描前总会有可用的映射就位。

代理启动时报 "Duplicate bedrock_identifier" 警告

两个后端为同一个基础物品发出了相同的基岩版标识符。会采用最后写入者胜出的策略;如果只需要一个后端提供该物品,无害。如果两个后端确实要在同一个基础物品下托管不同的自定义物品,请重命名其中一个源 Java 模型,使自动生成的哈希值不同。

基岩版玩家已连接但看不到资源包

当某个基岩版会话加载但没有可用的 RSPM 资源包时,代理会向所有在线 Java 玩家发出聊天横幅:

⚠ [RSPM] Bedrock player Alice connected before the resource pack was ready — they're seeing plain armor stands instead of custom models. Tell them to disconnect and reconnect; the pack will load on their next session. (Cause: ...)

基岩版玩家本人也会收到一个模态弹窗,代理控制台也会出现一条横幅。如果需要进一步排查,可启用调试日志流(Velocity 与 BungeeCord 都支持):

/rspm debug bedrock on

这会打开 GeyserBinder 输出的详细 [RSPM-BedrockDebug] 日志行。复现问题后,再关闭它:

/rspm debug bedrock off

该设置在代理重启时会重置为关闭,避免被意外保持开启。

在网络上更新 RSPM

升级后端 RSPM jar 后,也请把同一个 ResourcePackManager.jar 重新复制到代理的 plugins/ 文件夹并重启代理。每个后端与代理用的都是同一个 jar,所以请让所有组件保持相同版本。

目前尚未支持的内容

  • 通过代理插件在网络上分发 Java 资源包。 Java 客户端通过常规 API 直接从各后端接收资源包。代理侧没有 Java 资源包混合器。
  • 跨后端的 Java 资源包合并。 每个后端的 Java 资源包是独立的。玩家切换后端时会收到新后端的资源包。
  • 实时重新配置网络密钥。 密钥绑定到 Floodgate 的 key.pem。更改它需要重启代理每个后端(反正轮换 Floodgate 密钥时本来就要这么做)。