代理网络(BungeeCord / Velocity)
ResourcePackManager 可以运行在代理网络上。请在代理和每个提供资源包的后端安装同一个 ResourcePackManager.jar。其他已注册服务器可以不安装 RSPM。在后端,它会合并、托管、分发和转换资源包。在 Velocity 或 BungeeCord 上,jar 会检测代理平台并处理全网络的基岩版分发。代理持有网络密钥,并在玩家首次连接到各后端时将密钥发送给它。
本页中“代理插件”是对这个以代理角色运行的同一个 ResourcePackManager.jar 的简称。
代理插件的职责
代理插件的工作是基岩版资源包的合并与分发。在拥有多个后端的网络中,每个后端会生成自己的基岩版资源包(其合并后的 Java 资源包的转换版本)。代理插件会:
- 发现哪些已注册后端运行 RSPM,然后每 5 秒轮询这些参与后端的
/bedrock.zip和/mappings.json。优先使用强 ETag 配合If-None-Match,同时保留If-Modified-Since以兼容旧后端。未变化的文件返回304。每个后端会公告实际绑定的 HTTP 端口,因此代理通常自动使用该端口。参见后端 HTTP 端口解析。 - 等待收件箱状态稳定——一旦相邻两次轮询观察到相同的文件哈希集合,它就会立即合并。
- 将每个后端的基岩版资源包合并为一个全网络统一的资源包。
- 当存在物品映射时,把合并后的 Geyser 自定义映射文件复制到代理上的
plugins/Geyser-*/custom_mappings/。 - 在基岩版客户端接入时通过 Geyser 的
SessionLoadResourcePacksEvent分发合并后的资源包。
网络上的 Java 资源包由各后端通过常规 setResourcePack / addResourcePack API 分发。除了合并基岩版资源包,代理角色还负责网络密钥配置和经过认证的 RSPM 更新传播。纯 Java 网络分发 Java 资源包时不需要代理角色。
安装
Floodgate
Floodgate 允许基岩版玩家在没有付费 Java 版账号的情况下认证。Geyser 也支持使用 Java 账号进行在线认证;请根据所选认证方式遵循 Geyser 安装指南。RSPM 可以在没有 Floodgate 的情况下连接代理和后端。
如果代理首次启动 RSPM 时已安装 Floodgate,RSPM 会从 plugins/floodgate/key.pem 派生网络密钥,以保留现有网络的身份。后续启动会使用 RSPM 自己的 network-key 文件,只要其中的密钥仍然有效。如果保存的密钥缺失或无效,RSPM 会再次尝试从 Floodgate 派生,然后才生成随机密钥。
把 ResourcePackManager.jar 复制到代理
只有一个 jar。你在 Bukkit/Paper 后端上安装的同一个 ResourcePackManager.jar 也就是代理插件——它把 Velocity 和 BungeeCord 的实现一并打进一个 shaded jar,并自动检测自己运行在哪个平台上。没有单独的、按平台区分的代理 jar 需要解压。
如果你已经启动后端但尚未在代理安装 RSPM,无须重新寻找下载链接:代理后的每个无密钥后端都会在 plugins/ResourcePackManager/proxy-extension/ResourcePackManager.jar 暂存与自身 jar 逐字节相同的副本,并在控制台打印确切路径。复制该文件会安装这个后端当前运行的版本;请同时更新其他后端,使整个网络版本一致。
把同一个 ResourcePackManager.jar 复制到你代理的 plugins/ 文件夹:
| 代理软件 | 使用此 jar |
|---|---|
| Velocity | ResourcePackManager.jar |
| BungeeCord | ResourcePackManager.jar |
你随时可以在后端运行 /rspm status 来确认这一点;其中的 Proxy deployment 部分会打印 Network proxy jar: ResourcePackManager.jar 以及 Use the same jar on Bukkit/Paper, Velocity, and BungeeCord.
重启代理。就这么简单。
没有任何必须编辑的配置项,也没有需要粘贴的密钥。代理会在启动时自行建立网络密钥,并自动把它下发给每个后端——参见下文的 代理与后端如何建立链接。生成的代理 config.yml 只包含两项可选设置,两者都会在后文说明。
代理的首次轮询会在启动约 2 秒后触发,之后每 5 秒一次。结合单周期稳定性门控,在代理至少能看到一个已经在生产内容的后端之后,首次合并大约会在 7 秒后发布。
后端发现
代理会检查已注册服务器是否运行 RSPM,而不会让资源包同步等待未运行 RSPM 的服务器。端点公告和先前已验证的缓存内容可以立即确认参与者。否则,发现过程会在后台检查解析出的 HTTP 端点,最多同时进行两项检查,超时为五秒。未确认服务器会在约一分钟后再次检查。
/rspm status 会列出已确认参与者数量以及其他各服务器的发现状态。RSPM not confirmed 表示发现过程尚未确认 RSPM 存在,并不能证明插件不存在。如果服务器应当参与,请检查后端地址、HTTP 端口和可达性。在其他后端安装 RSPM 后,代理会自动发现它。
后端一旦确认,连接失败会报告为该参与者刷新失败。已提交且可用的内容会保留,直接获取和中继结果仍可在 /rspm status 中查看。空轮询计数为零表示有内容可用,并不表示每个后端连接都正常。
发现过程不授予更新权限。插件自动更新仍需要网络密钥认证和 jar 验证。
代理与后端如何建立链接
以下所有流程都无需配置。之所以记录在此,是因为当网络没有链接成功时,了解这个顺序就等于掌握了全部诊断思路。
**1. 代理确立密钥。**启动时它会按以下顺序解析出唯一一个值:
- 位于代理插件自身数据文件夹中已保存的
network-key文件——首次启动之后每次启动的稳定状态; - 一次性地从代理上的
plugins/floodgate/key.pem派生出的种子(如果该文件存在); - 全新生成的随机密钥。
确定的密钥会保存到 network-key,并在有效期间重复使用。控制台会报告来源(Network key loaded ✓、adopted from Floodgate key.pem 或 New network key generated)。格式错误的 network-key 文件会被替换。如果 RSPM 无法保存新密钥,或无法读取已有的 network-key 文件,代理角色会停止启动,并报告 Could not establish persistent RSPM network identity 或 Cannot read established RSPM network identity,而不是使用一个可能在下次重启时改变的密钥运行。请修复文件夹权限并重启代理。
**2. 代理把密钥推送给每个后端。**一旦有玩家连接到某个后端,代理就会通过 rspm:network 插件通道把密钥发送给它。这个方向是有意为之的:后端在物理上无法主动索取,因为代理不会转发一条玩家客户端从未注册过的通道上的插件消息。
**3. 后端采纳并持久化该密钥。**它会把密钥保存到自己的 data.yml,并报告 Network key received from the proxy; this backend is now linked. 只有在后端尚未持有密钥时授予才会被接受——已经确立密钥的后端会记录一条警告并保留现有密钥,而不会让一条消息把它重新指向另一个网络。
在 **Velocity 的现代转发(modern forwarding)**下,授予会用代理的 forwarding.secret 做 HMAC 签名,而配置为现代转发的后端要求存在该签名。在 BungeeCord 以及旧式转发下没有可用于签名的共享密钥,因此授予是未签名的,并按未签名接受。
一个走到第 2 步却从未走到第 3 步的后端,其密钥来源会一直是 not set。这正是触发 proxy-extension/ 暂存以及基岩版专属警告横幅的状态。
验证是否工作正常
代理控制台
重启代理大约 10 秒内(假设后端正在运行),你应能看到:
[ResourcePackManager] Network key loaded ✓
[ResourcePackManager] Network key provisioning ready on rspm:network; backends are keyed as players connect.
[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
打印一份快照:网络密钥指纹、后端列表、各后端针对 /bedrock.zip、/mappings.json 与 /rspm-update.jar 每条路径的拉取结果(200 / 304 / 404 / CONNECT_FAILED)、它已收到的端点公告、它能看到的中继条目、连续空轮询计数器、合并后的基岩版资源包与合并后的映射文件是否已落盘(含各自大小)以及当前合并资源包的 SHA-1 前缀、network-http-offset 回退值、检测到的 Geyser 插件文件夹与已部署的映射文件,还有代理上 Floodgate / Geyser 的存在情况。Velocity 接受 resourcepackmanager.command.status 或 resourcepackmanager.*;BungeeCord 注册的是确切的 resourcepackmanager.command.status 节点,权限插件可以通过通配符展开来满足它。控制台可以运行该命令。输出不会泄露任何机密(网络密钥只以一段简短的单向哈希指纹出现,也不会打印任何认证令牌),所以可以放心宽松授权。
在后端上运行 /rspm status
Deploy mode 一行应当显示 network-backend。Network key fingerprint 应显示一段简短哈希——它必须与代理打印的指纹一致。Network key source 会告诉你这个后端是怎样拿到密钥的:
| 来源行 | 含义 |
|---|---|
provided by the proxy | 正常的已链接状态。代理在某次玩家连接时授予了密钥。 |
saved on this server | 在之前某次启动时就已获得密钥(或是一台自行生成密钥的独立服务器)。 |
adopted from Floodgate's key | 一次性地从该后端本地的 plugins/floodgate/key.pem 播种得到。 |
not set — the proxy sends one when a player next connects here | **未链接。**要么自代理启动以来还没有玩家连接过,要么代理上缺少 RSPM/代理类型不受支持。 |
基岩版客户端
用基岩版客户端连接。你应当在进入世界之前看到资源包下载提示。自定义物品会显示为其应有的模型,而不是普通的盔甲架。
配置项参考
后端 plugins/ResourcePackManager/config.yml
网络模式是自动检测的——没有什么 networkMode: true 开关需要设置。检测信号(任一即可):
- 存在 Floodgate,但不存在 Geyser-Spigot — 针对基岩版-经由代理场景最强的信号。
spigot.yml: settings.bungeecord: true— 旧式 BungeeCord 的 IP 转发开关。paper-global.yml: proxies.velocity.enabled: true— 现代 Velocity 转发。
网络模式的备用端口设置是 networkHttpOffset-v2,它控制后端尚未公告实际绑定端口前,代理推测并轮询的 HTTP 端口。默认值为 1;代理与后端之间仍须能够访问对应端口,或者中继路径必须可用。完整说明参见自托管。
在正常运行中,每个后端都会自动把它真实的 HTTP 端口公告给代理(通过 magmaguy.com 端点注册表),所以该偏移仅在启动/失败时作为回退被参考。参见下文的 后端 HTTP 端口解析。
代理 config.yml
代理插件在首次启动时会写入一份最简默认配置。该文件夹因平台而异,因为每种代理都从自己的插件标识符推导它:
| 代理软件 | 配置路径 |
|---|---|
| Velocity | plugins/resourcepackmanager/config.yml |
| BungeeCord | plugins/ResourcePackManager/config.yml |
它恰好包含两项设置,都是可选的:
# FALLBACK offset added to each backend's Minecraft port to derive the HTTP
# port this proxy will hit for /bedrock.zip and /mappings.json BEFORE that
# backend has announced its real ResourcePackManager HTTP port. Default 1.
# In normal operation the backend announces the exact port it bound, so this
# value is only used at startup or if announcement fails — but if it IS used,
# it should match each backend's networkHttpOffset-v2.
network-http-offset-v2: 1
# Installs and updates this universal ResourcePackManager.jar in the proxy's
# Geyser extensions folder, which is what makes custom Bedrock ENTITIES render.
# Default true. Setting it to false stops future installation and update
# staging; it does not delete an extension jar that is already installed —
# remove that by hand while Geyser is stopped.
geyser-extension-auto-install: true
后端一侧对应的设置是后端 config.yml 中的 networkHttpOffset-v2 与 geyserExtensionAutoInstall。两侧是彼此独立的设置——在代理上关闭扩展安装并不会在后端上把它关闭,反之亦然。
代理会在 config.yml 旁保存 network-key。请保留这份生成的状态,不要在不同网络之间复制。删除文件会在下次启动时重新确定密钥;如果 Floodgate 文件可用,可能重新得到相同的密钥。若密钥改变,已配发密钥的后端会保留旧密钥并拒绝新密钥。服务同一组后端的两个代理必须共用密钥:这种情况下应在两个代理之间复制该文件。
代理侧不存在 force-resource-pack 设置。强制客户端接受资源包是后端侧的决定(后端 config.yml 中的 forceResourcePack),因为代理插件只负责基岩版资源包的分发——它从不发送 Java 资源包。如果旧的代理 config.yml 中仍带有 force-resource-pack 这一行,它会被直接忽略,可以删除。
也故意不提供 network-key 配置条目——可粘贴的密钥在发布前就被取消了,因为拼写错误会悄无声息地破坏 proxy↔backend 链接,而且任何地方都不会报错。密钥由代理确立并自动下发给后端,具体见 代理与后端如何建立链接。
后端 HTTP 端口解析
代理需要知道在每个后端上轮询 /bedrock.zip 与 /mappings.json 时该用哪个 HTTP 端口。它按以下顺序解析该端口:
- 后端公告的端点(优先)。 每个后端会把它实际绑定的确切 HTTP 端口上传到 magmaguy.com 端点注册表,以网络密钥为键。每次轮询时代理会刷新这份列表,并通过 Minecraft 端口(以及可用时的主机名)把某个后端公告的端口与服务器列表条目匹配起来。这意味着无论管理员在某个后端上显式设置了
selfHostPort,还是该后端自动落在mcPort + 1上,处理方式都完全相同——代理使用后端实际绑定的端口。 mcPort + network-http-offset-v2(回退)。 仅在没有匹配的公告可用时使用(例如任何后端公告之前的第一次轮询,或端点注册表短暂不可达时)。这就是为什么如果你依赖回退,两端的偏移仍应保持一致。
代理特意不把端口扫描后端作为回退手段——那在托管商看来像是滥用行为。当直连拉取根本无法工作时,中继路径(见下文)才是根本性的解决办法。
代理上的 /rspm status 会针对每个后端显示选用了哪个端口,以及它是来自公告还是来自偏移回退。
稳定性与合并节奏
Java 托管偏好也适用于代理后端。如果 Java 自托管探测失败,RSPM 可以将 Java 分发切换到远程托管,同时继续运行后端 HTTP 服务器,为 /bedrock.zip 和 /mappings.json 提供服务。
代理在合并前会等待收件箱状态稳定:第一次轮询确定基线文件哈希集合,下一次观察到相同集合的轮询会触发合并(单周期稳定性门控)。在约 2 秒的初始延迟和 5 秒轮询间隔下,这意味着当代理至少能看到一个后端在生产内容之后,首次合并大约会在 7 秒后发生。后续只有在收件箱文件的 SHA-1 集合发生变化时才会重新打包,所以长时间静默几乎零开销。
后端会把它们的 bedrock.zip 写入一个临时文件,然后原子性地重命名,因此 /bedrock.zip 路由始终提供一个完整的 zip——代理永远不必防范读到写了一半的文件,这也是门控只需单周期而非两周期的原因。
直连拉取与中继回退
默认路径是直连拉取:代理对每个后端发起 http://<backend-host>:<mcPort + offset><path> 的 HTTP GET。
如果代理无法直接访问某个后端的 HTTP 端口(在共享 / 托管 Minecraft 服务上很常见,MC 端口对外开放但相邻端口被防火墙屏蔽),后端会在网络命名空间(由网络密钥派生)下把 bedrock.zip 与 mappings.json 推送到 magmaguy.com 上的中继端点。当直连拉取硬性失败时,代理会列出并从中继下载。
两条路径最终都汇入同一个合并步骤,因此运维人员无需在两者之间做选择——优先使用直连拉取(对 magmaguy.com 带宽成本为零),需要时中继会透明启用。
中继在服务端有 30 分钟的 TTL。后端每 25 分钟推送一次以保持条目存活;正常关闭会立即丢弃条目,而不必等待 TTL 过期。
常见问题排查
某个后端始终拿不到网络密钥
症状:该后端上的 /rspm status 显示 Network key source: not set — the proxy sends one when a player next connects here,且后端控制台反复输出:
[ResourcePackManager] This backend is behind a proxy but has no network key yet, so it is not linked to the proxy.
[ResourcePackManager] The proxy sends one automatically the first time a player connects to this server.
请按顺序逐条排查:
- **自代理启动以来,真的有人连接过那个后端吗?**密钥授予是随玩家连接一起发生的。一个还没人去过的大厅服处于未获密钥状态是完全合理的。
- **代理上到底装了 RSPM 吗?**后端正是为这种情况才在
plugins/ResourcePackManager/proxy-extension/ResourcePackManager.jar暂存了一份自身 jar 的副本。把它复制到代理的plugins/文件夹并重启代理。 - **Velocity 现代转发:后端的转发密钥和代理的一致吗?**配置为现代转发的后端会有意拒绝未签名或签名错误的授予——这项校验是唯一能阻止未授权代理给你的后端配发密钥的机制。后端日志会指明它遇到的是两种情况中的哪一种。在两侧都修正密钥后,下一次玩家连接会自动重试;两边都不需要重启即可重新就绪。
- **代理是不是不受支持的代理?**只有 Velocity 与 BungeeCord 会运行代理角色。不支持 Waterfall。
Floodgate 的 key.pem 已不再参与这一流程。代理上没有 plugins/floodgate/key.pem 也是受支持的状态,代理会生成自己的密钥。Floodgate 认证与 RSPM 网络连接是独立的。
两个代理位于同一组后端之前
两个代理必须出示相同的网络密钥,否则每个后端会链接到先到达它的那一个,并拒绝另一个(记录 A proxy offered a network key that differs from the one this backend already uses)。请把主代理 RSPM 数据文件夹中的 network-key 文件复制到另一个代理的对应文件夹,然后重启它。
大约 20 秒后出现 "No merged pack content" 警告
在已有确认的 RSPM 参与者且连续四轮轮询为空之后,代理会记录警告,列出这些参与者、尝试访问的 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" 警告
不同的 Bedrock 标识符仍可能共享相同的 Java 物品、模型和条件选择器。仅重命名解析后的源模型无法区分这些物品。请为不同物品分配不同选择器,例如不同的 custom-model-data 值。当前合并器对同一选择器优先保留现代 definition 而非 legacy;类型相同时保留后一个条目。去重只保留一个物品。
基岩版玩家已连接但看不到资源包
当基岩版会话加载时没有可用的 RSPM 资源包,代理会向具有 resourcepackmanager.* 权限的在线工作人员发送聊天提示:
⚠ [RSPM] 基岩版玩家 Alice 在资源包准备好之前连接,目前看到的是普通盔甲架,而非自定义模型。请让该玩家断开后重新连接;资源包将在下一次会话加载。(原因:...)
基岩版玩家本人也会收到一个模态弹窗,代理控制台也会出现一条横幅。如果需要进一步排查,可启用调试日志流(Velocity 与 BungeeCord 都支持):
/rspm debug bedrock on
这会打开 GeyserBinder 输出的详细 [RSPM-BedrockDebug] 日志行。复现问题后,再关闭它:
/rspm debug bedrock off
该设置在代理重启时会重置为关闭,避免被意外保持开启。
在网络上更新 RSPM
每个后端与代理用的都是同一个 jar,所以请让所有组件保持相同版本。
手动方式是:升级后端 jar,把同一个 ResourcePackManager.jar 重新复制到代理的 plugins/ 文件夹,然后重启代理。
RSPM 也可以自己完成代理这一半。每个后端都会通过一条经过认证的路由(/rspm-update.jar,由从共享网络密钥派生出的令牌保护——密钥本身绝不会被传输)把自己的通用插件 jar 提供给代理。代理会校验所提供的文件确实是一个完整的通用 RSPM jar,其各平台描述符版本一致、入口点符合预期,拒绝降级,并在替换任何文件之前依据所声明的大小与 SHA-256 校验暂存下来的字节。它会为代理插件暂存同一个 jar;当检测到代理上托管着 Geyser 时,也会暂存其内置的 Geyser 扩展。这些文件会在代理关闭时应用,并保留此前的文件作为回滚副本。
这是一条经过认证的网络信任边界,而不是针对 Nightbreak 的独立来源校验:任何已被配发共享网络密钥的后端,都被信任可以提供一个结构有效、版本相同或更新的 RSPM jar。请保护好该密钥,并把共用它的每个后端都视为可信基础设施。
因此实践中,升级各后端然后重启代理通常就足够了——代理会已经为自己暂存好匹配的 jar。被拒绝的更新会记录 Rejected backend-offered ResourcePackManager update: ... 并附上原因。
可执行更新的认证失败
/rspm-update.jar 返回 HTTP 401 只会暂停来自该后端的 jar 自动传播。基岩版资源包和映射的直接轮询会继续。更新路径的重试间隔从一分钟开始递增,最多十五分钟。请比较两侧 /rspm status 中的网络密钥指纹,然后验证报告的 URL 到达预期后端,并确认版本一致。
如果指纹不同,代理上的 /rspm status 会给出当前的处理步骤:确认这是预期的代理和后端,停止受影响的后端,备份其 plugins/ResourcePackManager/data.yml,只删除其中的 networkKey 条目,然后启动它并通过此代理加入,使其重新获得密钥。保留代理的 network-key 以及所有 Floodgate 密钥。代理上的 401 控制台警告仍建议复制 Floodgate 的 key.pem;这条建议已经过时,因为 RSPM 会保存自己的网络身份,修改 key.pem 不会替换已建立的 RSPM 密钥。请保留两侧状态输出以供支持排查。
目前尚未支持的内容
- 通过代理插件在网络上分发 Java 资源包。 Java 客户端通过常规 API 直接从各后端接收资源包。代理侧没有 Java 资源包混合器。
- 跨后端的 Java 资源包合并。 每个后端的 Java 资源包是独立的。玩家切换后端时会收到新后端的资源包。
- 网络密钥的在线轮换。 后端仅在没有密钥时接受密钥,并拒绝替换消息。停止所有组件后,删除代理的
network-key,并清除每个后端data.yml中的networkKey,即可重新配发密钥。这不保证密钥会改变:代理可能再次从 Floodgate 的key.pem派生出相同的密钥。