自托管资源包
ResourcePackManager 内置了自己的小型 HTTP 服务器。当 autoHost: true(默认)且 preferSelfHost: true(默认)时,插件会尝试在与 Minecraft 服务器同一个 JVM 中托管合并后的资源包——无需外部文件托管服务、无需独立的 Web 服务器、也无需手动粘贴 URL。
本页介绍该自托管路径的工作原理、各项完整性检查的作用、端口与主机名的选择方式,以及当默认设置不合适时该如何配置。
如果你反而希望通过自己已有的、独立于 RSPM 的 Web 服务器托管 zip,请参阅 Troubleshooting page 中关于 autoHost: false 的一节。
分发决策树
当玩家加入时,RSPM 按以下优先级选择分发 URL:
selfHostForce: true— 直接走自托管,不做任何探测,也不做远程上传。主要用于测试自托管路径。会绕过其他所有开关。preferSelfHost: true且selfHostEnabled: true且不在网络模式 — 先尝试带三项完整性检查的自托管(见下文)。若全部通过,则确认走自托管;若任一项失败,则回退到远程路径。- 否则 — 将资源包上传到
https://magmaguy.com/rsp/并公告该 URL。如果上传失败或 SHA1 校验返回SESSION_NOT_FOUND,则回退到自托管(前提是selfHostEnabled: true)。
一旦确定了 URL,RSPM 在 Minecraft 1.20.3+ 上使用多资源包 API(以便与其他服务器发送的资源包共存),在更早版本上则使用旧的单资源包方法。
三项完整性检查
当 preferSelfHost: true 时,RSPM 在确认走自托管之前会按顺序运行下面三项检查:
第 1 层 — 对解析出的外部主机名做启发式检查
如果解析出的主机名(参见下文 “外部主机检测”)属于 RFC1918(10.*、172.16-31.*、192.168.*)、回环(127.*)、链路本地(169.254.*)或未指定(0.0.0.0),那么自托管对互联网客户端根本不可能可用。立即跳过,使用远程托管。
这能捕获非常常见的“ipify 查询失败、回退到 LAN IP”的失败模式。
第 2 层 — 本地回环自探测
对 http://127.0.0.1:<port>/rspm.zip 发起 HEAD 请求,验证返回 HTTP 200 并且响应体非空。可捕获:
- 端口绑定冲突(其他东西占用了所选端口)
- 资源包文件缺失(路由已注册但 zip 尚未在磁盘上就位)
- 路由注册的 bug
该探测使用激进的超时(3 秒),以免一个慢探测拖延启动。
第 3 层 — 外部可达性探测
向 magmaguy.com 托管端的 POST /rsp/probe 提交公告出的 URL。该托管端会从一个公共可视点(带 SSRF 防护和较紧的超时)尝试拉取该 URL,并把可达情况回报。
这能捕获生产环境中最常见的失败模式:服务器有公网 IP,但 HTTP 端口没有在路由器或防火墙上放通。第 2 层会通过(服务器在 127.0.0.1 上有响应),但任何真实客户端都根本下载不到资源包。
针对探测结果的决策策略:
- reachable=true → 外部客户端可以访问到我们的 URL。确认走自托管。
- reachable=false → 外部客户端访问不到。拆掉自托管,改用远程托管(从 magmaguy.com 看是普遍可达的)。
- 探测通信本身失败(IOException) → 无法证实任何一种结果。默认保留自托管:以“无法探测”为由拒绝是自相矛盾的,因为远程路径同样需要 magmaguy.com。
这些检查仍然检测不到的情况
NAT 回流(hairpin)边缘情况:端口对公网完全开放(第 3 层通过),但运维人员自家路由器不会把 LAN 内的流量回环回来。外部客户端正常工作,但运维人员从同一台机器测试时失败。
目前的变通方法:当从主机本机测试而路由器存在 hairpin 问题时,设置 preferSelfHost: false 或 selfHostExternalHost: 127.0.0.1。
端口解析
两个设置会互相影响:
selfHostPort— 显式端口(任意正整数)或-1(默认)以启用自动派生。networkHttpOffset-v2— 仅在selfHostPort = -1时才参考。加到 Minecraft 服务器端口上。默认1。
默认值是 selfHostPort: -1 + networkHttpOffset-v2: 1,所以:
- MC 端口 25565 → HTTP 端口 25566
- MC 端口 25584 → HTTP 端口 25585
这样在单主机网络上的多个后端之间会自动错开 HTTP 端口,无需任何管理员配置——每个后端本来就有唯一的 MC 端口,因此各自得到一个唯一的 HTTP 端口。
为什么偏移是 1?
大多数共享 / 托管型 Minecraft 服务(基于 Pterodactyl 的面板等)会为每个容器分配一段较窄的端口范围(通常只有 4–10 个端口)。更大的偏移会落到范围之外,宿主防火墙会静默屏蔽 HTTP 端口。偏移 1 即使在最紧的分配下也能放得下。
拥有完整端口控制权的自托管管理员可以把它改成任意值,但如果你运行代理网络,也必须同步调整代理的 network-http-offset-v2。
注意:RCON 端口冲突
如果你的宿主默认在 MC 端口 + 1 上启用 RCON,请将偏移改为 2 或 3 以避免端口冲突。在 server.properties 中查看 rcon.port=。
带版本号的配置键
config.yml 中的设置项名称就是字面的 networkHttpOffset-v2。v1 的键是 networkHttpOffset,默认值 100——在共享 / 托管型服务上会出问题,因为每个游戏容器只分到 4–10 个连续端口,MC + 100 落在范围外,HTTP 服务器在内部能够绑定但宿主防火墙会丢弃外部流量,代理会得到一个永远静默的 CONNECT_FAILED。v2 默认值为 1,让 MC + 1 即使在最窄的容器分配下也能稳稳落在范围内。
如果你从 v1 升级,废弃的 v1 键会以无害遗留物的形式留在你的配置中,等你手动清理——RSPM 故意不读取它。
外部主机检测
selfHostExternalHost 控制客户端在 URL 中看到的主机名。留空(默认)则按以下优先级自动检测:
- api.ipify.org / checkip.amazonaws.com — 返回本主机的公网 IPv4。每次
/rspm reload之间只缓存一次,避免反复请求 IP 服务。 Bukkit.getIp()— 服务器绑定地址,仅在非空且不为0.0.0.0时使用。通常是 LAN 地址。InetAddress.getLocalHost()— 尽力而为。localhost— 最后的兜底。盒子外的客户端访问不到。
如果自动检测落在了不可路由的地址上,且 preferSelfHost: true,第 1 层启发式检查会失败,插件会切换到远程托管。
要获得最可靠的自托管设置,请把 selfHostExternalHost 显式设为你的公网主机名(例如 play.example.com)。这会完全跳过 ipify/AWS 检测,探测会针对你显式给出的值运行。
配置项参考
# 是否允许使用内置 HTTP 服务器作为分发路径。
# 设为 false 时,无论其他开关如何都不会尝试自托管。
selfHostEnabled: true
# 自托管 HTTP 服务器的端口。
# -1(默认)= 自动派生:HTTP 端口 = Minecraft 服务器端口 + networkHttpOffset-v2。
# 设为任意正值则强制使用显式端口。
selfHostPort: -1
# 当 selfHostPort = -1 时附加到 Minecraft 服务器端口上的偏移。
# 默认 1(MC 25565 -> HTTP 25566)。在代理网络中必须与代理的
# network-http-offset-v2 一致。
networkHttpOffset-v2: 1
# 客户端用来访问自托管服务器的公网主机名或 IP。
# 留空则自动检测(api.ipify.org / checkip.amazonaws.com)。
selfHostExternalHost: ""
# 先尝试带三项完整性检查的自托管,任一项失败则回退到远程。
# 设为 false 时,使用旧顺序:先尝试远程上传,仅在上传失败时才走自托管。
preferSelfHost: true
# 跳过所有其他分发路径,强制走自托管。
# 会绕过完整性检查以及远程上传。主要用于测试。
selfHostForce: false
后端 HTTP 服务器路由
内置的 HTTP 服务器始终在下面这个地址提供资源包 zip:
http://<host>:<port>/rspm.zip
在网络模式下(RSPM 处于 Velocity / BungeeCord / Waterfall 代理之后),还会额外注册两个供代理插件拉取的路由:
http://<host>:<port>/bedrock.zip # 转换后的基岩版资源包
http://<host>:<port>/mappings.json # Geyser 自定义映射 JSON
三个路由都由文件支持:每次请求都会重新读取文件,所以即使重新合并写入了同一个 zip 路径,也会被自动采纳,无需重启 HTTP 服务器。两个基岩版路由都支持 If-Modified-Since,因此代理轮询器在内容未变时几乎零带宽。所有路由在底层文件缺失时(例如首次合并尚未完成)都会干净地返回 404。
验证自托管是否启用
/rspm status 会显示:
Active delivery: SELF-HOSTED— 当前使用自托管Active delivery: REMOTE (magmaguy.com)— 当前使用远程 auto-hostURL: ...— 客户端实际看到的 URLResolved external host—selfHostExternalHost解析得到的值Public IP (auto-detected)— ipify/AWS 报告的结果(如有)selfHostPort— 是自动还是显式,以及解析得到的值
如果你预期走自托管但实际显示远程,启动日志会解释是哪一项完整性检查失败了以及原因。
常见错误
- 把
selfHostPort设为任意值,却没在代理一侧同步修改 — 在网络模式下,代理使用mcPort + network-http-offset-v2来计算每个后端的 HTTP 端口。显式的selfHostPort会覆盖自动派生,但代理并不知道这件事,仍然会去轮询mcPort + offset。除非你准备好在两端协调,否则在网络模式下请保留selfHostPort: -1。 - 在路由器存在 hairpin 问题时仍然相信第 3 层探测的结果 — 该探测从 magmaguy.com 的可视点运行,所以无法捕获“外部客户端可用、但运维人员自家 LAN 无法回环”的情况。不确定时请用蜂窝网络下的手机测试。
- 把
networkHttpOffset-v2调过你托管商的端口范围 — 症状是代理侧永远静默的 CONNECT_FAILED。提高偏移之前,先确认mcPort + offset落在容器分配的端口区间内。