Alt-F4 #18 — Путь к Clusterio 2.0

опубликовали Hornwitser, DedlySpyder, stringweasel, Nanogamer7, Conor_, Therenas, nicgarner, Firerazer

По мере того как год подходит к концу, мы выбрали две темы, связанные с модами, для 18-го выпуска Alt-F4. Во-первых, Hornwitser дает нам некоторое представление о долгом прогрессе в разработке Clusterio 2.0 и о проблемах, которые он ставит. Затем DedlySpyder рассказывает о процессе разработки простого мода и проблемах совместимости, с которыми он сталкивается.

Путь к Clusterio 2.0 Hornwitser

Я хочу рассказать историю о том, как я потратил год на разработку Clusterio 2.0, до релиза которой еще предстоит пройти долгий путь. Если вы раньше не слышали о Clusterio, это серверное программное обеспечение с открытым исходным кодом, написанное Danielv123 (при участии около 30 других), которое позволяет модам взаимодействовать между серверами. Это, пожалуй, наиболее известно благодаря событию Clusterio 60k в 2018 году, когда сундуки с телепортацией использовались для передачи предметов между примерно 46 серверами Factorio, чтобы построить ванильную фабрику, которая могла бы делать 60k науки в минуту. Эти сундуки телепортации работают как сундуки активной поставки и запроса; один удаляет элементы из игры и помещает их в общее облачное хранилище, а другой берет элементы, запрошенные из этого облачного хранилища, и помещает их в игру.

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

В июле 2019 года состоялось мероприятие The Gridlock Cluster. Вместо телепортационных сундуков для транспортировки предметов между серверами были поезда, которые могли телепортироваться с края одного сервера на край другого сервера с помощью телепортационных остановок поездов. Код для телепортации поездов был реализован Godmave как плагин для Clusterio.

К сожалению, в коде возникли проблемы, и я здесь опишу ситуацию.

Скромное начало

Я начал взламывать кодовую базу Clusterio еще в июле 2019 года, пытаясь помочь команде Gridlock с многочисленными проблемами, которые у них были. Серверы падали постоянно, у игроков были проблемы, и новые ошибки и проблемы, казалось, появлялись с каждым часом. Это было неспокойно, но и весело. Событие вызвало у меня интерес к коду Clusterio, и после него я взял на себя задачу улучшить этот код для следующего события. Это оказался гораздо более масштабный проект, чем я мог вообразить.

Я стабильно работал над Clusterio 2.0 вот уже около 16 месяцев, и моя оценка того, когда это будет сделано, все еще та же «всего пара месяцев», с которой я начинал. Несмотря на это, моя мотивация продолжать работать над этим остается сильной, и одна из вещей, которые меня особенно мотивируют, — это проверить всю эту работу, организовав свое собственное мероприятие Clusterio. Я опубликовал на Reddit тизер того, что задумал, и сейчас цель — запустить его в начале следующего года. Возможно, январь, но когда все будет готово, покажет время.

Но вернемся к тому, с чего для меня все началось. Я устанавливал Clusterio на свой сервер, пытаясь настроить свой собственный тестовый кластер, чтобы работать над исправлением проблем, возникающих в кластере Gridlock. Одна из первых вещей, которые я заметил, — это тысяча пакетов, которые он вытащил в качестве зависимостей, занимая более 300 МБ дискового пространства. Потребность в таком большом количестве библиотек для этого проекта казалась абсурдной. Node.js был тогда для меня в новинку, и хотя сейчас я узнал, что на самом деле это не такое уж необоснованное количество зависимостей для приложения Node.js, их все же много. Это было признаком того стиля разработки, который использовался в проекте: нисходящий подход к добавлению функций любым способом, наиболее простым и быстрым для реализации на месте.

Такой стиль разработки привел к накоплению большого технического долга, и я имею в виду очень много. Технический долг — это термин, который часто используют при разработке программного обеспечения. Идея заключается в том, что выбор ярлыков при разработке для экономии времени часто приводит к увеличению объема работы по поддержке и расширению базы кода. В некотором смысле можно сказать, что Clusterio был скорее набором хаков, наваленных друг на друга, чем хорошо продуманным и структурированным проектом. Одним из ярких примеров этого было включение и использование четырех разных HTTP-клиентов в одном исходном файле. Обычно одного такого клиента более чем достаточно для всего проекта, но предположительно некоторые вещи было легче делать с одним клиентом, чем с другими, и со временем накапливались разные клиенты.

