RE:NODE

Minecraft11 мин чтения

MOTD, иконка сервера и ресурспаки в Minecraft

Двухстрочный MOTD с цветовыми кодами, server-icon.png размером 64x64 и ресурспак, который клиенты действительно скачают: хостинг, хеш и принудительная загрузка.

0 прочтений

Три мелочи определяют, что игрок видит до входа и как выглядит мир после него: строка MOTD в server.properties, файл server-icon.png ровно 64 пикселя в ширину и высоту и ресурспак, отдаваемый по URL с совпадающим хешем SHA-1. Ни одна из них не сложна, и все три ломаются одинаково тихо: сервер запускается, ничего не появляется, и никакой очевидной ошибки нет. В статье разобрано, откуда берётся каждая, какой у неё точный синтаксис, включая escape, нужный цветовым кодам, и конкретные причины, по которым пак отказывается скачиваться.

Из чего состоит запись в списке серверов#

Когда у клиента игрока сохранён ваш адрес, он открывает короткое соединение и запрашивает статус. Ваш сервер отвечает небольшим блоком JSON, а затем пингом для измерения задержки. Всё, что есть в записи списка, берётся из этого ответа:

  • Описание, то есть ваш MOTD, в виде форматированного текстового компонента на двух строках.
  • Число игроков, онлайн и максимум, плюс выборка имён, которая показывается при наведении курсора на число.
  • Версия: название и номер протокола, из-за чего появляется красная надпись «Outdated client», когда они не совпадают.
  • Favicon, PNG размером 64x64, закодированный прямо в ответ.

Весь этот обмен происходит до какой-либо аутентификации, поэтому запись работает даже для сервера, на который вы не можете зайти. Поэтому же enable-status=false в server.properties заставляет работающий сервер выглядеть выключенным для всех: он просто отказывается отвечать на вопрос. Эта настройка иногда полезна для частного сервера и иногда становится причиной, по которой кто-то час отлаживает файрвол, с которым всё в порядке.

Ещё одно, что нужно знать до правок: если вы используете прокси, на запрос статуса отвечает прокси, а не бэкенд. MOTD, иконка и число игроков берутся из собственной конфигурации прокси, и ничто из настроенного на сервере Paper за ним никогда не будет показано. Именно на этом попадаются в день, когда добавляют прокси Velocity к работающему серверу.

Пишем MOTD#

motd находится в server.properties в корне сервера, а по умолчанию равен A Minecraft Server. Файл - это файл свойств Java, что даёт два полезных escape и одну ловушку.

server.properties
motd=§6§lTHE MINE§r §7| §avanilla survival 1.21\n§8no whitelist §7- §fmc.example.com

\n начинает вторую строку. § - знак параграфа, символ, с которого начинается код форматирования. Иногда можно вставить в файл сам знак параграфа, и он сработает, но переживёт ли он сохранение, зависит от кодировки файла и редактора, которым тот сохранён, так что escape - это вариант, который работает всегда. Редактор файлов в панели пишет в UTF-8; текстовый редактор в Windows - может не писать.

КодЭффектКодЭффект
0Чёрный8Тёмно-серый
1Тёмно-синий9Синий
2Тёмно-зелёныйaЗелёный
3Тёмно-бирюзовыйbБирюзовый
4Тёмно-красныйcКрасный
5Тёмно-фиолетовыйdСветло-фиолетовый
6ЗолотойeЖёлтый
7СерыйfБелый
lЖирныйoКурсив
nПодчёркнутыйmЗачёркнутый
kОбфусцированныйrСброс

Несколько правил, которые нигде очевидно не записаны. Коды форматирования не складываются так, как вы ожидаете: цветовой код сбрасывает форматирование, поэтому §l§a - жирный зелёный, а §a§l - зелёный, затем жирный, что то же самое лишь по случайности порядка; ставьте цвет первым, а стиль вторым, и вас ничто не удивит. §r сбрасывает и то и другое. Клиент обрезает каждую строку по ширине записи в списке, а это где-то около 45 символов обычного текста, меньше с жирным. Делайте вторую строку второстепенной, а важное слово ставьте первым.

Для всего, что выходит за шестнадцать классических цветов, - градиентов, RGB по символам - используйте плагин, который отдаёт MOTD как полный текстовый компонент в момент пинга. Paper во многих местах понимает последовательность hex в стиле Bungee §x, но MOTD - как раз то место, которое надо проверить, а не предполагать, потому что при ошибке в публичном списке окажется строка видимого мусора. Плагин MOTD - это ещё и способ получить случайную строку на каждый пинг, сообщение о техобслуживании или отдельный MOTD для устаревших клиентов.

Обфусцированный текст (§k) в MOTD анимируется на каждом кадре и выглядит как сломанный шрифт на половине сайтов-каталогов, которые его собирают. Используйте его не больше чем для одного слова или не используйте вовсе.

server-icon.png#

Иконка - это файл с именем ровно server-icon.png в корневом каталоге сервера, то есть в той же папке, где лежат server.properties и папка мира, а не внутри plugins/.

