Русский
Русский
English
Статистика
Реклама

Разработка сервера для многопользовательской игры с помощью nodejs и magx

Многие разработчики начинают разработку многопользовательского онлайн сервера на основе библиотеки socket.io. Эта библиотека позволяет очень просто реализовать обмен данными между клиетом и сервером в реальном времени, но продумать и реализовать всю логику и интерфейс взаимодействия сервера с клиентами, а также архитектуру масштабирования и оптимизацию трафика все равно придется.


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


При разработке архитектуры многопользовательсой игры обычно рассматриваются 2 подхода: с авторитарным сервером и не-авторитарным (авторитарным клиентом). Оба эти подхода поддерживаются библиотекой magx. Начнем с более простого подхода не-авторитарного.


Не-авторитарный сервер


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


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


С помощью библиотеки magx такой сервер можно реализовать всего в несколько строк кода:


import * as http from "http"import { Server, RelayRoom } from "magx"const server = http.createServer()const magx = new Server(server)magx.define("relay", RelayRoom)// start serverconst port = process.env.PORT || 3001server.listen(port, () => {  console.info(`Server started on http://localhost:${port}`)})

Теперь, чтобы подключить клиентов к этому серверу и начать их взаимодействие, достаточно установить js библиотеку:


npm install --save magx-client


и подключить ее к проекту:


import { Client } from "magx-client"

Также можно воспользовать прямой ссылкой для использования в HTML:


<script src="http://personeltest.ru/aways/cdn.jsdelivr.net/npm/magx-client@0.7.1/dist/magx.js"></script>

После подключиеня, всего несколько строк позволят настроить соединение и взаимодействие с сервером:


// authenticate to serverawait client.authenticate()// create or join roomconst rooms = await client.getRooms("relay")room = rooms.length   ? await client.joinRoom(rooms[0].id)  : await client.createRoom("relay")console.log("you joined room", name)// handle state patchesroom.onPatch((patch) => updateState(patch))// handle state snapshotroom.onSnapshot((snapshot) => setState(snapshot))// handle joined playersroom.onMessage("player_join", (id) => console.log("player join", id))// handle left playersroom.onMessage("player_leave", (id) => console.log("player leave", id))

Детальный пример как построить взаимодействие между клиентами и не-авторитарным сервером описано в соответствующем примере в проекте magx-examples.


Авторитарный сервер


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


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


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


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


Данные/состояние каждой комнаты изолировано и синхронизируется только с клиентам комнаты. Одним из важнейших элементов авторитарного сервера это система управления состоянием. Mosx рекомендованная система управления состоянием, но архитектуре magx нет зависимости на какую-либо систему, поэтому выбор всегда остается за вами.


Описание игрового состояния


Так как вся логика игры должна строиться на основе состояния, то первым делом необходимо его описать. С помощью mosx это сделать достаточно просто необходимо создать классы для каждого типа объектов состояния и обернуть его декоратором @mx.Object, а перед каждым свойством, по которому необходимо отслеживать изменение состояния для синхронизации с клиентами необходимо поставить декоратор @mx. Давайте рассмотрим пример состояния с коллекцией игроков:


@mx.Objectexport class Player {  @mx public x = Math.floor(Math.random() * 400)  @mx public y = Math.floor(Math.random() * 400)}@mx.Objectexport class State {  @mx public players = new Map<string, Player>()  public createPlayer(id: string) {    this.players.set(id, new Player())  }  public removePlayer(id: string) {    this.players.delete(id)  }  public movePlayer(id: string, movement: any) {    const player = this.players.get(id)    if (!player) { return }    player.x += movement.x ? movement.x * 10 : 0    player.y += movement.y ? movement.y * 10 : 0  }}

Единственное ограничение, которое необходимо учесть при проектировании состояния необходимость использования Map() вместо вложенных объектов. Массивы (Array) и все примитивные типы (number, string, boolean) могут быть использованы без ограничений.


Описание игровой комнаты


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


export class MosxStateRoom extends Room<State> {  public createState(): any {    // create state    return new State()  }  public createPatchTracker(state: State) {    // create state change tracker    return Mosx.createTracker(state)  }  public onCreate(params: any) {    console.log("MosxStateRoom created!", params)  }  public onMessage(client: Client, type: string, data: any) {    if (type === "move") {      console.log(`MosxStateRoom received message from ${client.id}`, data)      this.state.movePlayer(client.id, data)    }  }  public onJoin(client: Client, params: any) {    console.log(`Player ${client.id} joined MosxStateRoom`, params)    client.send("hello", "world")    this.state.createPlayer(client.id)  }  public onLeave(client: Client) {    this.state.removePlayer(client.id)  }  public onClose() {    console.log("MosxStateRoom closed!")  }}

Регистрация комнаты на сервере


Последний шаг зарегистрировать комнату и сервер готов.


const magx = new Server(server, params)magx.define("mosx-state", MosxStateRoom)

Полный исходный код рассмотренного примера доступен в репозитарии magx-examples.


Почему стоит обратить внимание на этот проект?


В заключение хотел бы упомянуть о преимуществах используемых библиотек:


Mosx


  1. Простой и удобный способ описания состояния через декораторы @mx
  2. Возможность применять декоратор @mx к вычисляемым свойствам.
  3. Возможность создавать приватные объекты @mx.Object.private и приватные свойства @mx.private, с различным уровнем доступа для разных игроков.
  4. Динамически изменять доступ игроков к приватным объектам.
  5. Встроенный механизм объединения объектов в группы для удобного управления правами доступа к приватным данным
  6. Возможность делать копию состояния для каждого игрока
  7. Полная поддержка Typescript
  8. Минимум зависимостей (на библиотеки MobX и patchpack для сжатия пакетов)

Magx


  1. Простой и понятный API.
  2. Широкие возможности по кастомизации компонент сервера:
    • Механизм коммуникации клиента с сервером (по умолчанию используется webockets)
    • База данных для хранения данных комнат и сессий пользователей (по умолчанию используется локальное хранилище)
    • Механизм коммуникации серверов при масштабировании (из коробки реализован механизм коммуникации в кластере)
    • Способ авторизации и верификации пользователей (по умолчанию используются локальный сессии)
  3. Возможность работать в кластере из коробки
  4. Встроенные комнаты: лобби и relay (для не авторитарного сервера)
  5. JS Библиотека Magx-client для работы с сервером
  6. Мониторинговая консоль magx-monitor для управления комнатами сервера, их клиентами и просмотр состояния
  7. Полная поддержка Typescript
  8. Минимум зависимостей (на библиотеку notepack.io для уменьшения сетевого трафика)

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

Источник: habr.com
К списку статей
Опубликовано: 08.12.2020 12:05:45
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Node.js

Magx

Mosx

Nodejs

Multiplayer

Framework

Websockets

Networking

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru