Как сделать MMO (на стороне сервера)?
Я пытался найти способ создания ММО и всегда находить одни и те же ответы, это невозможно или нужно много денег, но я никогда не давал руководство о том, как их создать.
Я хочу создать что-то очень масштабируемое, моя текущая идея о том, как создать MMO, заключается в следующем:
Компоненты:
- Сервер входа: клиент отправляет имя пользователя и пароль на этот сервер и в случае успеха сообщает клиенту, к какому игровому серверу подключиться.
- Игровой сервер [1..N]: вся логика игры идет сюда, клиенты подключены к этому.
- Позиция БД: хранит данные зарегистрированных в данный момент пользователей и активных монстров, в которых они находятся на игровом сервере, их позиции на карте и действия, которые они предпринимают (перемещение, атака и т. Д.).
- База данных учетной записи: хранит все данные о пользователе (имя пользователя, пароль, персонажи, предметы, квесты и т. Д.)
- Сервер чата: поскольку пользователи, находящиеся в одном и том же месте, могут находиться на разных серверах, необходимо создать дополнительный, чтобы игроки могли общаться между ними.
- Monster DB: база данных с атрибутами, базовыми позициями и скриптами AI всех монстров.
- Monster Server [1..N]: все активные монстры на сервере
- Журнал БД: хранит все выполненные действия и текстовые сообщения чата.
Действия:
- Авторизоваться:
- Клиент отправляет имя пользователя и пароль на сервер входа.
- Сервер входа в систему проверяет данные с помощью БД учетных данных и проверяет, что в данный момент не зарегистрировано (Позиция БД), в случае успеха перейдите к 3, если нет, отправит обратно сообщение о неудачном входе.
- Сервер входа обновляет БД позиции, добавляя нового подключенного пользователя к серверу, с которым он будет связан (наименьшее количество людей / ближайшее)
- Позиция БД информирует соответствующий игровой сервер о том, что пользователь подключен.
- Сервер входа в систему отправляет клиенту, к которому подключен игровой сервер.
- Основной цикл (клиент):
- Клиент проверяет в БД позиции свою текущую позицию и действие и тех, кто рядом с ним (игроки и монстры), в полученные данные также входит время последнего обновления (снаряжение или уровень) игроков.
- Клиент сравнивает дату полученных игроков с текущими игроками, сохраненными в памяти, если игрок не был в памяти или дата не совпадает, Клиент запрашивает базу данных учетной записи для lvl, передач и т. Д.
- Клиент рендерит игроков
- через некоторое время перейдите к 1.
- чат:
- Клиент отправляет сообщение (pm/normal/all) на сервер чата
- Если вечера, сервер чата отправляет сообщение на цель
- Если все нормально, Сервер чата проверяет с помощью Сервера положения игроков в этой области (так же, как основной цикл (клиент).1 при проверке игроков рядом) и отправляет сообщение тем.
- Если все, сервер чата вещает всем игрокам
- Подтверждает, что отправитель и получатель получили сообщение
- Действие:
- Клиент отправляет действие (создание, перемещение, нападение и т. Д.) На игровой сервер.
- Игровой сервер обрабатывает действие и обновляет Position DB с эффектами действия (клиент будет знать, что произошло с действием основного цикла).
- В случае крафта или грабежа, игровой сервер возвращает клиенту полученный предмет.
- Основной цикл (игровой сервер):
- Проверяет все полученные данные от клиентов и обрабатывает их.
- Отправляет клиентам результаты процесса (урон, хр, полученный предмет и т. Д.) И обновляет Позицию БД с учетом ее последствий (новая позиция и т. Д.).
- Через некоторое время перейдите к 1.
- Основной цикл (сервер-монстр):
- Проверяет, есть ли рядом с активным монстром игрок, если нет, удаляет его из Monster Server и Position DB.
- Проверяет всех игроков в БД позиции, если рядом есть монстр (из БД монстров) и не активен, и активирует его (обновляя сервер позиций и сервер монстров).
- Monster выполняет действия (атакует, двигается, ничего не делает и т. Д.) На основе сценария, хранящегося в базе данных монстра.
- Через некоторое время перейдите к 1.
и вопросы у меня есть:
- Будет ли этот способ реализовать работу? (учитывая большую карту с множеством монстров и игроков)
- У меня есть ощущение, что позиция DB будет сильно напряжена, если что-то вырастет. было бы лучше, если бы:
- сделать несколько позиций БД
- создать БД, которая связывает (игрок / монстр, игровой сервер, позиция БД)
- сделать БД, которая связывает (Позиция БД, область)
- Таким образом, база данных позиций основана на области (или областях), и когда игрок перемещается в другую область, его данные перемещаются в другую базу данных позиций; и последняя БД (БД позиции, область) будет в случае, если в области слишком много игроков, несколько БД позиции могут совместно использовать одну и ту же область (и если в областях не много людей, БД позиции может содержать некоторые области)
- Об используемых технологиях я думал о следующем:
- Сервер входа: scala/django
- Игровой сервер: сырое программирование на C++?
- Позиция БД: scala/django для связи и БД с SQL
- БД данных учетной записи: scala/django для связи, а БД не уверена, использует ли NoSQL, например, mongoDB, или учетные записи, сохраненные в файлах (что будет лучше?)
- Сервер чата: сырое программирование на C++ или я должен попытаться адаптировать IRC-сервер?
- Монстр БД: SQL
- Monster Server: как игровой сервер
- Журнал БД: SQL
- Связь между клиентом и сервером должна быть UDP для более быстрой связи? а TCP для входа? или всегда должен держать открытый сокет TCP между клиентом и сервером? также для чата, TCP или UDP?
- Примерно каждые, как долго должен работать основной цикл, чтобы игра шла плавно? каждые 0,5 секунды, 0,1, что-то около 60 кадров в секунду? Кроме того, чтобы сделать таймер было бы лучше бросить поток каждый цикл? (контроль количества потоков, поэтому, если цикл занимает больше времени, чем следует)
И я не думаю, что на данный момент я что-то забываю, чтобы спросить и извините за этот большой пост...
2 ответа
Я не думаю, что ваше решение будет масштабироваться. Вопрос в том, какая база данных вашей позиции должна быть обновлена для каждого действия игрока. Вы, вероятно, используете этот метод, чтобы позволить игровым серверам обмениваться данными, что является плохой идеей, поскольку базы данных не предназначены для распространения системы. Рассматривайте базы данных как реальное автономное хранилище, только для загрузки состояния, когда игроки или объекты активированы.
Вам нужно избавиться от БД позиции и сохранить состояния игроков, распределенные между игровыми серверами.
Также подумайте о том, чтобы иметь внешний сервер, который постоянно поддерживает одно соединение с клиентом, ретранслировать сообщения на нужный игровой сервер и т. Д. Таким образом, вы можете избежать подключения клиентов к "правильному" игровому серверу и всех проблем, которые могут возникнуть. приходит с этим уровнем доверия.
Распределенное программирование довольно сложно, но язык программирования Erlang делает его проще для вас, чем Python/C++ и т. Д.
Кристиан прав, вы слишком полагаетесь на БД. Обычно текущее состояние игры и ее игроков сохраняется на реальном сервере во время выполнения. Вы можете создать функцию, которая будет автоматически обновлять БД позиции или состояния игрока, что очень часто встречается в ММО, но в конечном итоге База данных - это просто ссылка для извлечения данных во время запуска, а не во время выполнения.