idk i'm tired
This commit is contained in:
parent
1e5ef3b801
commit
6bad0e36b2
4 changed files with 143 additions and 155 deletions
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
tx.send(msg).await.unwrap()
|
SendUserUpdate(message) => {
|
||||||
|
let msg = to_string::<UserUpdate>(&message).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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue