Skip to content

polysource-projects/cs108-chacun-ws-server

Repository files navigation

    _______   .---.  .---.    ____        _______     ___    _ ,---.   .--. 
   /   __  \  |   |  |_ _|  .'  __ `.    /   __  \  .'   |  | ||    \  |  | 
  | ,_/  \__) |   |  ( ' ) /   '  \  \  | ,_/  \__) |   .'  | ||  ,  \ |  | 
,-./  )       |   '-(_{;}_)|___|  /  |,-./  )       .'  '_  | ||  |\_ \|  | 
\  '_ '`)     |      (_,_)    _.-`   |\  '_ '`)     '   ( \.-.||  _( )_\  | 
 > (_)  )  __ | _ _--.   | .'   _    | > (_)  )  __ ' (`. _` /|| (_ o _)  | 
(  .  .-'_/  )|( ' ) |   | |  _( )_  |(  .  .-'_/  )| (_ (_) _)|  (_,_)\  | 
 `-'`-'     / (_{;}_)|   | \ (_ o _) / `-'`-'     /  \ /  . \ /|  |    |  | 
   `._____.'  '(_,_) '---'  '.(_,_).'    `._____.'    ``-'`-'' '--'    '--' 

ChaCuN Multiplayer Server

🌟 What is ChaCuN?

ChaCuN, which stands for 'Chasseurs et Cueilleurs au Néolithique', is an electronic version of the board game 'Chasseurs et Cueilleurs', derived from the famous 'Carcassonne'. It is the project of first-year students enrolled in the summer 2024 EPFL Computer Science bachelor semester.

ChaCuN is designed to be played by 2 to 5 players, each aiming to build a prehistoric landscape by placing square tiles side by side. The different parts of the landscape, for example, forests, rivers, etc., can be occupied by hunters, gatherers, or fishermen to earn points.

🚀 Overview

This WebSocket server allows up to 5 players to play together (and remotely!) a game of ChaCuN. Originally, this was not possible, as the game was designed to be played on a single computer.

Key Features and Benefits

1. ⚡ Real-Time Interaction

  • Instantaneous Responses: The server automatically transmits game actions, which saves time manually updating the game state. This also ensures that the gameplay is not disrupted.
  • Game Chat Support: Players can communicate with each other in real-time using the chat feature, even after a game has ended.

2. 🔒 Anti-Cheating Measures

The server ensures that players cannot cheat by sending invalid moves or skipping a player's turn.

3. 🎨 Customizable Username and Game Name

Players can choose their own username and the name of the game they are playing. The seed of the game is automatically generated by the server.

🛠️ Technical Implementation

The integration of a WebSocket server is the backbone of these enhancements. The server handles real-time communication between clients, managing connections, message broadcasting, and synchronization of game states.

The server architecture splits the implementation into three main packages:

  • ch.epfl.chacun.server: Handles all the technical aspects of the server, such as the WebSocket server, the connection handlers, and the message handlers.
  • ch.epfl.chacun.game: Implements the game logic, such as the game state, the game actions, and the game rules.
  • ch.epfl.chacun.logic: Defines how the server should handle the messages received from the clients. This package is responsible for creating a game lobby, starting a game, and handling game actions, etc.

📜 RFC-6455 Implementation

The server follows the RFC-6455 WebSocket standard. All messages after connection are therefore decoded and encoded in the following format:

*  0                   1                   2                   3
*  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-------+-+-------------+-------------------------------+
* |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
* |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
* |N|V|V|V|       |S|             |   (if payload len==126/127)   |
* | |1|2|3|       |K|             |                               |
* +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
* |     Extended payload length continued, if payload len == 127  |
* + - - - - - - - - - - - - - - - +-------------------------------+
* |                               |Masking-key, if MASK set to 1  |
* +-------------------------------+-------------------------------+
* | Masking-key (continued)       |          Payload Data         |
* +-------------------------------- - - - - - - - - - - - - - - - +
* :                     Payload Data continued ...                :
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* |                     Payload Data continued ...                |
* +---------------------------------------------------------------+

The RFC6455 utility class is used to parse a payload into a PayloadData record. With the extracted data of the payload, we can then use the OpCode to determine the type of the message received:

Data Frames
  • TEXT for a text message
  • BINARY for a binary message
Control Frames

Control frames are used to communicate state about the WebSocket.

  • CLOSE for a close message
  • PING for a ping message
  • PONG for a pong message

Decoding Data

A client-to-server message is encoded using a masking key:
The masking key is a 32-bit value chosen at random by the client. The unpredictability of the masking key is essential to prevent authors of malicious applications from selecting the bytes that appear on the wire.

The server can decode the payload data by re-applying the mask key on the data.

Encoding Data

Contrary to the client-to-server message, the server-to-client message does not have a masking key. The server can directly encode the payload data and send it to the client.

🔄 Asynchronous WebSocket Server Implementation

The server uses the java.nio package to create an asynchronous server AsyncWebSocketServer, listening for incoming connections. When a client tries to connect, a new ChannelConnectionHandler is created to handle the connection. If the connection is accepted, a new ChannelReadHandler is created to process any incoming message.

1. 📢 Broadcast Messages

The abstract AsyncWebSocketServer extends the WebSocketBroadcaster abstract class which provides methods to broadcast messages to all connected clients of a game. Each client can subscribe to a specific game to receive messages and then unsubscribe.

2. 🛎️ Event Listener

A WebSocketBroadcaster extends the WebSocketEventListener abstract class which provides protected methods to handle events such as a new connection, a disconnection, or a message received.

This allows the server to define default behavior for these events, such as logging the event but also provides an easy way for the actual server implementation to override these methods and provide custom behavior.

3. ⏰ Timeout Watcher

The AsyncWebSocketServer class has a TimeoutWatcher that checks for timeouts on the server. If a client has not sent a message within a certain time frame, the server will close the connection.

4. 💻 Enhanced WebSocket Channel

Each AsynchronousSocketChannel is wrapped on connection in a WebSocketChannel class, which provides a lot of methods to read and write messages following the RFC-6455 standard. This also allows attaching a context object to the channel, which can be used to store information on the player (e.g., username).

🎲 Game Logic Implementation

The GameLogic class handles all actions related to the server. It is responsible for creating a game lobby, starting a game, handling game actions, broadcasting messages, etc. This class has a parseAndApplyWebSocketAction method that parses the message received from the client and applies the corresponding action. It returns a GameAction object, containing all the information needed for the server to send back an action if needed.

1. 🏠 Game Lobby

If a player wants to create a game, the server will create a new game lobby and add the player to it. If the first player to join the game lobby places a tile, the server will automatically start the game.

In a lobby, players can chat with each other and freely join/leave.

2. 🎮 OnGoing Game

When a game is started, the server will instantiate a new OnGoingGame. The OnGoingGame class is responsible for managing the game state, the game actions, and the game rules. If a player leaves in the middle of the game, the server will cancel the game. When a game ends, it will automatically be downgraded to a lobby.

🛠️ Actual Server Implementation

The WebSocketServer extends the AsyncWebSocketServer. It overrides the WebSocketEventListener methods to provide custom behavior for to match the game logic. For exemple, when a client sends a message, it will ask the GameLogic to parse and apply the action and send back a new action to the client, and broadcast it if needed.

📚 How to Use

If you want to use this server to add multiplayer support to your game, please read the documentation available at https://github.com/polysource-projects/cs108-chacun-multiplayer-docs.

About

A multiplayer server for the ChaCuN game.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published