Это должен быть PNG размером ровно 64 на 64 пикселя. Не 128, не 63 и не JPEG, переименованный в .png. Прозрачность поддерживается и хорошо смотрится на тёмном фоне списка. Всё остальное, и сервер выводит строку при запуске и продолжает работать без иконки:

code
[Server thread/WARN]: Couldn't load server icon

Файл читается один раз при запуске, а затем хранится в памяти, поэтому для смены иконки нужен перезапуск, а не перезагрузка. В панели загрузите его через файловый менеджер в корень сервера, затем перезапустите из консоли. Если у игрока клиент всё ещё показывает старую иконку, пусть обновит список многопользовательской игры; если она не меняется, помогает удалить запись сервера и добавить её заново.

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

Строка с числом игроков#

max-players в server.properties - это число справа в записи, и именно его сервер реально применяет. Его повышение не делает сервер способным вместить столько людей; оно лишь снимает отказ. Сколько ваш тариф способен вместить на самом деле - вопрос памяти и CPU, разобранный в статье сколько игроков помещается на сервере.

hide-online-players по умолчанию равен false. Значение true убирает выборку имён из подсказки при наведении и оставляет числа. Это разумная настройка приватности для частного сервера и ничего не даёт публичному.

Плагины, придумывающие число игроков, существуют. Их стоит избегать: числа тривиально проверяются через порт запросов, несколько сайтов-каталогов считают это основанием для удаления, а сервер, заявляющий сорок игроков при трёх, производит худшее первое впечатление, чем тот, у которого честно три.

Ресурспаки: четыре свойства#

Сервер может попросить каждого входящего клиента скачать и применить ресурспак. Этим управляют четыре ключа в server.properties, и по умолчанию все они пусты.

КлючЧто принимает
resource-packПрямой URL на .zip
resource-pack-sha140-символьный SHA-1 этого файла в нижнем регистре
require-resource-packtrue отключает всех, кто отказался. С версии 1.17
resource-pack-promptТекстовый компонент JSON, показываемый на экране согласия. С версии 1.17
server.properties
resource-pack=https://packs.example.com/themine-v7.zipresource-pack-sha1=2fd4e1c67a2d28fced849ee1bb76e7391b93eb12require-resource-pack=falseresource-pack-prompt={"text":"Our pack adds custom block sounds and item models."}

В версии 1.20.3 и новее есть ещё resource-pack-id - UUID, идентифицирующий пак, который появился потому, что в этой версии стало возможным применять несколько паков одновременно и добавлять или убирать их по отдельности во время работы. В старых версиях пак один, и он заменяет всё, что было до него.

Сам zip должен быть собран правильно, иначе клиент отвергнет его как недопустимый пак. pack.mcmeta должен лежать в корне архива, рядом с assets/. Самая частая ошибка на свете - выделить папку пака и сжать её, что даёт MyPack/pack.mcmeta на уровень глубже. Выделяйте содержимое, а не папку. Внутри pack.mcmeta значение pack_format - это число, привязанное к версии игры; когда оно не совпадает, большинство версий всё равно загружают пак с предупреждением о том, что он сделан для другой версии, а некоторые возможности молча не применяются.

Хостинг zip и правильный хеш#

URL скачивается клиентом, а не сервером. Он должен быть общедоступным по HTTP или HTTPS, отдавать файл напрямую с кодом 200 и не перенаправлять сначала на HTML-страницу. Это исключает ссылки для общего доступа из потребительских файлообменных сервисов, которые отдают веб-страницу с кнопкой загрузки, а не сам файл. Исключает это и всё, что стоит за проверкой защиты от ботов.

Проверьте с машины, которая не является вашим сервером:

bash
$ curl -IL https://packs.example.com/themine-v7.zipHTTP/2 200content-type: application/zipcontent-length: 4823914

Ответ 302 на что-то, заканчивающееся на .html, 403 или content-type со значением text/html - всё это значит, что клиент потерпит неудачу. Подойдёт любой небольшой хостинг статики: тариф веб-хостинга, объектное хранилище с публичными объектами или файл релиза на сервисе хостинга кода. Веб-тарифы RE:NODE отдают статические файлы от $3 в месяц и включают слот обратного прокси - направьте запись A на показанный адрес, и сертификат будет выпущен и продлён за вас, так что URL пака работает по HTTPS без всякой работы. О части, связанной с сертификатом, рассказано в статье ваш домен и его сертификат.

Теперь хеш. SHA-1 - это способ, которым клиент узнаёт, актуальна ли уже имеющаяся у него копия:

bash
$ sha1sum themine-v7.zip2fd4e1c67a2d28fced849ee1bb76e7391b93eb12  themine-v7.zip

В Windows - certutil -hashfile themine-v7.zip SHA1 или Get-FileHash -Algorithm SHA1 themine-v7.zip в PowerShell. Вставляйте значение в нижнем регистре без пробелов.

