Перейти к основному содержимому

Самостоятельный хостинг ресурс-пака

ResourcePackManager поставляется с собственным небольшим HTTP-сервером. Когда autoHost: true (по умолчанию) и preferSelfHost: true (по умолчанию), плагин пытается хостить собранный пак из той же JVM, что и сам Minecraft-сервер — без внешнего файлового хоста, без отдельного веб-сервера, без ручной вставки URL.

Эта страница описывает, как работает этот путь самостоятельного хостинга, что делают проверки исправности, как выбирается порт и hostname, и что настраивать, когда значения по умолчанию вам не подходят.

Если вместо этого вы хотите хостить zip через свой собственный существующий веб-сервер вне RSPM, см. раздел про autoHost: false на странице устранения неполадок.

Дерево решений по доставке

Когда игрок подключается, RSPM выбирает URL для доставки по такому приоритету:

  1. selfHostForce: true — прямой self-host, без проверок, без удалённой загрузки. Главным образом для тестирования self-host пути. Обходит все остальные флаги.
  2. preferSelfHost: true И selfHostEnabled: true И не в сетевом режиме — попробовать self-host с тремя проверками исправности (см. ниже). Если все проходят, фиксируется self-host. Если хоть одна не прошла, откат на удалённый путь.
  3. Иначе — загрузить пак на https://magmaguy.com/rsp/ и анонсировать этот URL. Если загрузка не удалась или проверка SHA1 сообщает SESSION_NOT_FOUND, откат на self-host (при условии selfHostEnabled: true).

Как только URL получен, RSPM использует multi-pack API Minecraft на 1.20.3+ (чтобы сосуществовать с другими паками, отправляемыми сервером) и старый метод одиночного пака на более старых версиях.

Три проверки исправности

Когда preferSelfHost: true, RSPM выполняет эти проверки по порядку перед тем, как зафиксировать self-host:

Уровень 1 — эвристическая проверка разрешённого внешнего хоста

Если разрешённый хост (см. «Определение внешнего хоста» ниже) — это RFC1918 (10.*, 172.16-31.*, 192.168.*), loopback (127.*), link-local (169.254.*) или unspecified (0.0.0.0), self-host никак не сможет работать для интернет-клиентов. Сразу пропустить и использовать удалённый хостинг.

Это ловит очень распространённый сценарий «ipify-запрос не удался, откатился на LAN-IP».

Уровень 2 — локальная самопроверка

Открывается HEAD-запрос на http://127.0.0.1:<port>/rspm.zip, проверяется HTTP 200 и непустое тело. Ловит:

  • коллизии при привязке порта (что-то другое уже на выбранном порту)
  • отсутствующий файл пака (маршрут зарегистрирован, но zip ещё не на диске)
  • баги регистрации маршрутов

Агрессивный таймаут (3 с), чтобы медленная проверка не затягивала загрузку.

Уровень 3 — проверка внешней доступности

POST анонсированного URL на POST /rsp/probe на хостере magmaguy.com. Хостер скачивает URL с публичной vantage point (с SSRF-защитой и жёстким таймаутом) и отчитывается, доступен ли он.

Ловит наиболее распространённую боевую проблему: у сервера есть публичный IP, но HTTP-порт не проброшен на роутере или файрволе. Уровень 2 проходит (сервер отвечает на 127.0.0.1), но ни один реальный клиент никогда не сможет скачать пак.

Политика принятия решений по результатам проверки:

  • reachable=true → внешние клиенты могут достучаться до нашего URL. Фиксируется self-host.
  • reachable=false → внешние клиенты не могут. Сворачивается self-host, используется удалённый хостинг (который универсально доступен с magmaguy.com).
  • сама связь проверки не удалась (IOException) → не удалось проверить никак. По умолчанию оставляется self-host: отказывать из-за невозможности проверки было бы парадоксально, потому что удалённому пути magmaguy.com тоже нужен.

Что проверки всё ещё не обнаруживают

Граничный случай NAT-hairpin, когда порт открыт в публичный интернет (Уровень 3 проходит), но собственный роутер оператора не делает loopback трафика обратно изнутри 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?

Большинство shared / managed Minecraft-хостингов (панели на базе Pterodactyl и т. п.) выделяют узкий диапазон портов на контейнер (часто всего 4–10 портов). Большие смещения уходят за границы диапазона, и файрвол хостинга молча блокирует HTTP-порт. Смещение 1 помещается даже в самые узкие выделения.

Самостоятельные администраторы с полным контролем над портами могут увеличить это до любого значения, но если вы держите прокси-сеть, вы обязаны также изменить network-http-offset-v2 прокси, чтобы совпадало.

Осторожно: коллизия с RCON

Если ваш хостинг включает RCON по умолчанию на MC port + 1, выберите смещение 2 или 3 во избежание коллизии портов. Проверьте server.properties на rcon.port=.

Версионированный ключ конфига

Настройка в config.yml буквально называется networkHttpOffset-v2. Ключ v1 был networkHttpOffset с дефолтом 100 — этот дефолт ломался на shared / managed-хостингах, где каждый игровой контейнер получает всего ~4–10 последовательных портов, MC + 100 уходило за пределы диапазона, HTTP-сервер привязывался внутренне, но файрвол хостинга отбрасывал внешний трафик, и прокси получал молчаливый CONNECT_FAILED навсегда. v2 поставляется с дефолтом 1, поэтому MC + 1 остаётся хорошо внутри даже самых узких контейнерных выделений.

Если вы обновляетесь с v1, мёртвый ключ v1 сидит в вашем конфиге как безвредный артефакт, пока вы не уберёте его вручную — RSPM намеренно его не читает.

Определение внешнего хоста

selfHostExternalHost контролирует, какое имя хоста клиенты видят в URL. Оставьте пустым (по умолчанию), чтобы авто-определить в таком порядке приоритета:

  1. api.ipify.org / checkip.amazonaws.com — возвращает публичный IPv4 этого хоста. Кешируется один раз на /rspm reload, чтобы IP-сервисы не нагружались.
  2. Bukkit.getIp() — bind-адрес сервера, когда непустой и не 0.0.0.0. Обычно LAN-адрес.
  3. InetAddress.getLocalHost() — best-effort.
  4. localhost — последний резерв. Клиенты вне коробки сюда не достучатся.

Если авто-определение приводит к не-маршрутизируемому адресу и preferSelfHost: true, эвристическая проверка Уровня 1 проваливается, и плагин переключается на удалённый хостинг.

Для максимально надёжной настройки self-host выставьте selfHostExternalHost явно на ваше публичное имя хоста (например, play.example.com). Это полностью пропускает определение через ipify/AWS, и проверка запускается против явного значения.

Справочник по конфигурации

# Можно ли вообще использовать встроенный HTTP-сервер как путь доставки.
# Когда false, self-host никогда не пробуется независимо от других флагов.
selfHostEnabled: true

# Порт для self-host HTTP-сервера.
# -1 (по умолчанию) = авто-вывод: HTTP порт = порт Minecraft-сервера + networkHttpOffset-v2.
# Установите любое положительное значение, чтобы принудительно задать порт.
selfHostPort: -1

# Прибавляется к порту Minecraft-сервера, когда selfHostPort = -1.
# По умолчанию 1 (MC 25565 -> HTTP 25566). Должно совпадать с network-http-offset-v2 прокси
# в прокси-сетях.
networkHttpOffset-v2: 1

# Публичное имя хоста или IP, которые клиенты используют для доступа к self-host серверу.
# Оставьте пустым для авто-определения (api.ipify.org / checkip.amazonaws.com).
selfHostExternalHost: ""

# Пробовать self-host СНАЧАЛА с тремя проверками исправности, откатываться на удалённый при отказе.
# Когда false, использовать старый порядок: сначала удалённая загрузка, self-host только при её отказе.
preferSelfHost: true

# Пропустить ВСЕ другие пути доставки и принудительно использовать self-host.
# Обходит проверки исправности И удалённую загрузку. Главным образом для тестирования.
selfHostForce: false

Маршруты бэкенд-HTTP-сервера

Встроенный HTTP-сервер всегда раздаёт zip пака по адресу:

http://<host>:<port>/rspm.zip

В сетевом режиме (RSPM находится за Velocity / BungeeCord / Waterfall прокси) регистрируются два дополнительных маршрута для опроса прокси-плагином:

http://<host>:<port>/bedrock.zip   # Bedrock-преобразованный пак
http://<host>:<port>/mappings.json # JSON кастомных маппингов Geyser

Все три маршрута file-backed: маршрут читает файл свежим при каждом запросе, поэтому пересборка, переписывающая тот же путь zip, подхватывается автоматически без перезапуска HTTP-сервера. Bedrock-маршруты поддерживают If-Modified-Since, поэтому опросчик прокси платит примерно нулевой трафик, когда ничего не изменилось. Все маршруты корректно возвращают 404, когда подлежащий файл отсутствует (например, до завершения первой сборки).

Проверка, что self-host активен

/rspm status показывает:

  • Active delivery: SELF-HOSTED — self-host используется
  • Active delivery: REMOTE (magmaguy.com) — удалённый авто-хостинг используется
  • URL: ... — фактический URL, который увидят клиенты
  • Resolved external host — во что разрешилось selfHostExternalHost
  • Public IP (auto-detected) — что вернули ipify/AWS, если что-то
  • selfHostPort — авто vs явный, и разрешённое значение

Если вы ожидали self-host, но видите удалённый, лог загрузки объясняет, какая проверка исправности не прошла и почему.

Типичные ошибки

  • Установка selfHostPort в произвольное значение и забывание про это на прокси — в сетевом режиме прокси использует mcPort + network-http-offset-v2 для вычисления HTTP-порта каждого бэкенда. Явный selfHostPort переопределяет авто-вывод, но прокси про это не знает, поэтому всё равно будет опрашивать mcPort + offset. Оставьте selfHostPort: -1 в сетевом режиме, если только не готовы координировать.
  • Доверять проверке Уровня 3 при сломанном hairpin на роутере — проверка идёт с vantage point magmaguy.com, поэтому она не может поймать случай, когда внешние клиенты работают, но собственная LAN оператора не делает loopback. Тестируйте с телефона по сотовой, если не уверены.
  • Увеличение networkHttpOffset-v2 за пределы диапазона портов вашего хостинг-провайдера — симптом — молчаливый CONNECT_FAILED навсегда на стороне прокси. Проверьте, что mcPort + offset находится в выделенной полосе портов вашего контейнера, прежде чем увеличивать смещение.