Quick refactor, project structure
This commit is contained in:
		
							parent
							
								
									ab25fa0267
								
							
						
					
					
						commit
						ab3c28ff37
					
				
							
								
								
									
										98
									
								
								src/client.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/client.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| use tokio::sync::Mutex; | ||||
| use futures::{ | ||||
|     select, | ||||
|     FutureExt, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| use hexland_server::{ | ||||
|     GlobalState, | ||||
|     Channel, | ||||
|     channel_pair, | ||||
|     GameController, | ||||
|     message::{Message, MessageWebSocket}, | ||||
|     msg, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| pub struct Client { | ||||
|     global_state: Arc<GlobalState>, | ||||
|     ws: MessageWebSocket, | ||||
|     channel: Option<Channel>, | ||||
| } | ||||
| 
 | ||||
| impl Client { | ||||
|     pub fn new(ws: MessageWebSocket, global_state: Arc<GlobalState>) -> Self { | ||||
|         Client { | ||||
|             global_state, | ||||
|             ws, | ||||
|             channel: None | ||||
|         } | ||||
|     } | ||||
|     pub async fn run(&mut self) { | ||||
|         loop { | ||||
|             match &mut self.channel { | ||||
|                 Some(channel) => { | ||||
|                     select! { | ||||
|                         msg = channel.rx.recv().fuse() => | ||||
|                             self.handle_server_msg(msg.unwrap()).await, | ||||
|                         msg = self.ws.next().fuse() => | ||||
|                             self.handle_client_msg(msg.unwrap()).await, | ||||
|                     }; | ||||
|                 } | ||||
|                 None => { | ||||
|                     let msg = self.ws.next().await; | ||||
|                     self.handle_client_msg(msg.unwrap()).await; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     async fn handle_client_msg(&mut self, msg: Message) { | ||||
|         match msg.command.as_str() { | ||||
|             "HOST" => { | ||||
|                 let room_code = self.global_state.code_generator.lock().await.generate(); | ||||
|                 let mut game_controller = GameController::default(); | ||||
| 
 | ||||
|                 let (client_channel, server_channel) = channel_pair(); | ||||
|                 self.channel = Some(client_channel); | ||||
|                 game_controller.channels.push(server_channel); | ||||
| 
 | ||||
|                 let game_controller = Arc::new(Mutex::new(game_controller)); | ||||
|                 self.global_state.rooms.lock().await.insert(room_code.clone(), Arc::clone(&game_controller)); | ||||
|                 tokio::spawn(async move {game_loop(game_controller)}); | ||||
|                 self.ws.send(msg!("ROOM_CODE", room_code)).await.unwrap(); | ||||
|             } | ||||
|             "JOIN" => { | ||||
|                 let room_code = &msg.args[0]; | ||||
|                 let rooms = self.global_state.rooms.lock().await; | ||||
|                 let room = rooms.get(room_code); | ||||
| 
 | ||||
|                 match room { | ||||
|                     Some(room) => { | ||||
|                         let mut room = room.lock().await; | ||||
|                         let (client_channel, server_channel) = channel_pair(); | ||||
|                         self.channel = Some(client_channel); | ||||
|                         room.channels.push(server_channel); | ||||
|                         self.ws.send(msg!("JOIN_OK")).await.unwrap(); | ||||
|                     } | ||||
|                     None => { | ||||
|                         self.ws.send(msg!("JOIN_INVALID")).await.unwrap(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             _ => if let Some(channel) = &self.channel { | ||||
|                 // Forward message to the server
 | ||||
|                 channel.tx.send(msg).await.unwrap(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     async fn handle_server_msg(&mut self, _msg: Message) { | ||||
|         todo!(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn game_loop(_gc: Arc<Mutex<GameController>>) { | ||||
|     todo!(); | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| use std::{ | ||||
|     collections::HashMap, | ||||
|     sync::Arc, | ||||
| }; | ||||
| 
 | ||||
| use tokio::sync::{Mutex, mpsc}; | ||||
| 
 | ||||
| pub mod message; | ||||
| use message::{Message}; | ||||
| mod code_generator; | ||||
| use code_generator::CodeGenerator; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct GlobalState { | ||||
|     pub code_generator: Arc<Mutex<CodeGenerator>>, | ||||
|     pub rooms: Arc<Mutex<HashMap<String, Arc<Mutex<GameController>>>>>, | ||||
| } | ||||
| 
 | ||||
| pub struct Channel { | ||||
|     pub tx: mpsc::Sender<Message>, | ||||
|     pub rx: mpsc::Receiver<Message>, | ||||
| } | ||||
| 
 | ||||
| pub fn channel_pair() -> (Channel, Channel) { | ||||
|     let (atx, brx) = mpsc::channel(32); | ||||
|     let (btx, arx) = mpsc::channel(32); | ||||
|     ( | ||||
|         Channel { tx: atx, rx: arx }, | ||||
|         Channel { tx: btx, rx: brx }, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct GameController { | ||||
|     pub channels: Vec<Channel>, | ||||
| } | ||||
							
								
								
									
										122
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -1,23 +1,17 @@ | ||||
| use std::{ | ||||
|     sync::Arc, | ||||
|     io::Error as IoError, | ||||
|     collections::HashMap, | ||||
| }; | ||||
| 
 | ||||
| use tokio::{ | ||||
|     net::{TcpListener}, | ||||
|     sync::{mpsc, Mutex}, | ||||
| }; | ||||
| 
 | ||||
| use futures::{ | ||||
|     select, | ||||
|     FutureExt, | ||||
| }; | ||||
| use hexland_server::GlobalState; | ||||
| use hexland_server::message::MessageWebSocket; | ||||
| 
 | ||||
| mod message; | ||||
| use message::{Message, MessageWebSocket}; | ||||
| mod code_generator; | ||||
| use code_generator::CodeGenerator; | ||||
| mod client; | ||||
| use client::Client; | ||||
| 
 | ||||
| #[tokio::main] | ||||
| async fn main() -> Result<(), IoError> { | ||||
| @ -31,118 +25,14 @@ async fn main() -> Result<(), IoError> { | ||||
|     // Accept all incoming connections
 | ||||
|     while let Ok((stream, addr)) = listener.accept().await { | ||||
|         let global_state = Arc::clone(&global_state); | ||||
|         let mut local_state = LocalState::default(); | ||||
|         tokio::spawn(async move { | ||||
|             // Upgrade to a WS connection
 | ||||
|             let mut ws = MessageWebSocket(tokio_tungstenite::accept_async(stream) | ||||
|             let ws = MessageWebSocket(tokio_tungstenite::accept_async(stream) | ||||
|                                           .await | ||||
|                                           .expect("Could not establish connection")); | ||||
|             println!("Connected to {}", addr); | ||||
| 
 | ||||
|             loop { | ||||
|                 match &mut local_state.channel { | ||||
|                     Some(channel) => { | ||||
|                         select! { | ||||
|                             msg = channel.rx.recv().fuse() => | ||||
|                                 handle_server_msg(msg.unwrap(), &mut local_state, &mut ws).await, | ||||
|                             msg = ws.next().fuse() => | ||||
|                                 handle_client_msg(msg.unwrap(), &global_state, &mut local_state, &mut ws).await, | ||||
|                         }; | ||||
|                     } | ||||
|                     None => { | ||||
|                         let msg = ws.next().await; | ||||
|                         handle_client_msg(msg.unwrap(), &global_state, &mut local_state, &mut ws).await; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             Client::new(ws, global_state).run().await; | ||||
|         }); | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| async fn handle_client_msg( | ||||
|     msg: Message, | ||||
|     global_state: &GlobalState, | ||||
|     local_state: &mut LocalState, | ||||
|     ws: &mut MessageWebSocket | ||||
| ) { | ||||
|     match msg.command.as_str() { | ||||
|         "HOST" => { | ||||
|             let room_code = global_state.code_generator.lock().await.generate(); | ||||
|             let mut game_controller = GameController::default(); | ||||
| 
 | ||||
|             let [client_channel, server_channel] = channel_pair(); | ||||
|             local_state.channel = Some(client_channel); | ||||
|             game_controller.channels.push(server_channel); | ||||
| 
 | ||||
|             let game_controller = Arc::new(Mutex::new(game_controller)); | ||||
|             global_state.rooms.lock().await.insert(room_code.clone(), Arc::clone(&game_controller)); | ||||
|             tokio::spawn(async move {game_loop(game_controller)}); | ||||
|             ws.send(msg!("ROOM_CODE", room_code)).await.unwrap(); | ||||
|         } | ||||
|         "JOIN" => { | ||||
|             let room_code = &msg.args[0]; | ||||
|             let rooms = global_state.rooms.lock().await; | ||||
|             let room = rooms.get(room_code); | ||||
| 
 | ||||
|             match room { | ||||
|                 Some(room) => { | ||||
|                     let mut room = room.lock().await; | ||||
|                     let [client_channel, server_channel] = channel_pair(); | ||||
|                     local_state.channel = Some(client_channel); | ||||
|                     room.channels.push(server_channel); | ||||
|                     ws.send(msg!("JOIN_OK")).await.unwrap(); | ||||
|                 } | ||||
|                 None => { | ||||
|                     ws.send(msg!("JOIN_INVALID")).await.unwrap(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         _ => if let Some(channel) = &local_state.channel { | ||||
|             // Forward message to the server
 | ||||
|             channel.tx.send(msg).await; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| async fn handle_server_msg( | ||||
|     msg: Message, | ||||
|     local_state: &mut LocalState, | ||||
|     ws: &mut MessageWebSocket | ||||
| ) { | ||||
|     todo!(); | ||||
| } | ||||
| 
 | ||||
| fn game_loop(game_controller: Arc<Mutex<GameController>>) { | ||||
|     todo!(); | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| struct GlobalState { | ||||
|     code_generator: Arc<Mutex<CodeGenerator>>, | ||||
|     rooms: Arc<Mutex<HashMap<String, Arc<Mutex<GameController>>>>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| struct GameController { | ||||
|     channels: Vec<Channel>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| struct LocalState { | ||||
|     channel: Option<Channel>, | ||||
| } | ||||
| 
 | ||||
| struct Channel { | ||||
|     tx: mpsc::Sender<Message>, | ||||
|     rx: mpsc::Receiver<Message>, | ||||
| } | ||||
| 
 | ||||
| fn channel_pair() -> [Channel; 2] { | ||||
|     let (atx, brx) = mpsc::channel(32); | ||||
|     let (btx, arx) = mpsc::channel(32); | ||||
|     [ | ||||
|         Channel { tx: atx, rx: arx }, | ||||
|         Channel { tx: btx, rx: brx }, | ||||
|     ] | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user