Здесь ломается три вещи, и все три можно предотвратить:

  • Хеша нет совсем. Пак всё равно работает, но клиент не может определить, совпадает ли его кэшированная копия, и перекачивает пак при каждом входе. На паке в 40 МБ это очень медленный экран подключения.
  • Устаревший хеш. Вы обновили zip, а свойство - нет. Клиент скачивает файл, обнаруживает несовпадение и отказывается или предупреждает. Всегда обновляйте оба вместе.
  • Кэшированный URL. Некоторые клиенты и большинство промежуточных кэшей опираются на URL. Меняйте имя файла каждый раз, когда меняется содержимое, - themine-v7.zip, затем themine-v8.zip, - и весь этот класс проблем исчезает.

Держите пак небольшим. Клиент категорически отказывается от очень больших паков - потолок около 100 МБ в современных версиях и вдвое меньше в старых, - но важен не лимит, а время подключения. Игрок с медленным соединением, наблюдающий за загрузкой в 60 МБ, прежде чем увидеть ваш спавн, часто просто уходит. Хорошая цель - меньше 10 МБ, а основной вес обычно составляют несжатые текстуры с разрешением, которого никто не различает.

Принудительный пак: нужно ли#

require-resource-pack=true превращает пак из предложения в условие: откажись - и тебя отключат. resource-pack-prompt - ваш единственный шанс объяснить причину, так что используйте его для фразы, которая успокаивает, а не для лозунга.

Две честные причины не делать пак обязательным. Во-первых, игрок, у которого в записи этого сервера «Ресурспаки сервера» переключены в Disabled, отклоняет пак автоматически, даже не увидев запроса, и его выкидывает с сообщением, которое он воспримет как «сервер сломан». Во-вторых, обязательность добавляет загрузку на критический путь первого входа, а это самый хрупкий момент в отношениях нового игрока с вашим сервером.

Обязательный пак оправдан, когда он несёт нагрузку: пользовательские предметы, модели которых и есть геймплей, карта, зависящая от собственных звуков. Всё остальное лучше оставить необязательным или отправлять игрокам по одному плагином уже после входа, что поддерживает большинство плагинов управления паками через тот же механизм, которым пользуется сервер.

Игроки Bedrock, подключающиеся через Geyser, - совершенно отдельный случай: они не могут прочитать пак для Java, потому что у Bedrock другой формат паков. Geyser раздаёт паки Bedrock из собственной папки packs/, поэтому кроссплей-сервер, которому важен внешний вид, поддерживает два набора. Об этом рассказано в статье Geyser и Floodgate.

Устранение неполадок#

В списке старый MOTD. Клиент кэширует запись, пока список не обновят. Нажмите обновление или выйдите с экрана многопользовательской игры и войдите снова. Если он так и не обновляется, на пинг отвечает прокси.

Цветовые коды отображаются как текст. Либо в файл записали настоящий знак параграфа в кодировке, которую сервер не распознал как него, либо код набрали с &. Коды с & - соглашение плагинов; в чистом server.properties нужен знак параграфа, лучше всего записанный как §.

Иконка не появляется. Почти всегда дело в размерах. Откройте файл и проверьте, что он 64x64, и посмотрите предупреждение в логе запуска. Работает PNG, экспортированный в 64x64 с альфа-каналом.

Клиент сообщает «Failed to download resource pack». Скачайте URL сами командой curl -IL с другой машины. В порядке вероятности: он перенаправляет на HTML-страницу, сертификат недействителен или истёк, хостинг блокирует запрос или файл слишком велик.

Пак скачивается, но ничего не меняется. Структура zip. pack.mcmeta должен лежать в корне. Распакуйте свой файл и посмотрите.

Пак обновился у вас, а у остальных нет. У них в кэше старый файл под тем же URL и с тем же хешем. Переименуйте файл и обновите оба свойства.

Сервера нет в списке вообще. Это не проблема MOTD. Проверьте, что сервер запущен, что порт в записи клиента - игровой и что enable-status равен true. Более широкая версия этого разбора есть в статье server.properties простыми словами.

FAQ#

Какой длины может быть MOTD?

Жёсткого предела, в который вы упрётесь, нет, но клиент обрезает каждую из двух строк примерно по 45 символов обычной ширины, а жирные символы шире. Пишите под 40 и проверяйте в настоящем клиенте, а не считайте.

Можно ли изменить MOTD без перезапуска?

Из server.properties - нет, он читается при запуске. Плагин MOTD может менять его на лету, а в Paper для этого обычно достаточно перезагрузки конфига именно этого плагина. Надёжный путь - изменить файл и перезапустить.

Куда именно кладётся server-icon.png?

В корневой каталог сервера, рядом с server.properties, eula.txt и папкой мира. Не в plugins/ и не в папку мира. В панели это верхний уровень файлового менеджера.

Нужен ли хеш SHA-1 для ресурспака?

Чтобы работало - нет, а на практике - да. Без него каждый игрок перекачивает пак при каждом входе. С ним загрузка происходит один раз, и клиент использует свою копию, пока хеш не изменится.

Почему некоторые игроки входят вообще без пака?

Потому что в записи вашего сервера в их клиенте ресурспаки отключены, что автоматически отклоняет запрос. Если require-resource-pack равен false, они заходят без него, и вам никто об этом не сообщает; если true, их отключают, и они винят сервер.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000