Idewavecore. Ретроспектива

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Очень круто - запрограммировать механизм или программный модуль, заставив его выполнять твою волю. С похожими мыслями в конце 2018 я размышлял о том, что хочу сделать собственный WoW-сервер, который будет полностью мной управляем. Поизучав С++ исходники MANGOS, я пришел к выводу, что не смогу вот так взять и реализовать все свои идеи, не понимая, как же работает MMO RPG сервер от начала и до конца. И для этой цели я решил реализовать свой движок. С нуля.


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

Если вкратце, то Login Server (как и аутентификация в клиенте WoW) построены на использовании алгоритма SRP. Описание алгоритма выходит за пределы статьи, но если вкратце, то он позволяет идентифицировать пользователя без передачи пароля на сервер, благодаря чему пароль (даже в закэшированном виде) можно не хранить на сервере. Даже желательно.

Алгоритм шифрования же World сервера скорее всего отличается от клиента к клиенту (я сделал такой вывод при беглом изучении исходников сервера WoW 3.3.5a). В статье речь пойдет о сервере для WoW 2.4.3 (именно для этой версии я писал сервер). Там используется что-то вроде шифра Цезаря. Хотя чаще (в исходниках) можно встретить название HeaderCrypt или Wowcrypt.

В версии 2.4.3 шифруются первые несколько байт каждого пакета на World сервере (кроме первого пакета). Для расшифровки (decrypt) используются первые 6 байт: 2 байта - размер пакета + 4 байта - opcode (специальный код, по которому можно определить хэндлер(ы), что будет с этим пакетом работать). И для зашифровки (encrypt) используются первые 4 байта (только opcode). Соответственно, если перехватить пакет (sniff), то не получится определить, на какой опкод он будет отправлен. А если пакет большой, то он может быть разбит на несколько и чтобы их правильно достать из буфера - нужны эти самые первые 2 байта (размер пакета).

Процесс входа на сервер вкратце можно описать так:

Клиент последовательно обменивается данными с Login сервером и в случае успеха получает SRP токен (session key), который затем будет использован для создания токена шифрования/расшифровки пакетов (crypto key). Токен создается на этапе "send auth request" (см. схему выше). После чего на клиент отправляется auth response, суть которого - показать, что операция прошла успешно. Auth response - единственный незашифрованный пакет, последующие пакеты будут шифроваться с помощью crypto key. По поводу шифра - у меня он реализован так.

Процесс взаимодействия с World сервером простой - клиент отправляет зашифрованный пакет, на сервере он кладется в буфер, расшифровываются первые несколько байт (о чем я писал выше), получаем размер (size) и опкод (opcode) и если количество байт в буфере >= size, то мы получаем список необходимых хэндлеров (их может быть несколько) по заданному опкоду и передаем им size байт из буфера. Либо ожидаем получения остальных байт. Отдельного внимания заслуживает Update Packet. Он отличается от остальных пакетов более сложной структурой.

Расшифровывать нужно каждый пакет. Если какой-то пакет пропущен, то следующий (согласно алгоритму) будет расшифрован неправильно. На эти грабли я наступал с особой старательностью.

В чем суть моего сервера

Во-первых, я его писал на Python 3 (asyncio + SQLAlchemy). Точнее, на момент создания я еще не имел опыта с SQLAlchemy - я его обрел после, когда решил, что существующая у меня реализация работы с БД - ужасна во всех ее проявлениях (а еще попутно решил изучить новую технологию). И очередной раз переписал проект с нуля.

Во-вторых, подход к обработке данных тоже несколько отличался. Я предпочел отказаться от идеи глобального хранилища всех объектов (где каждый объект содержит также методы работы с ним) и создать специальные мэнеджеры (manager), для того, чтобы работать с каждым отдельным типом объектов: Item, Player, Unit и т.д. Т.е. если я хочу выполнить действие над Player, я использую PlayerManager, который выполняет нужное действие и удаляется из памяти. В первую очередь это сделано в угоду читабельности. К примеру, аналогичный класс в MANGOS лично для меня кажется громоздким (как и C++, несмотря на множество его преимуществ). Каждый отдельный класс объекта - это SQLAlchemy модель и он же - структура данных, хранящая текущее состояние. Таким образом, я использую такие объекты не только для взаимодействия с БД, но и для обмена структурированными данными между частями приложения.

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

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

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

Что дальше

В процессе разработки сервера у меня возникла идея создания MMO RPG шаблонизатора, который предоставит формат описания игровых серверов (например, связка Login + World сервер, или шард-ориентированная архитектура, где каждая локация - отдельный сервер и т.д.), а так же серверов, имеющих отношение к игровым косвенно (например, web сервер, где будет сайт и форум). Именно для этого я создал фреймворк (но не совсем внятно описал его в своей предыдущей статье). И сейчас сервер переписываю на базе этого фреймворка.

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

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

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Есть ли у вас опыт написания игрового сервера с нуля?

  • 50,0%Да (есть полностью рабочий игровой сервер, сделанный с нуля)2
  • 0,0%Да (но не довел до конца)0
  • 50,0%Нету (и нет желания)2
  • 0,0%Хочу попробовать сделать0
Источник: https://habr.com/ru/post/545144/


Интересные статьи

Интересные статьи

…или как хакеры ломали наш опенсорс платежный процессинг в кибергороде. Привет! Мы тут недавно с процессингом RBK.money приняли активное участие в киберполигоне The Standoff — это когд...
Кто бы что ни говорил, но я считаю, что изобретение велосипедов — штука полезная. Использование готовых библиотек и фреймворков, конечно, хорошо, но порой стоит их отложить и создать ...
Много всякого сыпется в мой ящик, в том числе и от Битрикса (справедливости ради стоит отметить, что я когда-то регистрировался на их сайте). Но вот мне надоели эти письма и я решил отписатьс...
Получить трафик для интернет-магазина сегодня не проблема. Есть много каналов его привлечения: органическая выдача, контекстная реклама, контент-маркетинг, RTB-сети и т. д. Вопрос в том, как вы распор...
Джефф Хастон (Geoff Huston), главный инженер-исследователь интернет-регистратора APNIC, спрогнозировал, что адреса IPv4 закончатся в 2020 году. В новом цикле материалов мы освежим информацию о то...