This project is a proof-of-concept for a turn-based multiplayer online game server, exploring backend architecture, client-server communication, and game logic sharing.
The backend is built around a system of triggers and effects. Triggers are initiated by player commands or other system events. Effects listen for these triggers, modify the internal state of the game, and can create new triggers. This creates a reactive and predictable system.
To eliminate race conditions and ensure consistency, all commands from players within a single game session are evaluated sequentially by a single thread.
Communication between the client and server is implemented using WebSockets. Messages are serialized using Protocol Buffers (Protobuf) for efficient and strongly-typed data exchange.
A key feature of this project is the sharing of game logic, specifically command validation, between the Java-based server and the Angular-based client. This is achieved using GraalVM Polyglot on the server side.
The command approval logic is written in a single JavaScript file, command-validation/approval.js.
- Server: The Java server uses GraalVM to execute this JavaScript code, allowing it to validate commands authoritatively.
- Client: The Angular client fetches this same JavaScript file as static content from the server. It then dynamically imports and uses this logic to provide instant feedback to the user, for example, by disabling buttons for actions that are not currently allowed.
This approach avoids code duplication and ensures that the validation rules are consistent across both the client and the server.
- Java 21+
- Maven
- Node.js and npm
To start the game server, run the following command from the root of the project:
mvn clean compile exec:javaThe server will start on port 8080.
To start the Angular client, run:
(cd ./aster && npm install && npm run start)The client will be available at http://localhost:4200.
To start a game session, at least two players need to be in the queue. Open two browser tabs to
http://localhost:4200 to simulate two players joining the queue. A session will be created
automatically.