Projects Resume
Fork me on GitHub

WMBP (Websocket multiplayer backend proxy)

This is a pet weekend project to learn & enjoy Rust. Use at your own risk.

Introduction

WMBP is a project is to help more party games to sprout by providing a backend implementation. The base implementation is a one (Game) to many (Clients) connection communication pattern, which is coordinated by the Server, allowing serverless party games.

The Game connects to the Server with a websocket and creates a room. Once the room is created, the Game will receive the Room Code which will be used by Clients to connect.

While the Game has a mandatory communication pattern with the Server, the Clients have a seemingly direct connection to the Game, both in binary and text.

Example game

Usage

  1. Spin this Server, cargo run --release
  2. Game creates a websocket connection to this server to create a game new WebSocket("ws://127.0.0.1:8081/CREATE")
  3. Game sends Prepare with a certain amount of players.
  4. Server sends to Game the Room Code and refuses players if there are too many
  5. Clients creates a websocket connection to this server to create a game new WebSocket("ws://127.0.0.1:8081/ROOM_CODE")
  6. Game sends Start once enough players are connected.
  7. Game sends data to Clients with To and ToStr messages.
  8. Clients sends data to Game with plain text or arraybuffer (for binary format).
  9. Game receives data from Clients with From and FromStr messages.

The game flow of the server

In depth

Then endpoint of the websocket server is defining if you are a Host client (Game) or a Player client by the websocket you created.

  • ws://127.0.0.1:8081/CREATE creates a new game
  • ws://127.0.0.1:8081/ROOM connects to a room

Messages as a Game (host)

The messages for the Game are CBOR encoded with the following format: { "cmd": "snake_case_command", "data1": 1, "data2": "data2"}

For rust users, just take a look at the enum src/comm.rs#Commands. For Javascript users:

  • > Prepare: {"cmd": "prepare", "max_players": 8} # Prepares the game with the maximum number of clients
  • < PrepareReply: {"cmd": "prepare_reply", "key": "ROOM"} # On successful game creation, provides the ROOM key
  • > Start: {"cmd": "start"} # Starts the game, prevents the clients to connect from this point on.
  • < State: {"cmd": "state", "players": [5,2,3], "max_players": 8, "accept_conns": true} # Provides information about the game, players connected, etc.
  • > Kick: {"cmd": "kick", "player": 5} # Kicks player with id 5 (from the State message)
  • < Stop: {"cmd": "stop"} # Disconnect everybody
  • > To: {"cmd": "to", to: [2], "data": [1,2,3]} # Sends binary data to the user 1
  • > ToStr: {"cmd": "to_str", to: [3, 5], "data": "some string"} # Sends text data to the user 3 and 5
  • < From: {"cmd": "from", "from": 2, "data": [1,2,3]} # Received when user 2 sent binary data
  • < FromStr: {"cmd": "from", "from": 5, "data": "some string"} # Received when user 5 sent string data

Messages as a client

The Client has no specific message. Sending text (Text type for the websocket), the message will be transferred with FromStr to the Game, while sending binary data (such as CBOR encore data or images) will be forwarded with From to the Game.

Whenever Game sends data with To and ToStr, only the data will be forwarded to the client (as everything else would be redundant) as binary or text.

This means the Client has a connection that seems to be directly to the game.