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