Итак, мне нужно было работать над улучшением и очисткой кодовой базы Clusterio. Одной из первых вещей, которые я сделал, было сокращение этой тысячи или около того зависимостей. Оказалось, что большая часть этого на самом деле не нужна для работы Clusterio. Примерно половину составляли инструменты разработки, которые не нужно было устанавливать в производственной среде, а четверть — это то, что я бы назвал быстрыми решениями: большие библиотеки, задействованные для использования одной функции из них. Многие из этих библиотек было тривиально удалить, либо переопределив функцию локально, либо используя другую библиотеку, которая уже была зависимостью проекта. В конце концов, мне удалось избавиться от необходимости иметь около 700 пакетов (244 МБ), хотя следует отметить, что большинство из них были зависимостями от зависимостей.

Следующей проблемой, которой я занялся, было автоматическое тестирование. Если вы не знакомы с автоматическим тестированием, идея написания кода заключается в том, чтобы убедиться, что основной код работает должным образом и не нарушается при будущих изменениях. Автоматическое тестирование — это своего рода краеугольный камень для написания надежного кода, и хотя в какой-то момент были настроены обширные тесты, они не работали, когда я начал работать над проектом. Это еще один пример того, как технический долг поднимает свою уродливую голову. Ведение тестов и добавление новых тестов для покрытия нового кода — это дополнительная работа; пропуск этой работы — это ярлык.

После того, как тесты были исправлены, я сосредоточился на очистке самого кода. Такие вещи, как исправление битого кода, удаление неиспользуемого или устаревшего кода и рефакторинг плохого кода в немного менее плохой код. Одно из изменений, которое начало обретать форму, заключалось в переносе кода сундуков телепортации из основной базы кода в отдельный плагин. Поскольку Clusterio — это в первую очередь серверное программное обеспечение, делающее возможным межсерверное взаимодействие модов, наличие этих телепортационных сундуков, также называемых Clusterio, сбивает с толку, когда мы все больше и больше ожидаем, что Clusterio будет использоваться для других вещей, кроме этих сундуков. Поэтому мы также решили переименовать функцию телепортации предметов через магические сундуки в подпространственное хранилище. Пока я этим занимался, я также решил заменить эти шаткие небесные сундуки и спрайты коллекционной сети чем-то более подходящим для хранения подпространств.

Тем не менее, они по-прежнему являются скорее заполнителем, поскольку я не особо разбираюсь в 3D, когда дело касается текстурирования и механического моделирования. Я нашел время, чтобы настроить автоматизированную цепочку инструментов с Blender для рендеринга, обрезки и вывода спрайтов в мод. Вы знаете, как обстоят дела с программистами: автоматизируют все.

Исправление сохранений

По мере продолжения моей работы первым серьезным улучшением, над которым я работал, было исправление сохранений, но прежде чем я расскажу об этом, я хочу дать некоторый контекст проблемы, которую оно пытается решить. Движок игры позволяет изменять поведение игры с помощью кода Lua с помощью модов и / или сценариев. Моды загружаются при запуске игры, и для их обновления требуется перезапуск игры. Сценарии — это код Lua, упакованный с сохранениями игры, и для перехода на другой код сценария требуется только загрузить другое сохранение.

Когда в код сценария включается изменяющее игру поведение, это часто называют программным моддингом, поскольку вам не нужно загружать какие-либо моды и перезапускать Factorio, чтобы подключиться к серверу с использованием такого кода сценария. Хотя обновить мод и продолжить существующее сохранение легко, с кодом сценария все не так просто. По сути, есть три способа обновить код сценария в сохранении, которые я перечислю примерно в порядке сложности реализации:

  • Для сценариев, распространяемых через мод, можно добавить в мод сценарий миграции, который обновляет сценарий при обновлении мода. Хотя это довольно просто сделать, но у него есть серьезный недостаток, заключающийся в необходимости установки мода для запуска миграции.
  • Вы можете заменить код сценария, хранящийся в сохранении, пока игра не запущена. Это то, что я называю исправлением сохранений, и это относительно просто сделать, поскольку сохранения представляют собой обычные zip-файлы, а код Lua хранится в них как обычные текстовые файлы.
  • Вы также можете использовать динамическую природу Lua для загрузки и выполнения нового кода во время выполнения игры и сценария. Этот вариант, безусловно, самый сложный, но он дает возможность вносить исправления в игру во время работы карты. Недостатком является то, что его сложно реализовать и исправить, что увеличивает вероятность того, что что-то пойдет не так. Кроме того, единственный способ отправить данные в запущенную игру — использовать команды, что становится проблематичным, если они длинные.

