Самый глупый сервер, который мы написали


В одном из онлайн проектов мы были сильно ограничены во времени разработки серверной части, поэтому было принято тактическое решение – делать сервер максимально глупым. Об этом и пойдет речь – какой минимальный сервер нужен для многопользовательской онлайн игры. Что он должен уметь, какой функционал реализовывать.

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

Почему мы были вынуждены это сделать?
Одна команда с интересной задумкой геймплея связалась с нами и попросила сделать для них серверную часть. Времени в обрез, но люди хорошие, надо помочь. В условиях ограниченных ресурсов родилось решение – не реализовывать на стороне сервера вообще никакой игровой логики. Тогда у нас хватит времени и сил выполнить просьбу наших друзей. Кроме того, был учтен тот немаловажный факт, что к моменту нашего общения с “командой”, у них на клиенте уже была реализована вся игровая механика.

Чем это чревато? Какой профит?
Главная проблема – вопрос синхронизации игроков теперь ложится на плечи клиентщиков. Ничего, справятся. Другая проблема – благодатная почва для читеров – вполне решаемо. Да и до первого читера пока – как до луны. Зато один серверщик может сделать такой сервер на коленке за пару вечеров. Естественно, грамотный серверщик и грамотно сделать. :)

Что умеет сервер и как мы это сделали?
Минимальный функционал, который должен реализовывать сервер – следующий:

  • Хранить учетные записи игроков
  • Уметь создавать новые учетные записи, авторизовать игроков, выдавать по запросу клиента всю информацию по игроку
  • По запросу клиента изменять учетную запись клиента (инвентарь, опыт, уровень и т.п.)
  • Уметь сводить двух игроков в одной комнате – в бою
  • Во время боя уметь ретранслировать команды с одного клиента на другой.
  • Вести минимальную статистику по боям и событиям игрового мира


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

    Итак, в момент начала боя сервер одного из клиентов назначает “ведущим”. При этом, клиенты вообще не в курсе этой серверной логики. Другими словами, они оба считают себя ведущими. Все игровые события мы делим на “юзер-генерируемые” и “движок-генерируемые”. Первые мы слушаем от обоих клиентов и рассылаем обоим. К ним относятся в основном приказы игрока. А вот вторые – слушаем и рассылаем только от ведущего клиента. К ним относятся все события, которые генерируются игровым движком, и не связаны напрямую с действиями юзера. Таким образом, мы одного из клиентов назначаем “оператором игровой механики” в этом бою. В самих клиентах сделано только одно изменение: никакие игровые процессы не запускаются без команды с сервера.

    Пример. Допустим в какой-то момент клиент решает, что вот сейчас юнит #22 должен начать движение. Он отсылает соответствующее “движок-генерируемое” событие на сервер. При этом ни один из клиентов пока еще не двигает юнит #22. Если событие было отослано ведомым клиентом, сервер его просто игнорирует. Юнит #22 стоит на месте. И только если событие было отослано ведущим клиентом, оно рассылается сервером обоим клиентам. Оба клиента его получают и практически синхронно запускают механизм движения нужного юнита. Профит. :)

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

    Резюме
    Иногда жизнь создает условия, в которых приходится принимать нестандартные решения. Это страшновато, но зато дает новый бесценный опыт. И потом, делать все проекты по одной и той же схеме – просто не интересно.
    Если у вас возникнет аналогичная ситуация – не бойтесь использовать “глупые” сервера. Такой подход не просто жизнеспособен, а иногда вообще единственно правильный.
    До новых встреч. :)

    P.S. Дабы только очень заинтересованные могли узнать, о какой игре идет речь, мы намеренно разместили ссылку на нее в самом конце статьи.
    Heroes Of Scene

  • Эта запись была опубликована в рубрике Мысли о разработке и отмечена метками , , , . Добавить в закладки ссылку.

    2 в ответ на Самый глупый сервер, который мы написали:

    1. Feo пишет:

      Реализовываю мультиплеер для игры с подобным геймплеем (до 3х3, юниты выходят пачками) по подобному принципу. Интересно было найти эту заметку.
      Сколько раз в секунду считаете бой? Как по трафику?

      • antares пишет:

        Честно говоря, как устроен обсчет боя на клиенте, мы толком не знаем. Сервер же используется просто как ретранслятор команд. Но думаю, что события одного боя идут не чаще, чем 3-4 раза в секунду. Так что, и трафик небольшой.
        Тут важно заметить, что трафик серьезно оптимизировался клиентщиками. Например, при начале движения какого-то юнита шлется только команда на движение, и всё. То есть, всего одна команда, чтобы юниту пройти от одного края карты до другого. И так со всеми действиями.