В каждой игре Workshop устроен по-своему, но сбоев всегда одни и те же пять, только в разном порядке: у сервера есть предмет, которого нет у клиента; у клиента версия новее, чем у сервера; обязательная зависимость так и не попала в список; автор выпустил обновление, о котором никто не просил; или при первом запуске на середине четырёхгигабайтной загрузки закончилось место на диске. Стоит понять небольшое число механизмов под всем этим - что такое id предмета, куда SteamCMD всё складывает и кто говорит игроку, что скачивать, - и все пять сбоев диагностируются за минуту, а не за целый вечер.
Что такое предмет Workshop на самом деле#
Предмет Workshop - это опубликованный файл с числовым id, и только это число имеет значение. Это цифры после ?id= в адресе:
https://steamcommunity.com/sharedfiles/filedetails/?id=1753134636 ^^^^^^^^^^Каждый предмет принадлежит ровно одной игре. Названия не уникальны, не постоянны и ни одному конфигу не нужны. Коллекции сами являются опубликованными файлами со своими id. Как и сохранения, мутаторы и наборы карт, которые оказываются двумя предметами, а не одним.
Предмет можно посмотреть без ключа API, и это по-настоящему полезная привычка перед тем, как добавлять что-то на сервер:
$ curl -s -X POST \ https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/ \ -d 'itemcount=1&publishedfileids[0]=1753134636'В ответе есть название, consumer_app_id, file_size и time_updated. Для этого id это карта Hawaii для Unturned, приложение 304930, около 300 МБ, последнее обновление - отметка времени, которую можно сравнить с копией на вашем сервере. Два из этих четырёх полей отвечают на вопросы, о которых обычно гадают: тот ли это вообще предмет для нужной игры и сколько места на диске вы сейчас потратите.
Четыре способа доставить содержимое на сервер#
Способов всего четыре, и знание того, каким пользуется ваша игра, подсказывает, где искать, когда чего-то не хватает.
- Сервер скачивает всё при запуске по списку из собственного конфига. Вы вписываете id в файл, сервер получает их при старте. Так работают Unturned, Project Zomboid, Killing Floor 2 и Garry's Mod. Проще всего, но и контроля над временем меньше всего.
- Вы скачиваете через SteamCMD и раскладываете сами. Этого ждут Arma 3, DayZ, Squad и Left 4 Dead 2. Больше всего контроля, больше всего работы, и это путь, для которого нужен аккаунт Steam с этой игрой.
- Вы загружаете файлы вручную. Предмет со стороны сервера никогда не касается Steam. Это работает и ломает клиентскую сторону, потому что серверу нечего сообщить клиенту.
- Игра вообще не использует Steam Workshop. Insurgency: Sandstorm использует mod.io. ARK: Survival Ascended использует CurseForge. Minecraft не использует ни то ни другое. Знание этого экономит час поисков страницы Workshop, которой не существует.
| Игра | Как сервер получает предметы | Куда записываются id |
|---|---|---|
| Unturned | Скачивает при запуске | File_IDs в WorkshopDownloadConfig.json |
| Project Zomboid | Скачивает при запуске | WorkshopItems= и Mods= в <server>.ini |
| Killing Floor 2 | Скачивает при запуске | ServerSubscribedWorkshopItems= в KFEngine.ini |
| Garry's Mod | Подключает коллекцию при старте | +host_workshop_collection и -authkey |
| ARK: Survival Evolved | Управляется сервером | -automanagedmods и ActiveMods= |
| Left 4 Dead 2 | SteamCMD, затем addons/ | workshop_download_item 550 <id> |
| Arma 3 | SteamCMD, аккаунт-владелец | workshop_download_item 107410 <id>, затем -mod= |
| DayZ | SteamCMD, аккаунт-владелец | workshop_download_item 221100 <id>, затем -mod= |
| Squad | SteamCMD | workshop_download_item 393380 <id> |
Обратите внимание на app id в последнем столбце. Содержимое Workshop принадлежит игре, а не инструменту выделенного сервера, поэтому 107410 - это Arma 3, а не 233780, с которым вы устанавливали сервер. Это то же различие, на котором спотыкаются при создании токенов входа Steam для игровых серверов, и причина та же.
Загрузка предметов через SteamCMD#
Команда принимает app id игры и один id предмета:
$ ./steamcmd.sh +force_install_dir /srv/arma3 \ +login myspareaccount \ +workshop_download_item 107410 463939057 \ +quitПредмет оказывается в предсказуемом месте внутри каталога установки:
/srv/arma3/steamapps/workshop/ appworkshop_107410.acf what was fetched, and when content/107410/463939057/ the item itselfappworkshop_<appid>.acf - это манифест. Когда предмет обновился в Steam, а сервер упорно держит старую копию, стандартное решение - удалить этот файл: при следующей загрузке сравнивать будет не с чем, и всё скачается заново.
Про эту команду стоит знать три вещи, прежде чем писать скрипт. Анонимный вход работает для одних игр и не работает для других, а игры, серверные инструменты которых требуют аккаунта с игрой, почти всегда требуют его и здесь - ошибка в обоих случаях No subscription. Крупные предметы довольно часто обрываются по таймауту и успешно скачиваются со второй попытки, так что повтор в скрипте - не паранойя. И загрузка - это лишь половина дела: Arma 3 и DayZ потом требуют переименовать папку или сделать на неё символическую ссылку @ModName в корне сервера и скопировать .bikey каждого мода в папку keys/ сервера, иначе клиентов отклонят из-за неподписанного аддона. О сопутствующих аргументах рассказано в статье SteamCMD простыми словами, а полная последовательность для DayZ - в сервере DayZ и модах.
Коллекции и то, чего SteamCMD с ними не умеет#
Коллекция - это опубликованный файл со списком других опубликованных файлов. Игроки подписываются на неё одним щелчком, поэтому списки модов обычно распространяют именно так.
SteamCMD не умеет раскрывать коллекцию. workshop_download_item понимает id отдельных предметов и больше ничего. Обойти это можно двумя способами. Некоторые игры раскрывают коллекции сами - +host_workshop_collection в Garry's Mod принимает id коллекции и получает её содержимое, об этом рассказано в статье аддоны Workshop и FastDL в Garry's Mod. Для всего остального спросите у Steam:
$ curl -s -X POST \ https://api.steampowered.com/ISteamRemoteStorage/GetCollectionDetails/v1/ \ -d 'collectioncount=1&publishedfileids[0]=2521187158'В ответе есть массив children, по одной записи на предмет, у каждой свой publishedfileid. Ключ API не нужен. Передайте это в файл конфигурации, и коллекция раскрыта.
Стоит ли это делать - другой вопрос. Коллекция, которая вам не принадлежит, - это список модов под чужим контролем. Если владелец добавит предмет, ваш сервер подхватит его при следующем перезапуске; если уберёт - сервер его потеряет. Для сервера, который важен, прочитайте коллекцию один раз и зафиксируйте отдельные id. Для сервера, на котором вы с друзьями играете по четвергам, удобство перевешивает.
Зависимости - вторая проблема того же рода. У многих предметов на странице Workshop указаны необходимые предметы, но ни SteamCMD, ни большинство игр не разрешают их за вас. В Project Zomboid общей библиотеке нужен собственный номер в WorkshopItems и собственное имя в Mods - это две разные строки из двух разных мест, и статья моды Project Zomboid и Workshop разбирает это как следует. В Unturned пользовательская карта - это нередко предмет с ландшафтом плюс набор ассетов, и если указать только ландшафт, игроки получат мир, где вместо объектов красный текст ошибок.
Как содержимое попадает к игроку#
Именно здесь живёт большинство сбоев, которые видят игроки, потому что игры принципиально различаются, а подсказки, в какой вы модели, никто не даёт.
Четыре модели, и ваша игра использует ровно одну из них:
- Steam доставляет автоматически. Клиентам Unturned и Project Zomboid при подключении сообщают, какие предметы нужны серверу, и они скачивают их без участия игрока. Это лучший случай, и поэтому ручная загрузка файлов на такие серверы ломает их: серверу нечего сообщить клиенту.
- Игрок должен подписаться сам. Яркий пример - Left 4 Dead 2. Сервер не может выдать кампанию игроку, у которого её нет, а быстрой загрузки для кампаний VPK не существует. Подписываются все или не играет никто.
- Это делает за них лаунчер. Игроки DayZ пользуются DayZ Launcher, который читает список модов, объявленный сервером, подписывается на него и собирает подходящую командную строку. Именно поэтому порядок модов и ключи на сервере должны быть верными: лаунчер автоматизирует клиентскую сторону и громко падает, когда две стороны расходятся.
- Сервер оставляет всё себе. Содержимое только для сервера - инструменты администратора, генераторы лута, логирование - идёт в отдельный список:
-serverMod=в Arma 3,-servermod=в DayZ. Если положить серверный мод в клиентский список, каждый входящий игрок скачает то, чем никогда не сможет воспользоваться.
Правило, которое следует из всех четырёх: для каждого предмета решите, нужен ли он клиенту, и положите его в правильный список. Большинство жалоб «игроков кикает при входе» - это один предмет не в том списке.
Обновления, версии и поломка посреди сессии#
Авторы Workshop публикуют, когда им вздумается. Вас никто не спрашивает, а в большинстве игр вам никто и не сообщает.
Что произойдёт дальше, зависит от того, кто обновился первым. Клиент обновляется автоматически через Steam; у сервера та копия, которую он скачал в последний раз. Когда они различаются, одни игры кикают игрока с ошибкой версии, а другие пускают и тихо рассинхронизируют, что хуже. Некоторые игры обрабатывают это намеренно: Unturned следит за изменениями размещённой карты, потому что браузер серверов использует номера версий карт, чтобы проверить совместимость до подключения игрока, и когда изменение замечено, предупреждает игроков в чате и по таймеру останавливает сервер, чтобы перезапуск подхватил новую версию.
Две привычки предотвращают большую часть этого:
- Зафиксируйте список и обновляйте его намеренно. Берите отдельные id предметов, а не следуйте за чужой коллекцией, и меняйте их тогда, когда решите сами, желательно вместе с перезапуском, о котором вы объявили.
- Храните копию рабочего содержимого. Перед обновлением скопируйте дерево
steamapps/workshop/content/<appid>/или сделайте резервную копию. Это же единственная защита на случай, если автор скроет или удалит предмет, от которого вы зависите: как только он исчез из Workshop, новый игрок его не получит, а ваш сервер, возможно, не сможет скачать его повторно. Резервная копия, которую никто не восстанавливал, - это гипотеза, и весь смысл статьи о резервных копиях в этом.
Патчи игры - вторая ось. Крупное обновление игры делает моды недействительными, пока их авторы не пересоберут, а сервер, настроенный обновляться автоматически в день патча, - это сервер, на который в день патча никто не зайдёт. Отключите автообновление на сервере с большим числом модов, запишите версии, которые работали, и держите под рукой статью что делать, когда обновление мода всё ломает.
Диск, время загрузки и таймауты первого запуска#
Содержимое Workshop немалого размера, и оно лежит на том же томе, что и сервер. Одна крупная карта Unturned - несколько сотен мегабайт; набор модов Arma 3 с ACE, CBA и паком RHS - десятки гигабайт; коллекция Garry's Mod, которую никто не чистил, занимает столько, сколько успела набрать с 2019 года.
Из этого следует три вещи.
Первая загрузка медленная и похожа на сбой. Сервер запускается, начинает получать несколько гигабайт и почти ничего не пишет, пока это делает. Если у супервизора или панели есть таймаут запуска, он может убить процесс посреди загрузки, что перезапускает его, а тот начинает загрузку заново. Если кажется, что сервер уходит в цикл сбоев при первом запуске после добавления модов, посмотрите на консоль, прежде чем что-то менять, - скорее всего, загрузка ещё идёт. Как отличить настоящий цикл перезапусков от этого, рассказано в статье почему игровой сервер постоянно перезапускается.
Удаление предмета не освобождает диск. Уберите id из списка, и файлы останутся на месте на неопределённый срок. Время от времени очищать steamapps/workshop/content/<appid>/ или собственную папку кэша игры - это настоящая уборка на тарифе с 20 GB.
Обновлениям нужен запас. SteamCMD размещает загружаемое на том же томе, который обновляет, так что оставляйте 20-30 процентов свободными. Диск, рассчитанный ровно под содержимое, - это диск, на котором следующее обновление не пройдёт.
На RE:NODE в каждом тарифе указан диск, а панель показывает графиком его заполнение относительно этого лимита рядом с памятью и CPU, так что список модов, тихо съедающий том, виден до того, как станет аварией. Моды и плагины загружаете вы сами через файловый менеджер или по SFTP либо их получает собственная поддержка Workshop в игре - списка разрешённых модов нет.
Предмет Workshop - это чужой код#
К картам и текстурам этот раздел не относится. К значительной части содержимого Workshop относится вполне. Аддоны Garry's Mod содержат Lua, который выполняется на вашем сервере. Моды Arma 3 содержат SQF. Моды Project Zomboid содержат Lua. Запуск такого мода - это запуск чужого кода с привилегиями вашего сервера, над данными вашего сервера, от имени вашего сервера.
Это цепочка поставок, и действуют обычные правила гигиены цепочки поставок:
- Отдавайте предпочтение предметам с историей. Автор с трёхлетним журналом изменений и трекером задач - это другой риск, чем аккаунт, созданный на прошлой неделе.
- Держите список коротким. Каждый предмет - это обновление, за которым надо следить, и возможная причина, когда что-то ломается. Двенадцать модов, выбранных вами, лучше сорока, которые кто-то посоветовал.
- Читайте, что изменилось. Не каждую строку, но журнал изменений перед тем, как ставить обновление на работающий сервер.
- Делайте резервную копию перед добавлением. Добавлять легко; а мод, который незаметно переписал ваши таблицы лута, - это как раз то, что не отменить.
- Осторожно с тем, что вы ему доверяете. Если у мода есть серверный код, он может прочитать всё, что может прочитать сервер, - включая токен входа, лежащий в файле конфигурации.
Об эксплуатационной стороне подробнее в статье как содержать сервер с модами в чистоте. Сторону хостинга описать просто: один контейнер на сервер, CPU жёстко ограничен долей, которую вы купили, а на пределе памяти контейнер останавливается и чисто перезапускается, а не уходит в своп. Список модов, переросший тариф, поэтому проявляется как повторяющиеся перезапуски, а не как сервер, который работает всё медленнее и медленнее. Наблюдатель замечает и такую картину - три перезапуска за час вызывают предупреждение на странице сервера и автоматически открывают тикет, - так что о моде, ведущем к циклу сбоев, вы узнаете не от игрока.
Устранение неполадок#
Игроков выбрасывает на экран ошибки при входе. В списке сервера нет обязательного предмета. Обычно это набор ассетов карты или зависимость, которая упомянута на странице предмета, а в конфиге отсутствует.
Сервер игнорирует новый id предмета. Почти в каждой игре список читается при запуске. Перезапустите.
Предмет обновился в Steam, а у сервера всё ещё старая копия. Удалите steamapps/workshop/appworkshop_<appid>.acf и перезапустите либо удалите папку содержимого этого предмета.
`workshop_download_item` завершается с `No subscription`. Для Workshop этой игры анонимный вход не принимается. Используйте аккаунт, у которого есть эта игра.
`workshop_download_item` завершается таймаутом. Часто бывает на крупных предметах. Запустите снова; со второй попытки обычно всё проходит.
Мод есть на диске, а игра ведёт себя так, будто его нет. В большинстве игр загрузка и подключение - отдельные шаги. Project Zomboid нужен номер в WorkshopItems и имя в Mods; Arma 3 нужна папка в -mod=; Garry's Mod нужен предмет в коллекции, которую подключает сервер, а не просто в списке клиентской загрузки.
Коллекция изменилась, и сервер изменился вместе с ней. Так коллекции и работают. Если это не то, чего вы хотели, зафиксируйте отдельные id.
Игроки скачивают мод, которым не могут воспользоваться. Серверный мод попал в клиентский список. Перенесите его в -serverMod= или аналог.
FAQ#
Где на сервере оказываются файлы Workshop?
Внутри каталога установки, в steamapps/workshop/content/<gameappid>/<itemid>/, с манифестом в steamapps/workshop/appworkshop_<gameappid>.acf. Игры, которые подключают содержимое сами, часто затем копируют или кэшируют его в собственное место, например garrysmod/cache/workshop/ в Garry's Mod.
Может ли SteamCMD скачать коллекцию целиком?
Нет. Он понимает только id отдельных предметов. Либо игра раскрывает коллекцию сама, как Garry's Mod, либо вы раскрываете её через публичный веб-API GetCollectionDetails и записываете полученные id в конфиг.
Должны ли игроки подписываться на моды, которые использует мой сервер?
Это целиком зависит от игры. Unturned и Project Zomboid автоматически передают список клиентам при входе. Left 4 Dead 2 - нет, там каждый игрок должен подписаться сам. С игроками DayZ работает DayZ Launcher. Выясните, какую модель использует ваша игра, прежде чем писать инструкцию для входа.
Почему мой сервер сломался после обновления мода?
Потому что автор выпустил новую версию, а ваш сервер ещё работал на старой, либо наоборот. Зафиксируйте id, перезапускайте намеренно, а не автоматически, и храните копию папки содержимого, которая работала, чтобы можно было вернуть её на место.
Какой app id использовать для загрузок Workshop?
Игры, а не инструмента выделенного сервера. Содержимое Arma 3 - это 107410, хотя сервер устанавливается с 233780; содержимое Left 4 Dead 2 - это 550, хотя сервер устанавливается с 222860.
Сколько места на диске оставить под моды?
Больше, чем занимает содержимое, потому что обновления размещаются на том же томе. Перед добавлением проверьте file_size каждого предмета через публичный API, прибавьте запас 20-30 процентов и очищайте содержимое удалённых предметов, потому что само оно не удаляется.




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