Muitos desenvolvedores estão começando a desenvolver um servidor online multiusuário baseado na biblioteca socket.io . Esta biblioteca torna muito simples implementar a troca de dados entre o cliente e o servidor em tempo real, mas você ainda precisa pensar e implementar toda a lógica e interface da interação servidor-cliente, bem como a arquitetura para escalonamento e otimização de tráfego.
Eu quero falar sobre a biblioteca magx , usando a qual você não pode pensar sobre o componente de rede (comunicação entre o servidor e os clientes), mas imediatamente se concentrar no desenvolvimento da lógica do jogo e da IU do cliente.
Ao projetar a arquitetura de um jogo multiplayer, geralmente são consideradas 2 abordagens: com um servidor autoritário e um não autoritário (cliente autoritário). Ambas as abordagens são suportadas pela biblioteca magx. Vamos começar com uma abordagem mais simples - não autoritária.
Servidor não autorizado
Sua essência é que o servidor não controla os resultados de entrada de cada jogador. Os clientes rastreiam de forma independente as ações inseridas pelo jogador e a lógica do jogo localmente, após o que eles enviam o resultado de uma determinada ação para o servidor. Depois disso, o servidor sincroniza todas as ações realizadas com o estado do jogo de outros clientes.
É mais fácil de implementar do ponto de vista arquitetônico, pois o servidor é responsável apenas pela comunicação entre os clientes, sem fazer nenhum cálculo adicional que os clientes façam.
Usando a biblioteca magx, tal servidor pode ser implementado em apenas algumas linhas de código:
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}`)
})
Agora, para conectar os clientes a este servidor e iniciar sua interação, basta instalar a biblioteca js:
npm install --save magx-client
e conecte-o ao projeto:
import { Client } from "magx-client"
Como alternativa, você pode usar um link direto para HTML:
<script src="https://cdn.jsdelivr.net/npm/magx-client@0.7.1/dist/magx.js"></script>
Após a conexão, apenas algumas linhas permitirão que você configure a conexão e interação com o servidor:
// 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))
Um exemplo detalhado de como construir interação entre clientes e um servidor não autorizado é descrito no exemplo correspondente no projeto magx-examples .
Servidor autorizado
, , - .
- . , , , , .
, . , (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)
?
:
Mosx
Magx
- API.
- :
- ( webockets)
- ( )
- ( )
- ( )
- Salas integradas: saguão e retransmissão (para servidor não autorizado)
- Biblioteca cliente JS Magx para trabalhar com o servidor
- Monitor de console magx-monitor para gerenciamento de salas de servidores, seus clientes e visualização de status
- Suporte completo de texto digitado
- Dependências mínimas (para a biblioteca notepack.io - para reduzir o tráfego de rede)
Este projeto é muito jovem e espero que a atenção da comunidade o ajude a se desenvolver muito mais rápido.