Browse Source

Add more helper features for the game server

new_protocol
ThePerkinrex 5 years ago
parent
commit
234f101a65
No known key found for this signature in database GPG Key ID: 1F45A7C4BFB41607
  1. 14
      server/src/db.rs
  2. 3
      server/src/games/mod.rs
  3. 25
      server/src/games/run.rs
  4. 1
      server/src/games/run/functions.rs
  5. 5
      server/src/server.rs
  6. 10
      server/src/server/connection.rs
  7. 18
      server/src/server/lobby.rs
  8. 27
      server/src/server/votes.rs

14
server/src/db.rs

@ -82,6 +82,20 @@ impl Db {
.and_then(|r| r.map(|r| r.get(0)).collect())
.unwrap()
}
// FIXME: return Results intead of crashing
pub fn get_uuids_in_lobby_where_user_is(&mut self, uuid: Uuid) -> Vec<Uuid> {
let mut prepared = self.conn.prepare_cached("SELECT UUID FROM Users WHERE UUID in (SELECT UserId FROM UsersInLobbies WHERE LobbyId = (SELECT LobbyId FROM UsersInLobbies WHERE UserId = ?))").unwrap();
prepared
.query(params![uuid.as_bytes().to_vec()])
.and_then(|r| {
r.map(|r| r.get::<_, Vec<u8>>(0))
.map(|x| Ok(Uuid::from_slice(&x).unwrap()))
.collect()
})
.unwrap()
}
// FIXME: return Results intead of crashing
pub fn create_lobby(&mut self, public: bool) -> u32 {
let id = rand::random();

3
server/src/games/mod.rs

@ -4,6 +4,7 @@ mod config;
mod run;
pub use run::{CardId, CardIdx, PileKind, RunningGame};
use uuid::Uuid;
#[derive(Clone)]
pub struct Game {
@ -44,7 +45,7 @@ impl Game {
// self.authors.clone()
// }
pub fn run(&self, players: u32) -> run::RunningGame {
pub fn run(&self, players: &[Uuid]) -> run::RunningGame {
// let ast = rhai::Engine::new().compile_file(self.folder.join(&self.conf.script)).unwrap();
run::RunningGame::new(
self.name.clone(),

25
server/src/games/run.rs

@ -2,6 +2,7 @@ use rhai::{
serde::{from_dynamic, to_dynamic},
Dynamic, Func, AST,
};
use uuid::Uuid;
use std::collections::HashMap;
@ -22,6 +23,7 @@ pub struct RunningGame {
functions: Functions,
current_player: Player,
data: HashMap<String, serde_json::Value>,
players: HashMap<Uuid, u32>,
}
// TODO add errors
@ -40,30 +42,45 @@ impl RunningGame {
Ok((ast, fns))
}
pub fn new(name: String, ast: AST, fns: &[String], conf: &Config, players: u32) -> Self {
pub fn new(
name: String,
ast: AST,
fns: &[String],
conf: &Config,
current_players: &[Uuid],
) -> Self {
// log::info!("Fns: {:?}", fns);
let functions = Functions::new(fns, ast.clone(), &name);
let engine = setup_engine();
let setup = Func::<(Dynamic,), Dynamic>::create_from_ast(engine, ast, "setup");
let piles = conf.piles.clone();
let player_piles = vec![conf.player_piles.clone(); players as usize];
let player_piles = vec![conf.player_piles.clone(); current_players.len()];
let Data {
piles,
player_piles,
players: _,
other,
} = from_dynamic(
&setup(to_dynamic(Data::new(piles, player_piles, players)).unwrap()).unwrap(),
&setup(
to_dynamic(Data::new(piles, player_piles, current_players.len() as u32)).unwrap(),
)
.unwrap(),
)
.unwrap();
let mut players = HashMap::new();
for (i, player) in current_players.iter().enumerate() {
players.insert(player.clone(), i as u32);
}
log::info!("PLayers in game {}: {:?}", name, players);
Self {
name,
piles,
player_piles,
functions,
current_player: Player::new(0, players),
current_player: Player::new(0, current_players.len() as u32),
data: other,
players,
}
// Self {setup: Box::new(Func::<(Vec<Pile>, Vec<Vec<Pile>>), ()>::create_from_ast(engine, ast, "setup"))}
}

1
server/src/games/run/functions.rs

@ -52,6 +52,7 @@ impl Functions {
pub fn turn_end(&self, d: Dynamic, p: Player) -> RhaiResult<rhai::Array> {
self.engine
.call_fn(&mut Scope::new(), &self.ast, "turn_end", (d, p))
// TODO Check if the game has ended (With variable in the scope)
}
pub fn on_click(

5
server/src/server.rs

@ -24,14 +24,15 @@ pub async fn start(
let properties = Arc::new(properties);
let games = Arc::new(games);
let voting = votes::VotingSystem::new(pool.clone().await);
let running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame)>>>> = Default::default();
let connection = ConnectionService {
conn: RwLock::new(pool.clone().await),
properties: properties.clone(),
games: games.clone(),
voting: voting.clone(),
running_games: running_games.clone(),
};
let running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame)>>>> = Default::default();
let lobby = LobbyService::new(pool.clone().await, voting, running_games.clone());
let lobby = LobbyService::new(pool.clone().await, voting, games, running_games.clone());
let game = GameService::new(pool, running_games);
Server::builder()

10
server/src/server/connection.rs

@ -4,7 +4,7 @@ use log::info;
use tokio::sync::{mpsc, RwLock};
use std::sync::Arc;
use std::{collections::HashMap, sync::Arc};
use super::grpc::common::Name;
use super::grpc::connection_service::connection_server::Connection;
@ -16,12 +16,13 @@ use super::votes;
use super::client_id;
use crate::db;
use crate::{db, games::RunningGame};
pub struct ConnectionService {
pub conn: RwLock<db::DbClient>,
pub properties: Arc<crate::server_properties::ServerProperties>,
pub games: Arc<Vec<crate::games::Game>>,
pub running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame)>>>>,
pub voting: votes::VotingSystem,
}
@ -46,6 +47,11 @@ impl Connection for ConnectionService {
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
})?;
let lobby = request.get_ref().code;
if self.running_games.read().await.contains_key(&lobby) {
return Err(Status::permission_denied(
"Can't join a lobby where a game is running",
));
}
let mut conn = self.conn.write().await;
conn.join_lobby(uuid, lobby).await;
self.voting.updated_users(&lobby).await;

18
server/src/server/lobby.rs

@ -18,7 +18,7 @@ use crate::{db, games::RunningGame};
pub struct LobbyService {
conn: RwLock<db::DbClient>,
// games: Arc<Vec<crate::games::Game>>,
games: Arc<Vec<crate::games::Game>>,
voting: votes::VotingSystem,
running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame)>>>>,
}
@ -27,12 +27,14 @@ impl LobbyService {
pub fn new(
conn: db::DbClient,
voting: votes::VotingSystem,
games: Arc<Vec<crate::games::Game>>,
running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame)>>>>,
) -> Self {
Self {
conn: RwLock::new(conn),
voting,
running_games,
games,
}
}
}
@ -54,15 +56,15 @@ impl Lobby for LobbyService {
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
})?;
let finished = self.voting.ready(uuid).await;
if let Some(finished) = finished {
let user_count = self
.conn
if let Some(Some(winner)) = self.voting.ready(uuid).await {
let mut conn = self.conn.write().await;
let lobby = conn.get_lobby_for_user(uuid).await.unwrap();
let user_count = conn.get_uuids_in_lobby_where_user_is(uuid).await;
let game = self.games[winner as usize].run(&user_count);
self.running_games
.write()
.await
.get_users_in_lobby_where_user_is(uuid)
.await
.len();
.insert(lobby, RwLock::new((winner, game)));
}
Ok(Response::new(()))
}

27
server/src/server/votes.rs

@ -150,7 +150,7 @@ impl VotingSystem {
}
}
pub async fn ready(&self, user: Uuid) -> Option<bool> {
pub async fn ready(&self, user: Uuid) -> Option<Option<u32>> {
let mut conn = self.conn.write().await;
if let Some(lobby) = conn.get_lobby_for_user(user).await {
conn.vote_ready(user).await;
@ -158,14 +158,37 @@ impl VotingSystem {
let status = conn.get_votes(lobby).await;
if finished {
conn.delete_votes(lobby).await;
let winner = get_winner(status.iter().map(|(_, g, _)| g));
self.change_status_with_timeout(lobby, (status, finished), Some(SystemTime::now()))
.await;
Some(Some(winner))
} else {
self.change_status(lobby, (status, finished)).await;
Some(None)
}
Some(finished)
} else {
None
}
}
}
fn get_winner<'a, I: Iterator<Item = &'a u32>>(iter: I) -> u32 {
let mut count: HashMap<u32, u32> = Default::default();
for item in iter {
if let Some(e) = count.get_mut(item) {
*e += 1;
} else {
count.insert(*item, 1);
}
}
count
.into_iter()
.fold((0, 0), |(max_game, max_num), (game, num)| {
if num > max_num {
(game, num)
} else {
(max_game, max_num)
}
})
.0
}

Loading…
Cancel
Save