Quick refactor, project structure

This commit is contained in:
Dane Johnson 2022-10-12 10:57:57 -05:00
parent ab25fa0267
commit ab3c28ff37
3 changed files with 140 additions and 116 deletions

98
src/client.rs Normal file
View 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
View 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>,
}

View File

@ -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 },
]
}