more cleanup

This commit is contained in:
Adam 2024-11-21 13:56:03 -05:00
parent d0ac4bb93b
commit 67be24707d
5 changed files with 97 additions and 61 deletions

View file

@ -4,12 +4,12 @@ use crate::AppState;
use crate::DmUserMethod::*;
use crate::GameHandlerMessage::*;
use crate::SendUserMessage::*;
use crate::Sender;
use crate::UserHandlerMessage::*;
use axum::extract::ws::Message;
use lib::*;
use serde_json::to_string;
use std::{collections::HashMap, net::SocketAddr, sync::Arc};
use tokio::sync::mpsc::Sender;
/// For interacting with the game handler
pub enum GameHandlerMessage {

View file

@ -5,8 +5,7 @@ use crate::UserHandlerMessage::*;
use axum::extract::ws::{CloseFrame, Message};
use lib::*;
use serde_json::{from_str, to_string};
use std::net::SocketAddr;
use std::sync::Arc;
use std::{net::SocketAddr, sync::Arc};
/// Handles incoming messages
pub struct IncomingMessageHandler {

View file

@ -1,11 +1,9 @@
#![feature(if_let_guard)]
use crate::game_handler::*;
use anyhow::{Context, Result};
use axum::extract::ws::Message;
use lib::*;
use std::{
collections::{HashMap, HashSet},
collections::HashMap,
net::SocketAddr,
sync::{Arc, RwLock},
};
@ -17,6 +15,7 @@ pub mod card_loader;
pub mod game;
pub mod game_handler;
pub mod incoming_message_handler;
pub mod name_generator;
pub mod user_handler;
pub mod websocket;

View file

@ -0,0 +1,54 @@
use anyhow::{Context, Result};
use rand::prelude::SliceRandom;
use std::{
collections::HashSet,
fs::File,
io::{BufRead, BufReader},
};
pub struct NameGenerator {
first_names: Vec<String>,
last_names: Vec<String>,
}
/// Parse name list
pub fn load_names(path: &str) -> Result<Vec<String>> {
let f = File::open(path).with_context(|| format!("Invalid names path: \"{}\"", path))?;
let f = BufReader::new(f);
let mut buf = vec![];
for line in f.lines() {
buf.push(line?)
}
Ok(buf)
}
impl NameGenerator {
pub fn new() -> Self {
NameGenerator {
first_names: load_names("data/first.txt").unwrap(),
last_names: load_names("data/last.txt").unwrap(),
}
}
pub fn generate(&mut self, reserved_names: &HashSet<String>) -> String {
// Roll for username and re-roll if taken
let mut name;
loop {
name = format!(
"{} {}",
self.first_names.choose(&mut rand::thread_rng()).unwrap(),
self.last_names.choose(&mut rand::thread_rng()).unwrap(),
);
if !reserved_names.contains(&name) {
break;
}
}
name
}
}

View file

@ -1,41 +1,28 @@
use crate::name_generator::*;
use crate::AppState;
use crate::DmUserMethod::*;
use crate::GameHandlerMessage;
use crate::SendUserMessage::*;
use crate::User;
use crate::UserHandlerMessage::*;
use crate::*;
use rand::prelude::SliceRandom;
use axum::extract::ws::Message;
use lib::*;
use serde_json::to_string;
use std::{
fs::File,
io::{BufRead, BufReader},
collections::{HashMap, HashSet},
net::SocketAddr,
sync::{Arc, RwLock},
};
use tokio::sync::mpsc::Sender;
// TODO: clean up all this tx/msg mess
/// Parse name list
pub fn load_names(path: &str) -> Result<Vec<String>> {
let f = File::open(path).with_context(|| format!("Invalid names path: \"{}\"", path))?;
let f = BufReader::new(f);
let mut buf = vec![];
for line in f.lines() {
buf.push(line?)
}
Ok(buf)
}
/// Handles users
pub struct UserHandler {
/// Pointer to global state
state: Arc<AppState>,
users_by_id: HashMap<String, Arc<RwLock<User>>>,
first_names: Vec<String>,
last_names: Vec<String>,
name_generator: NameGenerator,
reserved_names: HashSet<String>,
}
@ -66,9 +53,8 @@ impl UserHandler {
UserHandler {
state,
users_by_id: HashMap::<String, Arc<RwLock<User>>>::new(),
first_names: load_names("data/first.txt").unwrap(),
last_names: load_names("data/last.txt").unwrap(),
reserved_names: HashSet::<String>::new(),
name_generator: NameGenerator::new(),
}
}
@ -143,41 +129,26 @@ impl UserHandler {
/// Create, register, and hydrate new user
async fn set_up_new_user(&mut self, dm_tx: Sender<Message>, addr: SocketAddr) {
// Roll for username and re-roll if taken
let mut name;
loop {
name = format!(
"{} {}",
self.first_names.choose(&mut rand::thread_rng()).unwrap(),
self.last_names.choose(&mut rand::thread_rng()).unwrap(),
);
if !self.reserved_names.contains(&name) {
break;
}
}
let name = self.name_generator.generate(&self.reserved_names);
let new_user = Arc::new(RwLock::new(User::new(name, dm_tx.clone())));
// Notify client of new username
let tx = dm_tx.clone();
let msg = user_client_self_update(&new_user);
tokio::spawn(async move { tx.send(msg).await });
// Register uuid
self.users_by_id
.insert(new_user.read().unwrap().uuid.clone(), new_user.clone());
// Register online using `addr` as key until something longer lived exists
self.state
.online_users
.write()
.unwrap()
.insert(addr, new_user.clone());
self.set_user_online(addr, new_user.clone());
// Hydrate client
if !dm_tx.is_closed() {
// Notify client of username
if let Err(e) = dm_tx.send(user_client_self_update(&new_user)).await {
tracing::error!("Error sending client update {}", e)
}
// Send game update
// TODO: send single update instad of broadcasting to all users
if let Err(e) = self
.state
.tx_game_handler
@ -187,6 +158,7 @@ impl UserHandler {
tracing::error!("Error contacing game handler {}", e)
}
// Send card packs for new game form
if let Err(e) = self
.state
.tx_game_handler
@ -195,6 +167,8 @@ impl UserHandler {
{
tracing::error!("Error contacing game handler {}", e)
}
} else {
self.user_cleanup(addr);
}
// Broadcast new user's existence
@ -398,15 +372,7 @@ impl UserHandler {
});
// Move user to offline
self.state.offline_users.write().unwrap().insert(
user_name,
self.state
.online_users
.write()
.unwrap()
.remove(&addr)
.unwrap(),
);
self.set_user_offline(user_name, &addr);
self.broadcast_user_count();
@ -418,6 +384,24 @@ impl UserHandler {
}
});
}
/// Set user status to online
fn set_user_online(&self, addr: SocketAddr, user: Arc<RwLock<User>>) {
self.state.online_users.write().unwrap().insert(addr, user);
}
/// Set user status to offline
fn set_user_offline(&self, user_name: String, addr: &SocketAddr) {
self.state.offline_users.write().unwrap().insert(
user_name,
self.state
.online_users
.write()
.unwrap()
.remove(addr)
.unwrap(),
);
}
}
/// Generate message to notify client of user changes