Некоторое время назад я участвовал в разработке поддержки мультиплеера для одной глобальной модификации Цивилизации 5 и сегодня хотел бы поделиться здесь некоторыми подробностями о том, как устроена сетевая игра, как всё-таки запустить ее с модами, что с ней вообще не так, и как мы это фиксили.

Что за Цивилизация 5?

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

Последний официальный патч был выпущен 27 октября 2014. С тех пор Firaxis переключилась на другие части серии, но даже до сих пор достаточно много людей играют в 5 часть. Конечно, онлайн намного меньше, чем у последующих частей серии, но всё равно он достаточно большой по сегодняшним меркам, особенно для игры, которая не получает официальных патчей уже более 10 лет.

Сообщество моддеров

Одной из главных причин, почему игра до сих пор пользуется популярностью, является огромное моддерское сообщество. Сегодня более 10к+ модов доступно в Steam Workshop, а местный моддерский сабфорум насчитывает 500к+ сообщений. Моды поддерживают эту игру свежей и всё еще интересной.

На сегодняшний день практически всё в игре может быть изменено модами. Ядро игры, DLL-библиотека со всей логикой, была запаблишена для сообщества самими разработчиками. Традиционными средствами моддинга, т.е. .lua, .xml, .sql и прочими файлами можно изменить всё (почти) остальное.

Vox Populi (также известен как VP)

Как я уже сказал, на сегодняшний день доступно огромное количество модов, но "центральным" и самым популярным является мод Vox Populi (сабфорум на civfanatics, канал в Discord). Он объединяет большое количество разработчиков под "единым" курсом развития и работой над одним гига-модом. Репозиторий с кодом сегодня насчитывает более 8к коммитов и 330 звездочек, что достаточно много, как для модификации игры.

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

Если вдруг захотите попробовать, то есть вот инструкция "как играть в Цивилизацию 5 + VP", а также вот еще гайд по установке модов в принципе. Еще есть отдельный тред, касающийся сетевой игры в VP. Стоит отметить, что не рекомендуется ставить моды из Steam Workshop, так как там они часто устаревшие. Если серьезно хотите заморочиться и попробовать, то для стабильности лучше ставить напрямую .zip файлы из веток форума и GitHub.

Что и как я там кодил

Я играл в Цивилизацию 5 временами с самого момента релиза, но только с друзьями по сети. Однажды мы решили попробовать мультиплеер с модами (с чистым VP), было это где-то в 2018 году, и оно достаточно сносно работало. В 2023 мы попробовали снова и мультиплеер уже был сломан и буквально неиграбелен. Примерно с тех пор и на протяжении года я контрибьютил в VP, чтобы сделать его совместимым с мультиплеером.

Совместимость VP с игрой по сети

Причина, по которой VP перестал быть совместимым с игрой по сети, была в том, что в сообществе еще не было понимания, что влияет на совместимость и как в целом работает мультиплеер. Поэтому кодили все вообще без оглядки на игру по сети. И тестировали все только в синглплеере (ну, к слову, конкретно этот пункт здесь только потому что протестировать что-то в мультиплеере - это тот еще квест). На мультиплеер официально забили, обосновав решение тем, что никто не в курсе, как его поддерживать, да и вообще якобы неткод не заопенсоршен (спойлер: незаопенсоршена только прям низкоуровневая логика пересылки байтиков, а так всё необходимое для создания мультиплеер-совместимых модов уже было) и поэтому пофиксить ничего не получится. Поэтому моды в сетевой игре работали весьма рандомно: что-то работало, что-то нет, что-то работало, но через раз. Спрос на мультиплеер был, но как его заставить снова работать - понимания не было, поэтому никто и не занимался.

Для меня было немножко загадкой, как так получается, - ведь некоторые моды же работают нормально, да и вообще сам VP работал нормально еще в 2018. Значит, с тех пор добавили какие-то функции, которые сломали мультиплеер, и всё что необходимо, это найти их и пофиксить.

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

Архитектура сетевой игры

На всякий случай отмечу, что я не C++ разработчик и никак не связан с геймдэвом. Все описанное - просто наблюдения фаната серии, который по счастливой случайности разбирается в компьютерах.

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

Если представить себе на секунду, как в вакууме работала бы сетевая игра какой-то пошаговой стратегии, да и в принципе любой игры, то, наверное, сразу приходит на ум схема, в которой есть:

  • Хост и "владелец" состояния текущей сессии, с которым синкают свое состояние все остальные игроки. Либо выделенный сервер вместо хоста.

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

Полагаю, это "традиционная" модель, которая работает в большинстве игр, но в Цивилизации 5 модель совершенно другая.

В Цивилизации 5 как такового "эталонного" состояния у игроков в сессии формально нет. Нет ни "владельца" состояния текущей сессии, нет и выделенного сервера, на котором ранится вся логика и с которого пуллили бы состояние все участники сессии. Тут вообще никто ничего ниоткуда не пуллит, есть только пуш.

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

