Фабрика размером с галактику: как я утопил 2 планеты в Солнце и сломал лимиты движка Factorio (Часть 2)
Привет снова, инженеры!
В прошлом посте я рассказывал, как наивная идея «собрать мега-сборку на Space Age» обернулась тремя месяцами раскопок в Lua и борьбой с рецептурным адом и UPS.
Сегодня хочу рассказать про вторую сторону этой медали: космическую навигацию, войну с авторами модов и баг, из-за которого игра вылетела с ошибкой, в существование которой я сначала вообще отказался верить.
Боль №3: Космос сошел с ума, или как вытащить планеты из Солнца
Когда базовые цепочки на Наувисе наконец заработали, пришло время взглянуть наверх — на звездную карту. В сборке сейчас суммарно больше шестидесяти космических тел (оригинальные миры, кастомные планеты, луны и орбитальные платформы).
Открываю карту галактики и наблюдаю прекрасное:
Планеты-камикадзе внутри звезды.
В самом центре системы ярко сияет главное солнце. А прямо внутри его текстуры, в пылающей фотосфере, беззаботно нарезают круги две орбитальные станции с солнечными коллекторами. Они буквально спавнились внутри диска звезды на нулевом радиусе.
Пришлось лезть в data-final-fixes.lua, вспоминать полярные координаты, пересчитывать радиусы орбит и аккуратно выводить эти станции наружу, чтобы они вращались вокруг звезды, как нормальные рукотворные объекты, а не жарились в термоядерном аду.Черная дыра вместо созвездий.
Вторая проблема — мододелы обожают делать крутые планеты, но совершенно не думают, как они выглядят вместе. В итоге за пределами Солнечной системы висели кучки планет посреди абсолютной черной пустоты. Ни звезд, ни ориентиров — просто летающие шары в темном подвале.
Чтобы придать космосу масштаб и логику, я разметил карту на 5 удаленных звездных секторов («Кузница», «Океанический фронтир», «Крио-рубеж», «Энергетический сектор» и «Сингулярность Предтеч») и прописал каждому сектору свое яркое солнце-ядро. Теперь у дальних систем есть центр гравитации, а у космических кораблей — понятная навигация.
Боль №4: Обновление модов — игра в русскую рулетку на 475 патронов
Сборка живет, Factorio 2.0/2.1 активно допиливается, и разработчики модов тоже выкатывают обновления. На днях я решил провести ревизию: скачал свежие версии сразу для 63 модов.
Наивный расчет: «Авторы ведь исправили баги, станет только стабильнее».
Реальность: игра перестала запускаться примерно шестью разными способами.
Искусственные заборы. Автор одного популярного мода на луну просто взял и добавил в манифест зависимостей строчку ! janus (запрет на запуск с планетой Янус). Почему? «Ну, мне показалось, они тематически не очень сочетаются». То, что у сотен игроков они прекрасно сосуществовали, автора не смутило.
Привет из 2020 года. Скрипт подтянул с портала мод версии 1.1.6, посчитав его новее нашей 1.1.5. Только вот 1.1.5 была неофициальным свежим портом под Factorio 2.1, а 1.1.6 оказалась архивной версией пятилетней давности для старой игры.
Фатальный nil. В библиотеке тепловых расчетов разработчик в патче решил причесать код интерфейса и… случайно снес строчку проверки if not storage.players. Итог: при любой попытке загрузить существующую карту движок пытается опросить несуществующего игрока и вываливается в Windows с крашем attempt to index field '?' (a nil value).
Пришлось вручную тестировать каждый чих, возвращать стабильные версии и патчить чужие «исправления».
Боль №5: Предел рекурсии Wube Software (21 > 20)
Но главный босс ждал меня на финальной стадии компиляции. Когда все зависимости сошлись, движок Factorio выдал лог, от которого у меня дернулся глаз:
Error while loading space-location prototype "erimos-prime": Too deep recursion for localised string: 21 > 20 (limit)
Что произошло?
В движке Factorio 2.1 есть жесткое ограничение: дерево локализованной строки (текста описания объекта) не может быть глубже 20 уровней вложенности.
А теперь следите за руками: есть планета Эримос Прайм.
Первый мод дописывает ей свойства атмосферы: desc = { "", desc, "Текст 1" } (глубина 2).
Второй мод добавляет статус орбитальной обороны (глубина 3).
Третий мод вешает расчет загрязнения (глубина 4).
Четвертый добавляет инфу о ресурсах…
К моменту, когда до планеты добрался 21-й мод со своим микро-описанием, строка превратилась в матрешку из 21 вложенной таблицы. И C++ парсер Wube просто выкинул белый флаг: «Лимит рекурсии превышен, я закрываюсь».
Лечилось это написанием собственного санитайзера в конце загрузки: скрипт пробегает по описаниям планет, рекурсивно раскручивает эту чудовищную матрешку, склеивает текстовые куски и запаковывает все обратно в плоский массив глубиной 1.
Что в сухом остатке?
На данный момент:
Все 475 модов засинхронизированы.
Контрольный прогон через движок выдал заветное: Prototype list checksum: 1364196656, exit code: 0.
Сохранения загружаются без единого предупреждения, а полет между секторами наконец-то похож на настоящее космическое путешествие, а не на блуждание по темному чулану.
Дальше останется лишь по ходу игры аккуратно полировать баланс отдельных рецептов.
А пока — чертежи готовы, поезда заправлены.
Фабрика должна расти.