Для Gridlock Cluster третий вариант был реализован с помощью сценария, называемого Hotpatch (также известного как серверный многомодовый сценарий). Концептуально Hotpatch — очень крутая штука; он позволяет загружать код, подобный модам, во время работы игры, и он будет выполнять этот код в среде, имитирующей среду мода Factorio. Но при использовании Hotpatch были серьезные проблемы: он плохо документирован, что затрудняет правильное использование; реализация была неполной и содержала ошибки; и самая неприятная проблема заключалась в том, что обновленный код сценария отправлялся в виде длинных команд при запуске. Это означало, что если игроки присоединялись к серверу во время его запуска и в процессе отправки этих длинных команд для обновления сценария, все шло наперекосяк, что было лишь одним из многих способов отказа серверов в Gridlock.

Хотя многие проблемы с Hotpatch были исправлены, сложность и трудности работы с ним преподали мне ценный урок: наличие расширенных возможностей, таких как возможность исправлять код во время выполнения, или технических чудес любого рода в этом отношении, не всегда оправдывайте сложность и проблемы, с которыми сталкиваются такие передовые системы. Я испытал это на собственном опыте, когда пытался исправить проблемы, в которых участвовал Hotpatch: все в команде (включая меня) изо всех сил пытались понять систему и способы решения проблем с ней.

По этой причине я решил заменить роль Hotpatch в Clusterio на что-то более простое: сохранение исправлений. Это менее эффективное решение с большими ограничениями в написании кода, но простота его работы более чем компенсирует это.

Сломать все

После того, как я реализовал исправление сохранений, стало ясно, что требуется капитальный ремонт кода. Особенно болезненным моментом в Clusterio было полное отсутствие удаленного управления. Если вы хотите запустить сервер Factorio, который является частью кластера, вам необходимо войти в систему на компьютере, на котором он размещен, и вручную запустить его через любой диспетчер процессов, который вы выберете для использования, то же самое происходит, если вы хотите изменить какие-либо настройки для этого сервер. Подобное управление кластером болезненно, и этот урок был извлечен на собственном горьком опыте на мероприятии Clusterio 60k.

Для Gridlock панель управления игровым сервером Pterodactyl использовалась для удаленного управления серверами; хорошая идея, которая оказалась причиной множества проблем. Но это история для другого раза.

Возможность удаленного управления серверами Factorio в Clusterio была желанной функцией в течение долгого времени, и были попытки реализовать ее. Эти попытки были скорее запоздалыми, и из-за того, как был структурирован код (запуск одного сервера Factorio для каждого процесса Node.js), стало очень трудно реализовать какое-либо разумное удаленное управление без капитального ремонта кода и взлома. все в процессе.

Естественно, я все сломал и внедрил удаленное управление.

Принцип работы Clusterio 2.0 заключается в том, что подчиненный процесс запускается на каждом компьютере, на котором вы хотите разместить серверы Factorio. Эти серверы Factorio называются экземплярами в Clusterio, и подчиненный процесс подключается к главному серверу и слушает команды для создания и запуска экземпляров. Несколько экземпляров могут работать одновременно на ведомом устройстве, что означает, что вам нужно настроить только одно ведомое устройство для каждого компьютера, на котором вы хотите разместить серверы Factorio, и на этих компьютерах должен запускаться только один процесс Node.js.

Еще одна вещь, которую пришлось изменить, — это способ связи Clusterio между компьютерами. В версии 1 это по большей части обрабатывается главным сервером, на котором размещен HTTP-сервер и отвечает на запросы к нему. Проблема заключается в том, что главный сервер не может отправлять сообщения на другие компьютеры, а только отвечать на запросы, отправленные ему с других компьютеров; вот как работает HTTP. Чтобы обойти это, я заменил HTTP на простой протокол на основе WebSocket с полезными нагрузками JSON. WebSocket, в отличие от HTTP, позволяет обеим сторонам соединения отправлять сообщения друг другу в любое время.

Теперь, когда все сломано, это стало точкой, где действительно началась разработка 2.0. В последующие месяцы я использовал эту возможность, чтобы начать все заново.

Надеюсь, вам понравился этот краткий обзор разработки Clusterio 2.0. Как вы можете себе представить, за последние 16 месяцев в 2.0 произошло еще много вещей, которых определенно хватит, чтобы написать больше статей на эту тему. Обратите внимание, что версия 2.0 еще не готова для производственного использования, однако, если вы заинтересованы в разработке и хотите протестировать ее, посетите наш сервер Discord и репозиторий GitHub.

Возможность модификации: рождение мода DedlySpyer

Что-то, что kovarex сказал в FFF-363, запомнилось мне:

Это пример функции, которую я просто ДОЛЖЕН СДЕЛАТЬ, потому что, как только я понял, что эта функция может быть там, я почти пытался ее использовать, и меня раздражало, что ее там нет.

— kovarex

Я играл в Factorio около шести лет, но с тех пор, как начал заниматься модификациями, мне всегда нравилось возиться с игрой. Иногда, когда я играю, я вижу что-то новое, что меня немного беспокоит и для чего нет мода, чтобы это исправить. Я дойду до того момента, когда в конечном итоге просто модифицирую его сам. Обычно это заставляет меня отказываться от текущего прохождения Factorio, в основном потому, что для меня создание модов вызывает тот же зуд, что и сама игра.

Вскоре после запуска 1.0 это случилось со мной снова. Я взял последнюю версию Krastorio 2, дошел до точки силовой брони в игре и задавался вопросом, почему я не могу вращать оборудование. Конечно, я мог бы перетасовать все вокруг в моей броне, но иногда мне просто хочется нажать R и с минимальными усилиями поставить что-нибудь на место. Быстрый поиск на портале модов показал мне, что есть Rotatable Batteries от GotLag; так что это было возможно, но не для всех.

Иногда заставить мод работать в любых обстоятельствах может потребоваться уйма работы. Безопасный способ справиться с любым случаем — жестко запрограммировать свои изменения для каждой ситуации. Это определенно сработает, но требует постоянного контроля. Сделав что-то подобное в прошлом, я знаю, что это может стать довольно громоздким и трудным для чтения. Кроме того, если один из этих модов что-то меняет, моя реализация либо полностью ломается, либо несовместима с «поддерживаемым» модом. Итак, я недавно стал большим поклонником попытки сделать свои моды как можно более динамичными, чтобы избежать этого. Теоретически это также должно сэкономить массу времени, но это не всегда срабатывает.

Однако эта реальность — то, что мне нравится в Factorio; «О, но мне нужно сделать это». Это не весело, если это просто добавление другой зависимости мода путем добавления некоторой строки в список. Итак, чтобы запустить новый мод с целью иметь возможность вращать любое оборудование без необходимости постоянно поддерживать его, мне нужно было опираться на то, как Factorio загружает моды.

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

Три раза? Кажется чрезмерным, правда? На самом деле, это фантастическая идея. В вики это объясняется более подробно, но я быстро объясню это здесь. У каждого мода в порядке загрузки есть этап настроек, затем этап данных. Этап настроек не требует пояснений, а этап данных предназначен для данных прототипа, таких как элементы, сущности и рецепты. Затем этот цикл повторяется еще два раза. Моды указывают, что загружать на каждой итерации цикла. Соглашения о моддинге рекомендуют добавлять прототипы как можно раньше в этом процессе. Это позволяет модам, которые хотят неявно полагаться на другие моды, делать это, не зная, что они существуют. Например, базовый мод Factorio делает это для бочек с жидкостями.

Вот как в сообществе появились гигантские модификации, полностью переработавшие все рецепты; они просто делают это на более позднем этапе обработки данных для каждого рецепта в игре. Никаких больших списков модов, требующих обслуживания, никакого «Этот мод нужно загружать в последнюю очередь».

Вот как я могу заставить мой мод вращать любое оборудование. Я могу просто перенести свои проверки на оборудование, для которого требуется перевернутая версия, на более поздний этап данных, и они должны неявно покрывать все оборудование в игре. Мне не нужно называть модификации X, Y и Z как зависимости, или чтобы игрок мог управлять чем-либо на их стороне; это просто работает. Нет постоянного управления сменой имени, если только не возникнет более сложная проблема, которую я буду рад отслеживать.

Учитывая все это, через несколько дней и заброшенное наполовину законченное сохранение Krastorio, родилось Rotatable Equipment .

Содействие

Как всегда, мы ищем людей, которые хотят внести свой вклад в Alt-F4, будь то отправка статьи или помощь с переводом. Если у вас есть что-то интересное, чем вы хотите в изящной форме поделиться с сообществом, то это место для вас. Если вы не совсем уверены в этом, мы с радостью поможем, обсудив идеи содержания и вопросы структуры. Если это похоже на то, что вас интересует, присоединяйтесь к Discord, чтобы начать!

Поскольку следующая пятница выпадает на Рождество, мы решили не выпускать выпуск на этой неделе, то есть это последний выпуск Alt-F4 в этом году! Мы с радостью вернемся к нему первого января с небольшим особенным эпизодом, посвященным тому, как проект развивался до сих пор, с мнениями различных членов команды о работе, которую они выполняли. Должно быть весело.

Comments: