From 9f405d9580e4b8e8c80779eb61266476fc6eb322 Mon Sep 17 00:00:00 2001 From: Adam <24621027+adoyle0@users.noreply.github.com> Date: Tue, 30 Apr 2024 02:28:43 -0400 Subject: [PATCH] ye --- src/CAHd_game.rs | 8 ++++---- src/api.rs | 37 +++++++++++++------------------------ src/main.rs | 42 ++++++++++++++++++++++++++++++++++++------ test_client.html | 43 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/CAHd_game.rs b/src/CAHd_game.rs index 180d254..e7eecc4 100644 --- a/src/CAHd_game.rs +++ b/src/CAHd_game.rs @@ -53,7 +53,7 @@ pub enum PlayerRole { #[derive(Debug)] pub struct CAHPlayer { /// Player's username - pub player_name: String, + pub name: String, /// This player's role pub role: PlayerRole, /// The player's hand @@ -72,7 +72,7 @@ pub struct CAHGame { /// Black draw pile pub black: Vec, /// White discard pile - pub jwhite_discard: Vec, + pub white_discard: Vec, /// Black discard pile pub black_discard: Vec, /// Indicates game active/game over @@ -189,14 +189,14 @@ impl CAHGame { pub fn create_player(&mut self, mut player: CAHPlayer) -> Result<()> { println!( "Creating player {} as {:?}", - &player.player_name, &player.role + &player.name, &player.role ); let mut hand_buf = vec![]; for _ in 0..10 { hand_buf.push(self.draw_one_white()?); } - println!("Dealing hand for {}", &player.player_name); + println!("Dealing hand for {}", &player.name); player.white.extend(hand_buf); self.players.push(player); diff --git a/src/api.rs b/src/api.rs index 4e5a82f..1ed7385 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,3 +1,4 @@ +use crate::AppState; use axum::{ extract::{ ws::{Message, WebSocket, WebSocketUpgrade}, @@ -6,19 +7,7 @@ use axum::{ response::IntoResponse, }; use futures::{sink::SinkExt, stream::StreamExt}; -use std::{ - collections::HashSet, - sync::{Arc, Mutex}, -}; -use tokio::sync::broadcast; - -// Our shared state -pub struct AppState { - // We require unique usernames. This tracks which usernames have been taken. - pub user_set: Mutex>, - // Channel used to send messages to all connected clients. - pub tx: broadcast::Sender, -} +use std::sync::Arc; pub async fn websocket_handler( ws: WebSocketUpgrade, @@ -35,18 +24,18 @@ pub async fn websocket(stream: WebSocket, state: Arc) { let (mut sender, mut receiver) = stream.split(); // Username gets set in the receive loop, if it's valid. - let mut username = String::new(); + let mut newplayer = String::new(); // Loop until a text message is found. while let Some(Ok(message)) = receiver.next().await { if let Message::Text(name) = message { - // If username that is sent by client is not taken, fill username string. - check_username(&state, &mut username, &name); + // If newplayer that is sent by client is not taken, fill newplayer string. + check_username(&state, &mut newplayer, &name); // If not empty we want to quit the loop else we want to quit function. - if !username.is_empty() { + if !newplayer.is_empty() { break; } else { - // Only send our client that username is taken. + // Only send our client that newplayer is taken. let _ = sender .send(Message::Text(String::from("Username already taken."))) .await; @@ -61,7 +50,7 @@ pub async fn websocket(stream: WebSocket, state: Arc) { let mut rx = state.tx.subscribe(); // Now send the "joined" message to all subscribers. - let msg = format!("{username} joined."); + let msg = format!("{newplayer} joined."); tracing::debug!("{msg}"); let _ = state.tx.send(msg); @@ -78,13 +67,13 @@ pub async fn websocket(stream: WebSocket, state: Arc) { // Clone things we want to pass (move) to the receiving task. let tx = state.tx.clone(); - let name = username.clone(); + let name = newplayer.clone(); // Spawn a task that takes messages from the websocket, prepends the user // name, and sends them to all broadcast subscribers. let mut recv_task = tokio::spawn(async move { while let Some(Ok(Message::Text(text))) = receiver.next().await { - // Add username before message. + // Add newplayer before message. let _ = tx.send(format!("{name}: {text}")); } }); @@ -96,12 +85,12 @@ pub async fn websocket(stream: WebSocket, state: Arc) { }; // Send "user left" message (similar to "joined" above). - let msg = format!("{username} left."); + let msg = format!("{newplayer} left."); tracing::debug!("{msg}"); let _ = state.tx.send(msg); - // Remove username from map so new clients can take it again. - state.user_set.lock().unwrap().remove(&username); + // Remove newplayer from map so new clients can take it again. + state.user_set.lock().unwrap().remove(&newplayer); } pub fn check_username(state: &AppState, string: &mut String, name: &str) { diff --git a/src/main.rs b/src/main.rs index a66c0e6..48bfab0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ fn load_json(path: &str) -> Result, Box> { Ok(jayson) } +#[allow(dead_code)] fn test() -> Result<(), Box> { // choose decks let cards_input_path: &str = "data/cah-cards-full.json"; @@ -32,14 +33,14 @@ fn test() -> Result<(), Box> { println!("{}", &chosen_packs.len()); let test_player0 = CAHPlayer { - player_name: "Adam".to_string(), + name: "Adam".to_string(), role: PlayerRole::Host, white: vec![], black: vec![], }; let test_player1 = CAHPlayer { - player_name: "Ferris".to_string(), + name: "Ferris".to_string(), role: PlayerRole::Player, white: vec![], black: vec![], @@ -71,8 +72,20 @@ fn test() -> Result<(), Box> { Ok(()) } +// Our shared state +pub struct AppState { + // We require unique usernames. This tracks which usernames have been taken. + user_set: Mutex>, + // Channel used to send messages to all connected clients. + tx: broadcast::Sender, + // Master card decks + all_cards: Mutex>, + // Games list + games: Mutex>, +} + #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box> { tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env() @@ -81,13 +94,28 @@ async fn main() { .with(tracing_subscriber::fmt::layer()) .init(); - let _ = test(); - // Set up application state for use with with_state(). let user_set = Mutex::new(HashSet::new()); let (tx, _rx) = broadcast::channel(100); - let app_state = Arc::new(AppState { user_set, tx }); + // choose decks + let cards_input_path: &str = "data/cah-cards-full.json"; + + // TODO: this should be a master card database and pointers + // to the cards should be passed to the game instead of actual cards + let all_cards = Mutex::new(load_json(cards_input_path)?); + let games = Mutex::new(vec![]); + let app_state = Arc::new(AppState { + user_set, + tx, + all_cards, + games, + }); + + tracing::debug!( + "Loaded {} Card packs!", + &app_state.all_cards.lock().unwrap().len() + ); let app = Router::new() .route("/", get(index)) @@ -97,6 +125,8 @@ async fn main() { let listener = tokio::net::TcpListener::bind("0.0.0.0:3030").await.unwrap(); tracing::debug!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); + + Ok(()) } // Include utf-8 file at **compile** time. diff --git a/test_client.html b/test_client.html index 96ec552..2687c35 100644 --- a/test_client.html +++ b/test_client.html @@ -11,7 +11,10 @@ div { margin-top: 1rem; } - + p { + margin: 0; + padding: 0; + } @@ -19,11 +22,19 @@

Disconnected...

-
-
- - -
+
+ +

Username

+

Game Name

+
+ +
+ + +
+ +
+
@@ -34,9 +45,23 @@