Если в сессии есть боты, то их действия тоже никуда не бродкастятся (потому что бродкастятся только действия реальных игроков). Их логика работы также вычисляется каждым участником сессии самостоятельно: например, бот решает "строить в городе казармы" или "строить в городе библиотеку" на основе какого-то алгоритма, который работает одинаково у каждого участника сессии, и по итогу везде бот выполняет одинаковое действие.

Как работают бродкасты
В английской версии статьи я когда-то рисовал такую схему, чтобы показать, как бродкастятся действия между игроками и как это влияет на их итоговое состояние

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

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

Например, если представить, что боты выбирали бы "строить казармы" или "строить библиотеку" на основе рандома, а не на основе четкого алгоритма, то у игрока А бот строил бы казармы, а у игрока Б он строил бы библиотеку. Действия ботов не бродкастятся между участниками сессии и состояние игры никогда никем ниоткуда не пуллится, "эталонного" состояния нет и вовсе, а потому наличие рандома в такой логике привело бы к тому, что игрок А и игрок Б играли бы как бы разную игру.

У одного игрока на экране бот был бы с казармами, у другого - с библиотекой. И дальнейшие действия бота тоже разнились бы на каждом экране и со временем эта разница накапливалась бы как снежный ком. Когда-нибудь такая сессия непременно приведет к тому, что игра крашнется.

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

Но вернемся к идеальному миру, где рандома в логике игры нет, состояние сессии вычисляется всегда одинаково у каждого участника, и по итогу все прекрасно работает. Это и есть "главное правило" стабильной сетевой игры в Цивилизации 5. И еще одно правило, что каждое действие человека нужно бродкастить на всех остальных, но это, в принципе, достаточно очевидное правило.

Как вы уже, наверное, догадались, эти правила и нарушались моддерами (и нарушались самими разработчиками в том числе), что приводило к разным состояниям игры у участников сессии, а в последствии и к вылетам. И, как выяснилось, не нарушать их - это прям вот головная боль.

Примеры кода, который делал сетевую игру невозможной

Как я уже говорил, долгое время VP разрабатывали без оглядки на работоспособность в сетевой игре. В одиночной игре все работало классно, но в сетевой не работало вообще. После вышеописанного можно понять почему - потому что рандом в логике на стабильность одиночной игры не влияет. Ну, будет бот что-то вычислять случайным образом, да и фиг с ним. И бродкастить никому ничего не нужно - новые фичи, в которых появлялись какие-то новые действия пользователя, просто кодили и все, забыв (или забив) на бродкаст в случае сетевой игры.

Но представим, что для действий пользователя реализовали корректный бродкаст и его обработку, и что никто не использовал в коде условный math.random() (потому что всё-таки это "плохой тон" и весь рандом там обычно условный, основанный на сиде сессии), и вроде как от всего видимого рандома мы избавились, но сетевая игра продолжает постоянно вылетать. В чем же быть проблема?

Как выяснилось, проблема все в том же - один и тот же код на разных устройствах возвращает разные результаты. Примеры фиксов:

  • #9768: использование sort, который в C++ не гарантирует воспроизводимый порядок для одинаковых элементов.

  • #10112: использование set с произвольной сортировкой.

  • #9867: использование указателей в качестве ключей в map и произвольный порядок как следствие.

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

  • #9767, #9970: использование в процессе вычисления логики переменных, которые принимают разное значение в зависимости от игрока, который производит эти вычисления.

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

Что можно было бы сделать изначально иначе?

У такой архитектуры сетевой игры есть свои плюсы. Но перевешивают ли эти плюсы сложность в поддержке такого решения? Я бы сказал, что, конечно, нет. Прям очень тяжело вести такую разработку и держать постоянно в уме все эти нюансы. Неудивительно, что, как я уже говорил, даже в ванильной Цивилизации 5 без всяких модов в сетевой игре были постоянные рассинхроны.

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

Дела еще изначально были бы получше, если бы Firaxis вместе с DLL-ем прикрепили бы и тесты (если они вообще существовали, хотя в такой кодовой базе они точно должны были существовать). Сегодня кодовая база VP (т.е. изначально вся логика Цивилизации 5) на сотни тысяч строк не покрыта ни единым тестом, поэтому сломать там что-то намного проще, чем починить. Спасибо, что правки вручную тестируют хотя бы в одиночной игре. А тестировать правки вручную в мультиплеере - это уже извращение, на которое далеко не каждый готов идти, потому это уже не просто "скомпилировать и запустить".

Реверс-инжениринг закрытого кода

Как я уже говорил, Firaxis выложила в открытый доступ Windows DLL с логикой всей игры, с логикой ботов, со всеми алгоритмами принятия решений и т.д. Изменяя этот DLL можно изменить практически все. Закрытой частью, которая реализована вне DLL, остается рендеринг, UI, взаимодействие с камерой, пересылка байтиков по сети, взаимодействие со Steam, с локальной базой и еще всякие мелочи, которые обычно и не нужно править. Но в этой закрытой части есть и баги, которые, получается, пофиксить никак нельзя. Конечно, грех жаловаться - хотя бы что-то отдали сообществу, уже хорошо.

То, что моддеры могут модифицировать только DLL, а не весь код полностью, накладывает определенные ограничения:

  • Разработка залочена на Visual Studio 2008 и поэтому нет возможности использовать какие-то более современные фичи C++.

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

  • Баги и утечки памяти в закрытом коде невозможно пофиксить.

  • Невозможно моддить рендеринг и всё ранее-перечисленное.

Более того, исполняемые файлы защищены CEG (DRM-защита от Steam, которая, хоть и устаревшая, но всё равно рабочая), поэтому пропатчить закрытый код и распространять его вместе с модом невозможно.

Но есть и хорошие новости:

  • Хоть и исполняемые файлы защищены CEG, их всё равно можно пропатчить в рантайме. Это достаточно легко реализовать, учитывая, что мы уже можем править код в подгружаемой DLL.

  • Исполняемые файлы не обфусцированы какой-то супер-модной технологией, как это делают сейчас.

  • Ну и самое приятное: непонятно, было ли это сделано намеренно или нет, но в Linux-версии исполняемый файл поставлялся со всеми сохраненными нэймингами и виртуальными таблицами. Учитывая, что он практически идентичен Windows-версии, можно их сопоставить и найти необходимую функцию по нэймингу из Linux-версии в Windows-версии.

Как-то так выглядит исполняемый файл под Linux
Как-то так выглядит исполняемый файл под Linux

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

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

Эта правка служит примером, что ничего невозможного в моддинге Цивилизации 5 нет. При желании достучаться можно и до закрытого кода.

Заключение

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

Такая вот история. Если вдруг захотите попробовать вспомнить 2010 и поиграть в Цивилизацию 5 с модами, уверяю, это будет того стоить. Ну, синглплеер уж точно. Long live VP!

И подписывайтесь на мой ? Telegram-канал, кстати. Там я размещаю всякие мысли про повседневную разработку, которые не подходят под формат блога.

