Skip to content

Commit

Permalink
Kick of game server
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 committed Nov 29, 2022
1 parent 494096b commit 71690d7
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ de_ui = { path = "crates/ui", version = "0.1.0-dev" }
de_uom = { path = "crates/uom", version = "0.1.0-dev" }

# Other
actix-web = "4.2.1"
ahash = "0.7.6"
anyhow = "1.0"
approx = "0.5.1"
Expand All @@ -98,6 +99,7 @@ gltf = "1.0"
itertools = "0.10.5"
iyes_loopless = "0.9.1"
iyes_progress = { version = "0.7.1", features = [ "iyes_loopless" ] }
jsonwebtoken = "8.1.1"
nalgebra = { version = "0.31.0", features = ["convert-glam022"] }
ntest = "0.9.0"
parry2d = "0.11.0"
Expand Down
17 changes: 17 additions & 0 deletions crates/server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "de_server"
description = "Digital Extinction lobby server."

version.workspace = true
edition.workspace = true
authors.workspace = true
repository.workspace = true
keywords.workspace = true
homepage.workspace = true
license.workspace = true
categories.workspace = true

[dependencies]
actix-web.workspace = true
jsonwebtoken.workspace = true
serde.workspace = true
78 changes: 78 additions & 0 deletions crates/server/src/game.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::{
collections::HashMap,
sync::{Mutex, MutexGuard},
};

use serde::{Deserialize, Serialize};

#[derive(Default)]
pub struct Games(Mutex<GamesInner>);

impl Games {
pub fn inner(&self) -> MutexGuard<'_, GamesInner> {
self.0.lock().unwrap()
}
}

#[derive(Default)]
pub struct GamesInner {
max_id: u16,
games: HashMap<u16, Game>,
}

impl GamesInner {
pub fn games(&self) -> &HashMap<u16, Game> {
&self.games
}

pub fn new_game(&mut self, config: GameConfig) {
self.games.insert(self.max_id, Game::empty(config));
self.max_id = self.max_id.wrapping_add(1);
}
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Game {
config: GameConfig,
players: Vec<String>,
}

impl Game {
pub fn empty(config: GameConfig) -> Self {
Self {
config,
players: Vec::new(),
}
}

/// Adds the player into the game.
///
/// # Panics
///
/// May panic if the player is already part of the game.
pub fn join(&mut self, player: &str) -> Result<(), JoinError> {
if self.config.max_players as usize <= self.players.len() {
return Err(JoinError::GameIsFull);
}

debug_assert!(self.players.iter().all(|p| p != player));
self.players.push(player.into());
Ok(())
}
}

pub enum JoinError {
GameIsFull,
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameConfig {
name: String,
max_players: u8,
}

impl GameConfig {
// TODO
}
59 changes: 59 additions & 0 deletions crates/server/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use game::{Game, GameConfig, Games};
use user::Users;

mod game;
mod user;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
let users_data = web::Data::new(Users::default());
let games_data = web::Data::new(Games::default());

HttpServer::new(move || {
let json_cfg = web::JsonConfig::default()
// TODO a constant
.limit(10 * 1024)
.content_type_required(true);
// TODO
//.content_type(|mime| mime == mime::APPLICATION_JSON);

let users_scope = web::scope("/users");
let games_scope = web::scope("/games")
.app_data(games_data.clone())
.service(list_games)
.service(create_game);

App::new()
.app_data(users_data.clone())
.service(users_scope)
.service(games_scope)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}

// TODO sing-up / sign-in request
// TODO validate JWT in every other request
// TODO join game
// TODO leave game game
// TODO remove game if everybody abandons it
// TODO start game (remove it and create rendezvous)

#[get("/")]
async fn list_games(games: web::Data<Games>) -> impl Responder {
HttpResponse::Ok().json(games.inner().games())
}

#[post("/")]
async fn create_game(games: web::Data<Games>, game: web::Json<GameConfig>) -> impl Responder {
// TODO require user ID header
// TODO disconnect user from other games (including this one -> re-connect)
// TODO place the user into the game

// TODO validate game parameters
// * 2 <= max_players <= 4
games.inner().new_game(game.0);
HttpResponse::Ok().json(())
}
32 changes: 32 additions & 0 deletions crates/server/src/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::{
collections::HashMap,
sync::{Mutex, MutexGuard},
};

use serde::{Deserialize, Serialize};

#[derive(Default)]
pub struct Users(Mutex<UsersInner>);

impl Users {
pub fn inner(&self) -> MutexGuard<'_, UsersInner> {
self.0.lock().unwrap()
}
}

#[derive(Default)]
pub struct UsersInner {
users: HashMap<String, User>,
}

impl UsersInner {
pub fn get(&self, id: &str) -> Option<&User> {
self.users.get(id)
}
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct User {
name: String,
}

0 comments on commit 71690d7

Please sign in to comment.