12 changed files with 435 additions and 266 deletions
@ -1,223 +0,0 @@ |
|||||
use tonic::{transport::Server, Request, Response, Status}; |
|
||||
|
|
||||
use log::info; |
|
||||
|
|
||||
use std::sync::Arc; |
|
||||
|
|
||||
#[allow(non_camel_case_types)] |
|
||||
mod game; |
|
||||
|
|
||||
use game::connection_server::{Connection, ConnectionServer}; |
|
||||
use game::lobby_server::{Lobby, LobbyServer}; |
|
||||
use game::{CardId, Image, LobbyCode, LobbyConfig, Name, Null, UserId}; |
|
||||
|
|
||||
use crate::db; |
|
||||
|
|
||||
pub struct ConnectionService { |
|
||||
conn: Arc<db::DbPool>, |
|
||||
properties: Arc<crate::server_properties::ServerProperties>, |
|
||||
games: Arc<Vec<crate::games::Game>>, |
|
||||
} |
|
||||
|
|
||||
#[tonic::async_trait] |
|
||||
impl Connection for ConnectionService { |
|
||||
async fn connect(&self, request: Request<Name>) -> Result<Response<UserId>, Status> { |
|
||||
let name = request.into_inner().name; |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
let uuid = conn.add_user(&name).await; |
|
||||
info!("Connected {}[{}]", name, uuid); |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(UserId { |
|
||||
id: uuid.to_hyphenated().to_string(), |
|
||||
})) |
|
||||
} |
|
||||
|
|
||||
async fn join_lobby_with_code( |
|
||||
&self, |
|
||||
request: Request<LobbyCode>, |
|
||||
) -> Result<Response<Null>, Status> { |
|
||||
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
|
||||
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
|
||||
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
|
||||
})?; |
|
||||
let lobby = request.get_ref().code; |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
conn.join_lobby(uuid, lobby).await; |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(Null {})) |
|
||||
} |
|
||||
|
|
||||
async fn create_lobby( |
|
||||
&self, |
|
||||
request: Request<LobbyConfig>, |
|
||||
) -> Result<Response<LobbyCode>, Status> { |
|
||||
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
|
||||
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
|
||||
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
|
||||
})?; |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
let lobby = conn.create_lobby(request.into_inner().public).await; |
|
||||
conn.join_lobby(uuid, lobby).await; |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(LobbyCode { code: lobby })) |
|
||||
} |
|
||||
|
|
||||
async fn name(&self, _request: Request<Null>) -> Result<Response<game::Name>, Status> { |
|
||||
Ok(Response::new(game::Name { |
|
||||
name: self.properties.name.clone(), |
|
||||
})) |
|
||||
} |
|
||||
|
|
||||
type getGamesStream = mpsc::UnboundedReceiver<Result<game::Game, tonic::Status>>; |
|
||||
|
|
||||
async fn get_games(&self, _: Request<Null>) -> Result<Response<Self::getGamesStream>, Status> { |
|
||||
let (sender, receiver) = mpsc::unbounded_channel(); |
|
||||
for (id, game) in self.games.iter().enumerate() { |
|
||||
sender |
|
||||
.send(Ok(game::Game { |
|
||||
id: id as u32, |
|
||||
name: game.name.clone(), |
|
||||
version: game.version.clone(), |
|
||||
authors: game.authors.clone(), |
|
||||
})) |
|
||||
.unwrap(); |
|
||||
} |
|
||||
Ok(Response::new(receiver)) |
|
||||
} |
|
||||
|
|
||||
type getPublicLobbiesStream = mpsc::UnboundedReceiver<Result<LobbyCode, tonic::Status>>; |
|
||||
|
|
||||
async fn get_public_lobbies( |
|
||||
&self, |
|
||||
_request: Request<Null>, |
|
||||
) -> Result<Response<Self::getPublicLobbiesStream>, Status> { |
|
||||
let (sender, receiver) = mpsc::unbounded_channel(); |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
for id in conn.getPublicLobbies().await { |
|
||||
sender.send(Ok(LobbyCode { code: id })).unwrap(); |
|
||||
} |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(receiver)) |
|
||||
} |
|
||||
|
|
||||
async fn disconnect(&self, request: Request<Null>) -> Result<Response<Null>, Status> { |
|
||||
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
|
||||
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
|
||||
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
|
||||
})?; |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
conn.disconnect(&uuid).await; |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(Null {})) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
use tokio::sync::mpsc; |
|
||||
|
|
||||
pub struct LobbyService { |
|
||||
conn: Arc<db::DbPool>, |
|
||||
games: Arc<Vec<crate::games::Game>>, |
|
||||
} |
|
||||
|
|
||||
#[tonic::async_trait] |
|
||||
impl Lobby for LobbyService { |
|
||||
async fn get_card_image( |
|
||||
&self, |
|
||||
request: tonic::Request<CardId>, |
|
||||
) -> Result<tonic::Response<Image>, tonic::Status> { |
|
||||
let id = request.into_inner(); |
|
||||
let game = &self.games.as_ref()[id.game_id as usize]; |
|
||||
let card = game.get_card_path(&id.card_id); |
|
||||
let mut buffer = Vec::new(); |
|
||||
image::open(&card) |
|
||||
.expect(&format!("Error loading the image in {:?}", card)) |
|
||||
.write_to(&mut buffer, image::ImageOutputFormat::Png) |
|
||||
.unwrap(); |
|
||||
Ok(Response::new(Image { content: buffer })) |
|
||||
} |
|
||||
|
|
||||
async fn vote(&self, _request: Request<game::Vote>) -> Result<Response<Null>, Status> { |
|
||||
todo!() |
|
||||
} |
|
||||
|
|
||||
async fn ready(&self, _request: Request<Null>) -> Result<Response<Null>, Status> { |
|
||||
todo!() |
|
||||
} |
|
||||
|
|
||||
async fn status(&self, _request: Request<Null>) -> Result<Response<game::LobbyStatus>, Status> { |
|
||||
todo!() |
|
||||
} |
|
||||
|
|
||||
async fn leave( |
|
||||
&self, |
|
||||
request: tonic::Request<Null>, |
|
||||
) -> Result<tonic::Response<Null>, tonic::Status> { |
|
||||
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
|
||||
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
|
||||
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
|
||||
})?; |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
conn.leave_lobby(&uuid).await; |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(Null {})) |
|
||||
} |
|
||||
|
|
||||
type usersStream = mpsc::UnboundedReceiver<Result<Name, tonic::Status>>; |
|
||||
|
|
||||
async fn users(&self, request: Request<Null>) -> Result<Response<Self::usersStream>, Status> { |
|
||||
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
|
||||
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
|
||||
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
|
||||
})?; |
|
||||
let (sender, receiver) = mpsc::unbounded_channel(); |
|
||||
let mut conn = self.conn.acquire().await; |
|
||||
for name in conn.getUsersInLobbyWhereUserIs(uuid).await { |
|
||||
sender.send(Ok(Name {name})).unwrap(); |
|
||||
} |
|
||||
conn.close().await; |
|
||||
Ok(Response::new(receiver)) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
pub async fn start( |
|
||||
pool: db::DbPool, |
|
||||
games: Vec<crate::games::Game>, |
|
||||
properties: crate::server_properties::ServerProperties, |
|
||||
) { |
|
||||
let arc = Arc::new(pool); |
|
||||
let properties = Arc::new(properties); |
|
||||
let games = Arc::new(games); |
|
||||
let connection = ConnectionService { |
|
||||
conn: arc.clone(), |
|
||||
properties: properties.clone(), |
|
||||
games: games.clone(), |
|
||||
}; |
|
||||
let lobby = LobbyService { |
|
||||
conn: arc.clone(), |
|
||||
games, |
|
||||
}; |
|
||||
|
|
||||
Server::builder() |
|
||||
.add_service(ConnectionServer::new(connection)) |
|
||||
.add_service(LobbyServer::new(lobby)) |
|
||||
.serve(properties.addr) |
|
||||
.await |
|
||||
.unwrap(); |
|
||||
} |
|
||||
|
|
||||
mod client_id { |
|
||||
pub fn get(metadata: &tonic::metadata::MetadataMap) -> Result<uuid::Uuid, Error> { |
|
||||
metadata |
|
||||
.get("client_id") |
|
||||
.ok_or(Error::NotSet) |
|
||||
.and_then(|x| { |
|
||||
uuid::Uuid::parse_str(x.to_str().map_err(|_| Error::MalformedUuid)?) |
|
||||
.map_err(|_| Error::MalformedUuid) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
pub enum Error { |
|
||||
MalformedUuid, |
|
||||
NotSet, |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,55 @@ |
|||||
|
use tonic::transport::Server; |
||||
|
|
||||
|
use std::sync::Arc; |
||||
|
|
||||
|
use crate::db; |
||||
|
|
||||
|
mod connection; |
||||
|
mod grpc; |
||||
|
mod lobby; |
||||
|
|
||||
|
use grpc::game::connection_server::ConnectionServer; |
||||
|
use grpc::game::lobby_server::LobbyServer; |
||||
|
|
||||
|
use connection::ConnectionService; |
||||
|
use lobby::LobbyService; |
||||
|
|
||||
|
pub async fn start( |
||||
|
pool: db::DbPool, |
||||
|
games: Vec<crate::games::Game>, |
||||
|
properties: crate::server_properties::ServerProperties, |
||||
|
) { |
||||
|
let arc = Arc::new(pool); |
||||
|
let properties = Arc::new(properties); |
||||
|
let games = Arc::new(games); |
||||
|
let connection = ConnectionService { |
||||
|
conn: arc.clone(), |
||||
|
properties: properties.clone(), |
||||
|
games: games.clone(), |
||||
|
}; |
||||
|
let lobby = LobbyService::new(arc.clone(), games); |
||||
|
|
||||
|
Server::builder() |
||||
|
.add_service(ConnectionServer::new(connection)) |
||||
|
.add_service(LobbyServer::new(lobby)) |
||||
|
.serve(properties.addr) |
||||
|
.await |
||||
|
.unwrap(); |
||||
|
} |
||||
|
|
||||
|
mod client_id { |
||||
|
pub fn get(metadata: &tonic::metadata::MetadataMap) -> Result<uuid::Uuid, Error> { |
||||
|
metadata |
||||
|
.get("client_id") |
||||
|
.ok_or(Error::NotSet) |
||||
|
.and_then(|x| { |
||||
|
uuid::Uuid::parse_str(x.to_str().map_err(|_| Error::MalformedUuid)?) |
||||
|
.map_err(|_| Error::MalformedUuid) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
pub enum Error { |
||||
|
MalformedUuid, |
||||
|
NotSet, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,113 @@ |
|||||
|
use tonic::{Request, Response, Status}; |
||||
|
|
||||
|
use log::info; |
||||
|
|
||||
|
use tokio::sync::mpsc; |
||||
|
|
||||
|
use std::sync::Arc; |
||||
|
|
||||
|
use super::grpc::game::connection_server::Connection; |
||||
|
use super::grpc::game::{LobbyCode, LobbyConfig, Name, Null, UserId, Game}; |
||||
|
|
||||
|
use super::client_id; |
||||
|
|
||||
|
use crate::db; |
||||
|
|
||||
|
pub struct ConnectionService { |
||||
|
pub conn: Arc<db::DbPool>, |
||||
|
pub properties: Arc<crate::server_properties::ServerProperties>, |
||||
|
pub games: Arc<Vec<crate::games::Game>>, |
||||
|
} |
||||
|
|
||||
|
#[tonic::async_trait] |
||||
|
impl Connection for ConnectionService { |
||||
|
async fn connect(&self, request: Request<Name>) -> Result<Response<UserId>, Status> { |
||||
|
let name = request.into_inner().name; |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
let uuid = conn.add_user(&name).await; |
||||
|
info!("Connected {}[{}]", name, uuid); |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(UserId { |
||||
|
id: uuid.to_hyphenated().to_string(), |
||||
|
})) |
||||
|
} |
||||
|
|
||||
|
async fn join_lobby_with_code( |
||||
|
&self, |
||||
|
request: Request<LobbyCode>, |
||||
|
) -> Result<Response<Null>, Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
let lobby = request.get_ref().code; |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
conn.join_lobby(uuid, lobby).await; |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(Null {})) |
||||
|
} |
||||
|
|
||||
|
async fn create_lobby( |
||||
|
&self, |
||||
|
request: Request<LobbyConfig>, |
||||
|
) -> Result<Response<LobbyCode>, Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
let lobby = conn.create_lobby(request.into_inner().public).await; |
||||
|
conn.join_lobby(uuid, lobby).await; |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(LobbyCode { code: lobby })) |
||||
|
} |
||||
|
|
||||
|
async fn name(&self, _request: Request<Null>) -> Result<Response<Name>, Status> { |
||||
|
Ok(Response::new(Name { |
||||
|
name: self.properties.name.clone(), |
||||
|
})) |
||||
|
} |
||||
|
|
||||
|
type getGamesStream = mpsc::UnboundedReceiver<Result<Game, tonic::Status>>; |
||||
|
|
||||
|
async fn get_games(&self, _: Request<Null>) -> Result<Response<Self::getGamesStream>, Status> { |
||||
|
let (sender, receiver) = mpsc::unbounded_channel(); |
||||
|
for (id, game) in self.games.iter().enumerate() { |
||||
|
sender |
||||
|
.send(Ok(Game { |
||||
|
id: id as u32, |
||||
|
name: game.name.clone(), |
||||
|
version: game.version.clone(), |
||||
|
authors: game.authors.clone(), |
||||
|
})) |
||||
|
.unwrap(); |
||||
|
} |
||||
|
Ok(Response::new(receiver)) |
||||
|
} |
||||
|
|
||||
|
type getPublicLobbiesStream = mpsc::UnboundedReceiver<Result<LobbyCode, tonic::Status>>; |
||||
|
|
||||
|
async fn get_public_lobbies( |
||||
|
&self, |
||||
|
_request: Request<Null>, |
||||
|
) -> Result<Response<Self::getPublicLobbiesStream>, Status> { |
||||
|
let (sender, receiver) = mpsc::unbounded_channel(); |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
for id in conn.get_public_lobbies().await { |
||||
|
sender.send(Ok(LobbyCode { code: id })).unwrap(); |
||||
|
} |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(receiver)) |
||||
|
} |
||||
|
|
||||
|
async fn disconnect(&self, request: Request<Null>) -> Result<Response<Null>, Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
conn.disconnect(&uuid).await; |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(Null {})) |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
#[allow(non_camel_case_types)] |
||||
|
pub mod game; |
||||
@ -0,0 +1,94 @@ |
|||||
|
mod votes; |
||||
|
|
||||
|
use tonic::{Request, Response, Status}; |
||||
|
|
||||
|
use log::info; |
||||
|
|
||||
|
use tokio::sync::mpsc; |
||||
|
|
||||
|
use std::sync::Arc; |
||||
|
|
||||
|
use super::grpc::game::lobby_server::Lobby; |
||||
|
use super::grpc::game::{CardId, Image, LobbyStatus, Name, Null, Vote}; |
||||
|
|
||||
|
use super::client_id; |
||||
|
|
||||
|
use crate::db; |
||||
|
|
||||
|
pub struct LobbyService { |
||||
|
conn: Arc<db::DbPool>, |
||||
|
games: Arc<Vec<crate::games::Game>>, |
||||
|
voting: votes::VotingSystem, |
||||
|
} |
||||
|
|
||||
|
impl LobbyService { |
||||
|
pub fn new(conn: Arc<db::DbPool>, games: Arc<Vec<crate::games::Game>>) -> Self { |
||||
|
Self { games, conn: conn.clone(), voting: votes::VotingSystem::new(conn).0 } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#[tonic::async_trait] |
||||
|
impl Lobby for LobbyService { |
||||
|
async fn get_card_image( |
||||
|
&self, |
||||
|
request: tonic::Request<CardId>, |
||||
|
) -> Result<tonic::Response<Image>, tonic::Status> { |
||||
|
let id = request.into_inner(); |
||||
|
let game = &self.games.as_ref()[id.game_id as usize]; |
||||
|
let card = game.get_card_path(&id.card_id); |
||||
|
let mut buffer = Vec::new(); |
||||
|
image::open(&card) |
||||
|
.expect(&format!("Error loading the image in {:?}", card)) |
||||
|
.write_to(&mut buffer, image::ImageOutputFormat::Png) |
||||
|
.unwrap(); |
||||
|
Ok(Response::new(Image { content: buffer })) |
||||
|
} |
||||
|
|
||||
|
async fn vote(&self, request: Request<Vote>) -> Result<Response<Null>, Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
// self.votes.vote(uuid, request.into_inner().id).await;
|
||||
|
// log::info!("Votes: {:?}", self.votes.get_votes().await);
|
||||
|
Ok(Response::new(Null {})) |
||||
|
} |
||||
|
|
||||
|
async fn ready(&self, _request: Request<Null>) -> Result<Response<Null>, Status> { |
||||
|
todo!() |
||||
|
} |
||||
|
|
||||
|
async fn status(&self, _request: Request<Null>) -> Result<Response<LobbyStatus>, Status> { |
||||
|
todo!() |
||||
|
} |
||||
|
|
||||
|
async fn leave( |
||||
|
&self, |
||||
|
request: tonic::Request<Null>, |
||||
|
) -> Result<tonic::Response<Null>, tonic::Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
conn.leave_lobby(&uuid).await; |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(Null {})) |
||||
|
} |
||||
|
|
||||
|
type usersStream = mpsc::UnboundedReceiver<Result<Name, tonic::Status>>; |
||||
|
|
||||
|
async fn users(&self, request: Request<Null>) -> Result<Response<Self::usersStream>, Status> { |
||||
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x { |
||||
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), |
||||
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), |
||||
|
})?; |
||||
|
let (sender, receiver) = mpsc::unbounded_channel(); |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
for name in conn.get_users_in_lobby_where_user_is(uuid).await { |
||||
|
sender.send(Ok(Name { name })).unwrap(); |
||||
|
} |
||||
|
conn.close().await; |
||||
|
Ok(Response::new(receiver)) |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
use tokio::sync::broadcast; |
||||
|
use uuid::Uuid; |
||||
|
|
||||
|
use std::sync::Arc; |
||||
|
|
||||
|
use crate::db; |
||||
|
|
||||
|
type Message = Vec<(String, u32, bool)>; |
||||
|
|
||||
|
pub struct VotingSystem { |
||||
|
conn: Arc<db::DbPool>, |
||||
|
// games: Arc<Vec<crate::games::Game>>,
|
||||
|
broadcast: broadcast::Sender<Message>, |
||||
|
} |
||||
|
|
||||
|
impl VotingSystem { |
||||
|
pub fn new( |
||||
|
conn: Arc<db::DbPool>, |
||||
|
// games: Arc<Vec<crate::games::Game>>,
|
||||
|
) -> (Self, broadcast::Receiver<Message>) { |
||||
|
let (tx, rx) = broadcast::channel(1); |
||||
|
( |
||||
|
Self { |
||||
|
conn, |
||||
|
// games,
|
||||
|
broadcast: tx, |
||||
|
}, |
||||
|
rx, |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
pub fn subscribe(&self) -> broadcast::Receiver<Message> { |
||||
|
self.broadcast.subscribe() |
||||
|
} |
||||
|
|
||||
|
pub async fn vote(&self, user: Uuid, game: u32) { |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
if let Some(lobby) = conn.get_lobby_for_user(&user).await { |
||||
|
conn.vote(user, game).await; |
||||
|
let status = conn.get_votes(lobby).await; |
||||
|
self.broadcast.send(status).unwrap(); |
||||
|
|
||||
|
} |
||||
|
conn.close().await; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
pub async fn ready(&self, user: Uuid) { |
||||
|
let mut conn = self.conn.acquire().await; |
||||
|
if let Some(lobby) = conn.get_lobby_for_user(&user).await { |
||||
|
conn.vote_ready(user).await; |
||||
|
let status = conn.get_votes(lobby).await; |
||||
|
self.broadcast.send(status).unwrap(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
conn.close().await; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue