Serverentwicklung für Multiplayer-Spiele mit NodeJS und Magx

Viele Entwickler beginnen mit der Entwicklung eines Mehrbenutzer-Online-Servers, der auf der Bibliothek socket.io basiert . Diese Bibliothek macht es sehr einfach, den Datenaustausch zwischen dem Client und dem Server in Echtzeit zu implementieren. Sie müssen jedoch noch die gesamte Logik und Schnittstelle der Server-Client-Interaktion sowie die Architektur für die Skalierung und Verkehrsoptimierung überdenken und implementieren.







Ich möchte über die Magx- Bibliothek sprechen , mit der Sie nicht an die Netzwerkkomponente (Kommunikation zwischen Server und Clients) denken können, sondern sich sofort auf die Entwicklung der Spielelogik und der Client-Benutzeroberfläche konzentrieren können.







Bei der Gestaltung der Architektur eines Multiplayer-Spiels werden normalerweise zwei Ansätze berücksichtigt: mit einem autoritären Server und einem nicht autoritären (autoritären Client). Beide Ansätze werden von der Magx-Bibliothek unterstützt. Beginnen wir mit einem einfacheren Ansatz - nicht autoritär.







Nicht autorisierender Server



Das Wesentliche ist, dass der Server nicht die Eingabeergebnisse jedes Spielers kontrolliert. Clients verfolgen unabhängig voneinander die vom Spieler eingegebenen Aktionen und die Spielelogik lokal. Anschließend senden sie das Ergebnis einer bestimmten Aktion an den Server. Danach synchronisiert der Server alle ausgeführten Aktionen mit dem Spielstatus anderer Clients.







Aus architektonischer Sicht ist die Implementierung einfacher, da der Server nur für die Kommunikation zwischen Clients verantwortlich ist, ohne dass zusätzliche Berechnungen von Clients durchgeführt werden müssen.







Mit der magx-Bibliothek kann ein solcher Server in nur wenigen Codezeilen implementiert werden:







import * as http from "http"
import { Server, RelayRoom } from "magx"

const server = http.createServer()
const magx = new Server(server)

magx.define("relay", RelayRoom)

// start server
const port = process.env.PORT || 3001
server.listen(port, () => {
  console.info(`Server started on http://localhost:${port}`)
})
      
      





Um nun Clients mit diesem Server zu verbinden und ihre Interaktion zu starten, installieren Sie einfach die js-Bibliothek:







npm install --save magx-client









und verbinden Sie es mit dem Projekt:







import { Client } from "magx-client"
      
      





Alternativ können Sie einen direkten Link für die HTML-Verwendung verwenden:







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





Nach dem Verbinden können Sie mit nur wenigen Zeilen die Verbindung und Interaktion mit dem Server konfigurieren:







// authenticate to server
await client.authenticate()

// create or join room
const 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 patches
room.onPatch((patch) => updateState(patch))

// handle state snapshot
room.onSnapshot((snapshot) => setState(snapshot))

// handle joined players
room.onMessage("player_join", (id) => console.log("player join", id))

// handle left players
room.onMessage("player_leave", (id) => console.log("player leave", id))
      
      





Ein detailliertes Beispiel für den Aufbau einer Interaktion zwischen Clients und einem nicht autorisierenden Server finden Sie im entsprechenden Beispiel im magx-examples- Projekt .







Autorisierender Server



, , - .







- . , , , , .







, . , (cheating).







. magx , (worker). , .







/ . — . Mosx — , magx - , .









, . mosx — @mx.Object, , @mx. :







@mx.Object
export class Player {
  @mx public x = Math.floor(Math.random() * 400)
  @mx public y = Math.floor(Math.random() * 400)
}

@mx.Object
export 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. Typescript
  6. ( MobX patchpack — )


Magx



  1. API.
  2. :

    • ( webockets)
    • ( )
    • ( )
    • ( )
  3. Eingebaute Räume: Lobby und Relais (für nicht autorisierende Server)
  4. JS Magx-Client- Bibliothek für die Arbeit mit dem Server
  5. Überwachungskonsole MagX-Monitor für die Verwaltung von Serverräumen, ihre Kunden und Anzeigen Status
  6. Volle Typescript-Unterstützung
  7. Minimale Abhängigkeiten (für die Bibliothek notepack.io - um den Netzwerkverkehr zu reduzieren)


Dieses Projekt ist noch recht jung und ich hoffe, dass die Aufmerksamkeit der Community dazu beitragen wird, dass es sich viel schneller entwickelt.








All Articles