idk i'm tired

This commit is contained in:
Adam 2024-08-15 01:56:11 -04:00
parent 1e5ef3b801
commit 6bad0e36b2
4 changed files with 143 additions and 155 deletions

View file

@ -29,6 +29,7 @@ pub enum GameHandlerMessage {
/// Handles game stuff /// Handles game stuff
pub struct GameHandler { pub struct GameHandler {
/// Global state pointer
state: Arc<AppState>, state: Arc<AppState>,
} }

View file

@ -3,7 +3,7 @@
use crate::game_handler::*; use crate::game_handler::*;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use axum::extract::ws::Message; use axum::extract::ws::Message;
use game_handler::GameHandlerMessage; use game_handler::*;
use lib::*; use lib::*;
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -14,7 +14,7 @@ use std::{
}; };
use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender;
use tokio::sync::{broadcast, mpsc}; use tokio::sync::{broadcast, mpsc};
use user_handler::UserHandlerMessage; use user_handler::*;
use uuid::Uuid; use uuid::Uuid;
pub mod game_handler; pub mod game_handler;
pub mod message_handler; pub mod message_handler;

View file

@ -7,15 +7,19 @@ use serde_json::{from_str, to_string};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc; use std::sync::Arc;
/// Handles incoming messages
pub struct MessageHandler { pub struct MessageHandler {
/// Global state pointer
state: Arc<AppState>, state: Arc<AppState>,
} }
impl MessageHandler { impl MessageHandler {
/// Returns new MessageHandler object
pub fn new(state: Arc<AppState>) -> Self { pub fn new(state: Arc<AppState>) -> Self {
MessageHandler { state } MessageHandler { state }
} }
/// Handles incoming messages
pub async fn handle(&self, addr: SocketAddr, message: Message) { pub async fn handle(&self, addr: SocketAddr, message: Message) {
match message { match message {
Message::Text(text) => match text { Message::Text(text) => match text {
@ -28,7 +32,9 @@ impl MessageHandler {
.send(to_string::<ChatMessage>(&ChatMessage { text: msg }).unwrap()) .send(to_string::<ChatMessage>(&ChatMessage { text: msg }).unwrap())
.unwrap(); .unwrap();
} }
_user_log_in if let Ok(user_log_in) = from_str::<UserLogInRequest>(&text) => { _user_log_in_request
if let Ok(user_log_in) = from_str::<UserLogInRequest>(&text) =>
{
self.state self.state
.users_tx .users_tx
.send(UserHandlerMessage::UserLogIn { .send(UserHandlerMessage::UserLogIn {
@ -39,7 +45,7 @@ impl MessageHandler {
.unwrap(); .unwrap();
tracing::debug!("passed login to user handler"); tracing::debug!("passed login to user handler");
} }
_new_game if let Ok(new_game) = from_str::<NewGameRequest>(&text) => { _new_game_request if let Ok(new_game) = from_str::<NewGameRequest>(&text) => {
self.state self.state
.games_tx .games_tx
.send(GameHandlerMessage::NewGame { addr, new_game }) .send(GameHandlerMessage::NewGame { addr, new_game })
@ -50,21 +56,28 @@ impl MessageHandler {
_join_game_request if let Ok(join_request) = from_str::<GameJoinRequest>(&text) => { _join_game_request if let Ok(join_request) = from_str::<GameJoinRequest>(&text) => {
self.state self.state
.games_tx .games_tx
.send(GameHandlerMessage::JoinGame { addr, id: join_request.id }) .send(GameHandlerMessage::JoinGame {
addr,
id: join_request.id,
})
.await .await
.unwrap(); .unwrap();
} }
_ => tracing::debug!("Unhandled text from {}", addr), _ => tracing::debug!("Unhandled text from {}", addr),
}, },
Message::Binary(data) => tracing::debug!("{} sent binary: {:?}", addr, data), Message::Binary(data) => tracing::debug!("{} sent binary: {:?}", addr, data),
Message::Close(close_frame) => { Message::Close(close_frame) => {
self.handle_close(close_frame, addr); self.handle_close(close_frame, addr);
} }
Message::Pong(ping) => {
Message::Ping(ping) => {
tracing::debug!("Pong received with: {:?}", ping); tracing::debug!("Pong received with: {:?}", ping);
} }
Message::Ping(pong) => {
Message::Pong(pong) => {
tracing::debug!("Pong received with: {:?}", pong); tracing::debug!("Pong received with: {:?}", pong);
} }
} }
@ -72,48 +85,7 @@ impl MessageHandler {
/// This runs when a connection closes /// This runs when a connection closes
fn handle_close(&self, close_frame: Option<CloseFrame>, addr: SocketAddr) { fn handle_close(&self, close_frame: Option<CloseFrame>, addr: SocketAddr) {
if let Some(cf) = close_frame { let user_name = self
tracing::debug!(
"Close received from {0} with code: {1} and reason: {2}",
self.state
.online_users
.read()
.unwrap()
.get(&addr)
.unwrap()
.read()
.unwrap()
.name,
cf.code,
cf.reason
)
} else {
tracing::debug!("close received without close frame")
}
let msg = ChatMessage {
text: format!(
"{0} left.",
self.state
.online_users
.read()
.unwrap()
.get(&addr)
.unwrap()
.read()
.unwrap()
.name
),
};
tracing::debug!("{}", msg.text);
self.state
.broadcast_tx
.send(to_string::<ChatMessage>(&msg).unwrap())
.unwrap();
// Move user to offline
let name = self
.state .state
.online_users .online_users
.read() .read()
@ -125,16 +97,7 @@ impl MessageHandler {
.name .name
.clone(); .clone();
self.state.offline_users.write().unwrap().insert( // Send client updates
name.clone(),
self.state
.online_users
.write()
.unwrap()
.remove(&addr)
.unwrap(),
);
self.state self.state
.broadcast_tx .broadcast_tx
.send(meta_server_summary_update(&self.state)) .send(meta_server_summary_update(&self.state))
@ -143,5 +106,39 @@ impl MessageHandler {
.broadcast_tx .broadcast_tx
.send(meta_chat_update(&self.state)) .send(meta_chat_update(&self.state))
.unwrap(); .unwrap();
// Announce User left in chat
let msg = ChatMessage {
text: format!("{0} left.", &user_name),
};
tracing::debug!("{}", msg.text);
self.state
.broadcast_tx
.send(to_string::<ChatMessage>(&msg).unwrap())
.unwrap();
// Process close frame
if let Some(cf) = close_frame {
tracing::debug!(
"Close received from {0} with code: {1} and reason: {2}",
&user_name,
cf.code,
cf.reason
)
} else {
tracing::debug!("close received without close frame")
}
// Move user to offline
// This should probably happen first/immediately but moving down here avoids a clone
self.state.offline_users.write().unwrap().insert(
user_name,
self.state
.online_users
.write()
.unwrap()
.remove(&addr)
.unwrap(),
);
} }
} }

View file

@ -1,4 +1,5 @@
use crate::AppState; use crate::AppState;
use crate::SendUserMessage::*;
use crate::User; use crate::User;
use crate::UserHandlerMessage::*; use crate::UserHandlerMessage::*;
use lib::*; use lib::*;
@ -6,21 +7,41 @@ use serde_json::to_string;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
pub enum UserHandlerMessage { /// Handles users
NewUser { user: User, addr: SocketAddr },
UserLogIn { username: String, addr: SocketAddr },
DmUserAddr { addr: SocketAddr, message: String },
}
pub struct UserHandler { pub struct UserHandler {
/// Pointer to global state
state: Arc<AppState>, state: Arc<AppState>,
} }
/// For interacting with the user handler
pub enum UserHandlerMessage {
NewUser {
user: User,
addr: SocketAddr,
},
UserLogIn {
username: String,
addr: SocketAddr,
},
DmUserAddr {
addr: SocketAddr,
message: SendUserMessage,
},
}
/// Types of messages that can be sent to a user as a DM
pub enum SendUserMessage {
SendUserUpdate(UserUpdate),
SendChatMessage(ChatMessage),
}
impl UserHandler { impl UserHandler {
/// Returns new UserHandler
pub fn new(state: Arc<AppState>) -> Self { pub fn new(state: Arc<AppState>) -> Self {
UserHandler { state } UserHandler { state }
} }
/// Handles incoming messages
pub async fn handle(&self, message: UserHandlerMessage) { pub async fn handle(&self, message: UserHandlerMessage) {
match message { match message {
NewUser { user, addr } => { NewUser { user, addr } => {
@ -32,8 +53,8 @@ impl UserHandler {
} }
} }
async fn send_message_addr(&self, addr: SocketAddr, message: String) { /// Send message direct to a single user via addr
let msg = to_string::<ChatMessage>(&ChatMessage { text: message }).unwrap(); async fn send_message_addr(&self, addr: SocketAddr, message: SendUserMessage) {
let tx = self let tx = self
.state .state
.online_users .online_users
@ -45,14 +66,20 @@ impl UserHandler {
.unwrap() .unwrap()
.tx .tx
.clone(); .clone();
match message {
SendUserUpdate(message) => {
let msg = to_string::<UserUpdate>(&message).unwrap();
tx.send(msg).await.unwrap() tx.send(msg).await.unwrap()
} }
SendChatMessage(message) => {
let msg = to_string::<ChatMessage>(&message).unwrap();
tx.send(msg).await.unwrap()
}
}
}
/// Create, register, and hydrate new user
async fn set_up_new_user(&self, user: User, addr: SocketAddr) { async fn set_up_new_user(&self, user: User, addr: SocketAddr) {
//
// Create, Register, and Hydrate new user
//
let tx = user.tx.clone(); let tx = user.tx.clone();
let new_user = Arc::new(RwLock::new(user)); let new_user = Arc::new(RwLock::new(user));
@ -77,7 +104,6 @@ impl UserHandler {
tx.send(meta_games_browser_update(&self.state)) tx.send(meta_games_browser_update(&self.state))
.await .await
.unwrap(); .unwrap();
tx.send(meta_new_game_card_packs(&self.state)) tx.send(meta_new_game_card_packs(&self.state))
.await .await
.unwrap(); .unwrap();
@ -87,39 +113,21 @@ impl UserHandler {
let _ = &self let _ = &self
.state .state
.broadcast_tx .broadcast_tx
.send(meta_announce_user_join(&self.state, &addr)) .send(meta_announce_user_join(&self.state, &addr));
.unwrap();
let _ = &self let _ = &self
.state .state
.broadcast_tx .broadcast_tx
.send(meta_server_summary_update(&self.state)) .send(meta_server_summary_update(&self.state));
.unwrap(); let _ = &self.state.broadcast_tx.send(meta_chat_update(&self.state));
let _ = &self
.state
.broadcast_tx
.send(meta_chat_update(&self.state))
.unwrap();
// TODO: this races the broadcasts but if it's done last it'll probably show up last // TODO: this races the broadcasts but if it's done last it'll probably show up last...
tx.send(meta_motd()).await.unwrap(); tx.send(meta_motd()).await.unwrap();
} }
/// Handle user login
async fn login(&self, username: String, addr: SocketAddr) { async fn login(&self, username: String, addr: SocketAddr) {
// User's DM channel let broadcast_tx = self.state.broadcast_tx.clone();
let dm = self let new_name = username.clone();
.state
.online_users
.read()
.unwrap()
.get(&addr)
.unwrap()
.read()
.unwrap()
.tx
.clone();
let broadcast = self.state.broadcast_tx.clone();
let old_name = self let old_name = self
.state .state
.online_users .online_users
@ -132,8 +140,7 @@ impl UserHandler {
.name .name
.clone(); .clone();
let new_name = username.clone(); // Resume user's old session if they exist as offline
if self if self
.state .state
.offline_users .offline_users
@ -156,47 +163,47 @@ impl UserHandler {
) )
.unwrap(); .unwrap();
// Send welcome back messages
let msg = format! { let msg = format! {
"{0} changed name to {1}. Welcome back!", "{0} changed name to {1}. Welcome back!",
old_name, old_name,
new_name new_name
}; };
dm.send( tracing::debug!("{}", &msg);
serde_json::to_string(&ChatMessage { let _ = broadcast_tx.send(to_string(&ChatMessage { text: msg }).unwrap());
text: "Welcome back!".to_string(), }
}) // Check if name is taken by an online user
.unwrap(), else if self
)
.await
.unwrap();
tracing::debug!("{msg}");
} else if self
.state .state
.reserved_names .reserved_names
.read() .read()
.unwrap() .unwrap()
.contains(&new_name) .contains(&new_name)
{ {
tracing::debug!("name is taken"); self.send_message_addr(
dm.send( addr,
serde_json::to_string(&ChatMessage { SendChatMessage(ChatMessage {
text: "Name is taken".to_string(), text: "Name is taken".to_string(),
}) }),
.unwrap(),
) )
.await .await;
.unwrap();
tracing::debug!("{}", old_name.clone()); tracing::debug!("{}", old_name.clone());
dm.send( self.send_message_addr(
to_string::<UserUpdate>(&UserUpdate { addr,
SendUserUpdate(UserUpdate {
username: old_name.clone(), username: old_name.clone(),
}) }),
.unwrap(),
) )
.await .await;
.unwrap();
} else { } else {
// Reserve name
self.state
.reserved_names
.write()
.unwrap()
.insert(new_name.clone());
// Change user's name
self.state self.state
.online_users .online_users
.write() .write()
@ -207,48 +214,31 @@ impl UserHandler {
.unwrap() .unwrap()
.change_name(username); .change_name(username);
// send the user their new name
self.send_message_addr(
addr,
SendUserUpdate(UserUpdate {
username: new_name.clone(),
}),
)
.await;
// Send chat updates
let msg = format! { let msg = format! {
"{0} changed name to {1}.", "{0} changed name to {1}.",
old_name, old_name,
new_name new_name
}; };
broadcast_tx
// Reserve name
self.state
.reserved_names
.write()
.unwrap()
.insert(new_name.clone());
tracing::debug!("{msg}");
broadcast
.send(to_string::<ChatMessage>(&ChatMessage { text: msg }).unwrap()) .send(to_string::<ChatMessage>(&ChatMessage { text: msg }).unwrap())
.unwrap(); .unwrap();
tracing::debug!("Name {} reserved.", &new_name);
// send the user their new name
dm.send(
to_string::<UserUpdate>(&UserUpdate {
username: new_name.clone(),
})
.unwrap(),
)
.await
.unwrap();
} }
tracing::debug!( // Send client updates
"Online Users: {} Offline Users: {}", broadcast_tx
self.state.online_users.read().unwrap().len(),
self.state.offline_users.read().unwrap().len()
);
broadcast
.send(meta_games_browser_update(&self.state)) .send(meta_games_browser_update(&self.state))
.unwrap(); .unwrap();
broadcast.send(meta_chat_update(&self.state)).unwrap(); broadcast_tx.send(meta_chat_update(&self.state)).unwrap();
tracing::debug!(" HI! login received {} {} {}", addr, new_name, old_name)
} }
} }