1 stable release
1.0.2 | Jan 7, 2022 |
---|
#213 in WebSocket
18KB
152 lines
cg-game-server
About
This is a library that consists mostly of traits that are meant to speed up and standardize the development of CodeGame game servers.
It's the server's job to keep the players connected to each other and prevent them from cheating using minimal server-side state. All decisions are made by the client but always verified by the server.
Installation
Add the following dependencies to your Cargo.toml:
# this lib
cg-game-server = "0.1.0"
# CodeGame uses actix as its web framework, the traits in this project are built for actix
actix = "0.10"
actix-web = {version = "3", features = ["openssl"]}
actix-web-actors = "3"
# the project uses serde and serde_json to communicate with the clients
serde = {version = "1.0.133", features = ["derive"]}
serde_json = "1.0.74"
How to use
TL;DR: For some examples, please see the official games.
Apart from the main.rs
module that starts the webserver, each CodeGame game server consists of three parts:
Here's a closer look at each:
Events
Events are structs
that represent an action. Events flow between sockets and them and their clients, carrying data with them.
There are two types of events ReceiveableEvents
(R
in generics), which are sent to the server by a client (received by a socket), and SendableEvents
(S
in generics), which are sent between sockets.
When creating your own events it is recommended that you create two enums
. Be sure to include the standard events in your enums too. It should look something like this:
use cg_game_server::events::{Error, Join, Leave};
use actix::prelude::Message;
use serde::{Deserialize, Serialize};
use std::result::Result;
/// Deserialization `Result` for deserializing `ReceiveableEvents`
pub type ReceiveableEventSerde = Result<ReceiveableEvents, serde_json::Error>;
/// Events that the client may send to the server
#[derive(Serialize, Deserialize, Debug, Message, Clone)]
#[rtype(result = "()")]
#[serde(tag = "event_name")]
pub enum ReceiveableEvents {
#[serde(rename = "join")]
Join(Join),
#[serde(rename = "leave")]
Leave(Leave),
}
/// Events that the server may send to the client
#[derive(Serialize, Debug, Message, Clone)]
#[rtype(result = "()")]
#[serde(tag = "event_name")]
pub enum SendableEvents {
#[serde(rename = "error")]
Error(Error),
#[serde(rename = "join")]
Joined(Join),
#[serde(rename = "leave")]
Left(Leave),
}
Socket
The Socket
(C
in generics) is what client connects to. It contains the game logic and is responsible for interpreting events sent by the client. Furthermore it sends all events that it reiceives from other sockets to the client.
A socket is required to impl
ement the following:
actix::Actor
-> required by actix, can send and receive messagesactix::StreamHandler
-> required by actix, handles WebSocket communicationactix::Handler<EventWrapper<S>>
required by CodeGame, handlesSendableEvents
sent to a socketactix::GameServerCommunications<G, R>
required by CodeGame, makes sure that the basic game server communication functions are available for everyimpl
ementation ofSocket
Server
The GameServer
(G
in generics) is the middle man. Its actix::Addr
is passed to each new socket. Sockets can send events to the game server which it either processes or relays to other sockets.
A server is required to impl
ement the following:
actix::Actor
-> required by actix, can send and receive messagesactix::Handler<EventWrapper<S>>
required by CodeGame, handlesSendableEvents
sent to socketsactix::Handler<EventWrapper<Connect<C>>>
required by CodeGame, handlesConnect
events sent to the serveractix::Handler<EventWrapper<Disconnect>>
required by CodeGame, handlesDisconnect
events sent to the serveractix::Handler<EventWrapper<Join>>
required by CodeGame, handlesJoin
events sent to the serveractix::Handler<EventWrapper<Leave>>
required by CodeGame, handlesLeave
events sent to the server
Dependencies
~30MB
~606K SLoC