Комментарии (47)


  1. Kelbon
    01.09.2025 18:07

    Во всяком случае для дебага было бы логично сериализовать весь всё состояние игры каждый ход в json или посчитать от него хеш и сравнивать между всеми игроками, странно что опции это включить нет


    1. sperson Автор
      01.09.2025 18:07

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

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


    1. Kromster80
      01.09.2025 18:07

      В Циве же есть сейвы, наверняка даже бинарные. Вот это и есть необходимая сериализация. Почистить их только от переменных игроков, и можно сравнивать.


  1. MonkAlex
    01.09.2025 18:07

    Я про цивилизацию помню только, что когда мы сохраняли сессию (с друзьями), а потом загружали её в другой день - за нас 1 ход ходил почему то ИИ и сбрасывал нам постройки (особенно обидно за чудеса света). И я помню аналогичные жалобы в стиме от игроков.

    Интересная статья, спасибо =)


    1. Fenex
      01.09.2025 18:07

      Да, это известный баг. Занятно, что есть простой способ это обойти. После сохранения надо тут же ещё раз сохранить игру в тот же самый файл. После этого простого действия, при загрузке ход пропускаться не будет.


  1. Vugluskr1
    01.09.2025 18:07

    Когда я ридал это вондерфул текст, я прямо трейне, ибо такой эинфаче решение это просто гранде


    1. Metotron0
      01.09.2025 18:07

      Партиционно инкрементирую ваш вижен ситуации.


  1. vikarti
    01.09.2025 18:07

    Нет тестов.

    А почему бы...не принят что текущий код в какой то минимальной версии - работает и не попробовать эти чертовы тесты завайбкодить. а потом выкинуть уже явно кривые тесты. Чтобы хотя бы не сделать еще хуже.

    Что я не понимаю?


    1. MonkAlex
      01.09.2025 18:07

      Некому. Моды пишут энтузиасты, на голом энтузиазме.


    1. sperson Автор
      01.09.2025 18:07

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

      Если есть свободное время и желание, можно всегда заслать PR, требования к коду там достаточно лояльные, все будут только рады )


    1. Kromster80
      01.09.2025 18:07

      Тесты (юнит, игровые, "сценарии" для мультиплеера) были бы отличным подспорьем, если бы команда видела стабильное будущее на 3-4 года вперед.


  1. Panzerschrek
    01.09.2025 18:07

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


    1. sperson Автор
      01.09.2025 18:07

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


  1. Chanser
    01.09.2025 18:07

    Как заядлому игроку во все версии Civilization, регулярно ловящему рассинхроны в сетевой игре, было очень интересно прочитать, спасибо!

    Интересно, в VI и VII версиях логика работы сетевой игры такая же? Аналогичные проблемы подсказывают что да, но вдруг...
    И интересно конечно почему Firaxis была выбрана именно такая баго-ориентированная архитектура


    1. sperson Автор
      01.09.2025 18:07

      Насчет последующих частей особо не вкурсе; когда интересовался, где-то читал, что для VI части нет DLLника открытого, как для V, подозреваю, его до сих пор тоже нет и, наверное, никогда и не будет. Так что с моддингом там по идее похуже и в целом кишочки уже и не поковыряешь, как в V, чтобы понять в деталях, как оно все работает.


    1. sperson Автор
      01.09.2025 18:07

      А насчет подхода - ну, можно с уверенностью сказать, что:
      - такой подход в теории может быть менее требователен к интернет-ресурсам
      - и запилить его было явно намного проще и быстрее, чем какой-либо другой

      Лично я подозреваю, что второй пункт оказался решающим, потому что по сути в такой схеме логика для МП практически не отличается от логики СП. Вот прям если DLL посмотреть, то логика МП от СП отличается разве что редкими ифчиками по типу `if isMultiplayer`. В другой схеме переписывать с виду там прям очень много пришлось бы.


      1. JediPhilosopher
        01.09.2025 18:07

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

        Да, это изначально заметно сложнее реализуется, но все окупается при реализации мультиплеера. Который прикручивать в изначально не подготовленный для этого код это просто леденящий душу пиздец.

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


      1. Chanser
        01.09.2025 18:07

        Согласен, но жалко что так. Когда понимаешь что у real-time шутеров нет проблем с синхронизацией многопользовательских игр под сотню игроков, а у пошаговой стратегии на 2-3 человека рассинхроны и вылеты.
        Но это была проблема всех игр серии. Причем с одной стороны у мультиплеера проблема с синхронизацией, а у синглплеера - с глупыми ИИ. Make your choise так сказать)


      1. Kromster80
        01.09.2025 18:07

        Главные фишки подхода - автоматическая устойчивость к читам, "бесплатные" реплеи и малый объем передаваемой информации между игроками. Запилить его совсем не проще, чем сохранять всю игру и перекидывать каждый ход между игроками.

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


        1. sperson Автор
          01.09.2025 18:07

          К читам устойчивости нет совсем никакой, потому что ничего не запрещает:

          • поставить мод, который открывает всю карту, показывает все ресурсы и тд и тп

          • как хочешь слать какие хочешь бродкасты, их валидность практически никак не проверяется (ну, кроме базового "существует ли такой юнит", но не "может ли этот юнит ходить так далеко")

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


          1. Kromster80
            01.09.2025 18:07

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


            1. JediPhilosopher
              01.09.2025 18:07

              Почему, можно если протокол плохо продуман (клиент отсылает результаты действий, а не запросы на действия), а валидации нет.

              То есть вопрос в том, как работает протокол. Вот игрок кликает в игре на кнопку "купить танк". Что отошлется другим игрокам? "Игрок нажал на кнопку купить танк"? Или "Игрок купил танк в клетке [15,20]"? Во втором случае читерам вообще раздолье.


              1. Kromster80
                01.09.2025 18:07

                Плохо продумать можно всё что угодно, тут не поспоришь ))
                Есть общепринятые подходы, обмен инпутами это один из них, еще со времен изобретения мультиплеера в RTS :-)


  1. vanyasav
    01.09.2025 18:07

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

    P.S. как в мультиплеере вычисляется, кто построит чудо света?


    1. sperson Автор
      01.09.2025 18:07

      Когда чудо строится, у тебя есть показатель "производство" в городе + кол-во уже вложенного "производства" в чудо. Каждый ход "производство" из города вкладывается в прогресс постройки чуда. Если в один ход оба игрока заканчивают одно и то же чудо, то построится оно у того, у кого было по итогу вложено больше "производства".

      Например:
      - Игрок А строит чудо размером в 15 производства со скоростью 5 производства за ход; ход 1: 5/15, ход 2: 10/15; ход 3: 15/15
      - Игрок Б строит чудо со скоростью 6 производства за ход: ход 1: 6/15, ход 2: 12/15, ход 3: 18/15

      По итогу чудо появится у игрока Б. Это не только в МП так, в СП против ботов логика та же.


      1. Fenex
        01.09.2025 18:07

        Если в один ход оба игрока заканчивают одно и то же чудо, то построится оно у того, у кого было по итогу вложено больше "производства".

        Это в вашем моде так? В ваниле это завит от слота: строит тот игрок, который находится выше.
        А в турнирном патче, например, сделали псевдорандом.