From b9ab4e5adefcc35deb7bb0d902ff73394d2521b3 Mon Sep 17 00:00:00 2001 From: ThePerkinrex Date: Tue, 17 Nov 2020 19:23:03 +0100 Subject: [PATCH] Add leave lobby --- protobuf/game.proto | 1 + server/src/db.rs | 18 ++++++++++-- server/src/grpc.rs | 17 ++++++++++-- server/src/grpc/game.rs | 32 ++++++++++++++++++++++ server/src/logger.rs | 2 +- unity/Assets/Scripts/Client.cs | 9 ++++-- unity/Assets/Scripts/MainMenuController.cs | 4 +-- unity/Assets/Scripts/grpc/Game.cs | 5 ++-- unity/Assets/Scripts/grpc/GameGrpc.cs | 32 +++++++++++++++++++++- 9 files changed, 107 insertions(+), 13 deletions(-) diff --git a/protobuf/game.proto b/protobuf/game.proto index 7b90e66..bcd195e 100644 --- a/protobuf/game.proto +++ b/protobuf/game.proto @@ -20,6 +20,7 @@ service Lobby { rpc vote(Vote) returns(Null); rpc ready(Null) returns(Null); rpc status(Null) returns(LobbyStatus); + rpc leave (Null) returns (Null); } message UserID { string id = 1; } diff --git a/server/src/db.rs b/server/src/db.rs index a8f78bb..1b55639 100644 --- a/server/src/db.rs +++ b/server/src/db.rs @@ -71,6 +71,8 @@ impl DbConnection { pub async fn create_lobby(&mut self, public: bool) -> u32 { let id = rand::random(); + + log::info!("Created the lobby {}", id); self.conn .execute(query_unchecked!( "INSERT INTO Lobbies(id, public) VALUES(?, ?)", @@ -83,6 +85,7 @@ impl DbConnection { } pub async fn join_lobby(&mut self, user: Uuid, lobby: u32) { + log::info!("{} joined the lobby {}", user, lobby); self.conn .execute(query_unchecked!( "INSERT INTO UsersInLobbies(UserId, LobbyId) VALUES(?, ?)", @@ -93,8 +96,15 @@ impl DbConnection { .unwrap(); // Server crashes if ids collide } - pub async fn close(self) { - self.conn.close().await.unwrap(); + pub async fn leave(&mut self, user: Uuid) { + log::info!("{} leaving the lobby", user); + self.conn + .execute(query_unchecked!( + "DELETE FROM UsersInLobbies WHERE UserId = ?", + user.as_bytes().to_vec(), + )) + .await + .unwrap(); } pub async fn getPublicLobbies(&mut self) -> Vec { @@ -103,4 +113,8 @@ impl DbConnection { .await .unwrap().into_iter().map(|(x,)| x as u32).collect() } + + pub async fn close(self) { + self.conn.close().await.unwrap(); + } } diff --git a/server/src/grpc.rs b/server/src/grpc.rs index c5fde2b..6e1b102 100644 --- a/server/src/grpc.rs +++ b/server/src/grpc.rs @@ -98,7 +98,7 @@ impl Connection for ConnectionService { .send(Ok(LobbyCode{code: id})) .unwrap(); } - conn.close(); + conn.close().await; Ok(Response::new(receiver)) } } @@ -138,6 +138,17 @@ impl Lobby for LobbyService { async fn status(&self, _request: Request) -> Result, Status> { todo!() } + + async fn leave(&self, request: tonic::Request) -> Result, 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(uuid).await; + conn.close().await; + Ok(Response::new(Null{})) + } } pub async fn start( @@ -150,7 +161,7 @@ pub async fn start( let games = Arc::new(games); let connection = ConnectionService { conn: arc.clone(), - properties, + properties: properties.clone(), games: games.clone(), }; let lobby = LobbyService { @@ -161,7 +172,7 @@ pub async fn start( Server::builder() .add_service(ConnectionServer::new(connection)) .add_service(LobbyServer::new(lobby)) - .serve("0.0.0.0:50052".parse().unwrap()) + .serve(properties.addr) .await .unwrap(); } diff --git a/server/src/grpc/game.rs b/server/src/grpc/game.rs index b93794a..f0c2172 100644 --- a/server/src/grpc/game.rs +++ b/server/src/grpc/game.rs @@ -371,6 +371,10 @@ pub mod lobby_server { &self, request: tonic::Request, ) -> Result, tonic::Status>; + async fn leave( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; } #[doc = " Lobby functionality (client_id required for most of them)"] #[derive(Debug)] @@ -517,6 +521,34 @@ pub mod lobby_server { }; Box::pin(fut) } + "/game.Lobby/leave" => { + #[allow(non_camel_case_types)] + struct leaveSvc(pub Arc); + impl tonic::server::UnaryService for leaveSvc { + type Response = super::Null; + type Future = BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).leave(request).await }; + Box::pin(fut) + } + } + let inner = self.inner.clone(); + let fut = async move { + let interceptor = inner.1.clone(); + let inner = inner.0; + let method = leaveSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = if let Some(interceptor) = interceptor { + tonic::server::Grpc::with_interceptor(codec, interceptor) + } else { + tonic::server::Grpc::new(codec) + }; + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => Box::pin(async move { Ok(http::Response::builder() .status(200) diff --git a/server/src/logger.rs b/server/src/logger.rs index 22846f0..1a3df1f 100644 --- a/server/src/logger.rs +++ b/server/src/logger.rs @@ -55,7 +55,7 @@ pub fn setup( fern::Dispatch::new() .level(log::LevelFilter::Debug) - .level_for("h2::codec", log::LevelFilter::Info) + .level_for("h2", log::LevelFilter::Info) .level_for("tokio::codec", log::LevelFilter::Info) .level_for("sqlx::query", log::LevelFilter::Info) .chain(stdout_logger) diff --git a/unity/Assets/Scripts/Client.cs b/unity/Assets/Scripts/Client.cs index 0c2bfde..cb8c162 100644 --- a/unity/Assets/Scripts/Client.cs +++ b/unity/Assets/Scripts/Client.cs @@ -68,7 +68,12 @@ public static class Client } } - public List getPublicLobbies() { + public void LeaveLobby() { + lobby_client.leave(new Game.Null(), new Metadata { new Metadata.Entry("client_id", connId) }); + lobby = null; + } + + public List GetPublicLobbies() { AsyncServerStreamingCall stream = connection.getPublicLobbies(new Game.Null()); List l = new List(); @@ -82,7 +87,7 @@ public static class Client return l; } - public List getGames() + public List GetGames() { AsyncServerStreamingCall stream = connection.getGames(new Game.Null()); List l = new List(); diff --git a/unity/Assets/Scripts/MainMenuController.cs b/unity/Assets/Scripts/MainMenuController.cs index 379a3dc..1113b38 100644 --- a/unity/Assets/Scripts/MainMenuController.cs +++ b/unity/Assets/Scripts/MainMenuController.cs @@ -140,7 +140,7 @@ public class MainMenuController : MonoBehaviour { // Simulate Lobbies in a Server var conn = Client.GetConnection(); if(conn != null) { - foreach(string lobby in conn.getPublicLobbies()) { + foreach(string lobby in conn.GetPublicLobbies()) { Debug.Log(lobby); } // conn.Close(); @@ -160,7 +160,7 @@ public class MainMenuController : MonoBehaviour { // Add Lobby Games to list when function exists var conn = Client.GetConnection(); if(conn != null) { - var games = conn.getGames(); + var games = conn.GetGames(); foreach(Game.Game game in games) { var gameGO = Instantiate(lobbyScroll.transform.GetChild(0), lobbyScroll.transform); gameGO.GetComponentsInChildren()[0].text = game.Name; diff --git a/unity/Assets/Scripts/grpc/Game.cs b/unity/Assets/Scripts/grpc/Game.cs index e0317f4..f304522 100644 --- a/unity/Assets/Scripts/grpc/Game.cs +++ b/unity/Assets/Scripts/grpc/Game.cs @@ -39,10 +39,11 @@ namespace Game { "Lk51bGwSMQoLY3JlYXRlTG9iYnkSES5nYW1lLkxvYmJ5Q29uZmlnGg8uZ2Ft", "ZS5Mb2JieUNvZGUSJAoIZ2V0R2FtZXMSCi5nYW1lLk51bGwaCi5nYW1lLkdh", "bWUwARIxChBnZXRQdWJsaWNMb2JiaWVzEgouZ2FtZS5OdWxsGg8uZ2FtZS5M", - "b2JieUNvZGUwATKcAQoFTG9iYnkSKQoMZ2V0Q2FyZEltYWdlEgwuZ2FtZS5D", + "b2JieUNvZGUwATK9AQoFTG9iYnkSKQoMZ2V0Q2FyZEltYWdlEgwuZ2FtZS5D", "YXJkSUQaCy5nYW1lLkltYWdlEh4KBHZvdGUSCi5nYW1lLlZvdGUaCi5nYW1l", "Lk51bGwSHwoFcmVhZHkSCi5nYW1lLk51bGwaCi5nYW1lLk51bGwSJwoGc3Rh", - "dHVzEgouZ2FtZS5OdWxsGhEuZ2FtZS5Mb2JieVN0YXR1c2IGcHJvdG8z")); + "dHVzEgouZ2FtZS5OdWxsGhEuZ2FtZS5Mb2JieVN0YXR1cxIfCgVsZWF2ZRIK", + "LmdhbWUuTnVsbBoKLmdhbWUuTnVsbGIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/unity/Assets/Scripts/grpc/GameGrpc.cs b/unity/Assets/Scripts/grpc/GameGrpc.cs index cb41003..ac46850 100644 --- a/unity/Assets/Scripts/grpc/GameGrpc.cs +++ b/unity/Assets/Scripts/grpc/GameGrpc.cs @@ -345,6 +345,13 @@ namespace Game { __Marshaller_game_Null, __Marshaller_game_LobbyStatus); + static readonly grpc::Method __Method_leave = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "leave", + __Marshaller_game_Null, + __Marshaller_game_Null); + /// Service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { @@ -375,6 +382,11 @@ namespace Game { throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); } + public virtual global::System.Threading.Tasks.Task leave(global::Game.Null request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + } /// Client for Lobby @@ -464,6 +476,22 @@ namespace Game { { return CallInvoker.AsyncUnaryCall(__Method_status, null, options, request); } + public virtual global::Game.Null leave(global::Game.Null request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return leave(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + public virtual global::Game.Null leave(global::Game.Null request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_leave, null, options, request); + } + public virtual grpc::AsyncUnaryCall leaveAsync(global::Game.Null request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return leaveAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + public virtual grpc::AsyncUnaryCall leaveAsync(global::Game.Null request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_leave, null, options, request); + } /// Creates a new instance of client from given ClientBaseConfiguration. protected override LobbyClient NewInstance(ClientBaseConfiguration configuration) { @@ -479,7 +507,8 @@ namespace Game { .AddMethod(__Method_getCardImage, serviceImpl.getCardImage) .AddMethod(__Method_vote, serviceImpl.vote) .AddMethod(__Method_ready, serviceImpl.ready) - .AddMethod(__Method_status, serviceImpl.status).Build(); + .AddMethod(__Method_status, serviceImpl.status) + .AddMethod(__Method_leave, serviceImpl.leave).Build(); } /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. @@ -492,6 +521,7 @@ namespace Game { serviceBinder.AddMethod(__Method_vote, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.vote)); serviceBinder.AddMethod(__Method_ready, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.ready)); serviceBinder.AddMethod(__Method_status, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.status)); + serviceBinder.AddMethod(__Method_leave, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.leave)); } }