diff --git a/server/src/game_handler.rs b/server/src/game_handler.rs index 2205f61..48ef034 100644 --- a/server/src/game_handler.rs +++ b/server/src/game_handler.rs @@ -1,15 +1,242 @@ use crate::user_handler::*; use crate::AppState; -use crate::Game; -use crate::NewGameManifest; -use crate::NewGameRequest; use crate::User; +use anyhow::Result; use lib::*; -use std::net::SocketAddr; -use std::sync::{Arc, RwLock}; +use rand::prelude::IteratorRandom; +use rand::thread_rng; +use serde::Deserialize; +use std::{ + collections::HashMap, + net::SocketAddr, + sync::{Arc, RwLock}, +}; +use uuid::Uuid; // This file is disgusting, don't look at it +/// Card Set +#[derive(Debug)] +pub struct CardSet { + pub white: Option>, + pub black: Option>, +} + +/// Card Packs +#[derive(Debug)] +pub struct CardPacks { + pub official: HashMap, + pub unofficial: HashMap, +} + +/// A white card +#[derive(Debug, Deserialize)] +pub struct CardWhite { + /// Card text + pub text: String, + /// ID of the pack it came from + pub pack: u8, +} + +/// A black card +#[derive(Debug, Deserialize)] +pub struct CardBlack { + /// Card text + pub text: String, + /// Amount of cards to submit for judging + pub pick: u8, + /// ID of the pack it came from + pub pack: u8, +} + +/// A card pack +#[derive(Debug, Deserialize)] +pub struct CardPack { + /// Name of the pack + pub name: String, + /// Whether or not this is an official card pack + pub official: bool, + /// White card data + pub white: Option>, + /// Black card data + pub black: Option>, +} + +/// New game request structure +#[derive(Debug)] +pub struct NewGameManifest { + /// Game name + pub name: String, + /// Game host + pub host: Arc>, + /// Selected game packs + pub packs: Vec, +} + +/// A struct that represents a player +#[derive(Debug)] +pub struct Player { + /// Player's user's uuid + pub user_uuid: Uuid, + /// The player's hand + pub white: Vec, + /// The player's wins + pub black: Vec, +} + +/// The game master +#[derive(Debug)] +pub struct Game { + /// The name of the game + pub name: String, + /// The host user of the game + pub host: Arc>, + /// White draw pile + pub white: Vec, + /// Black draw pile + pub black: Vec, + /// White discard pile + pub white_discard: Vec, + /// Black discard pile + pub black_discard: Vec, + /// List of current players + pub players: HashMap, + // /// Reference to current card czar + // czar: &Player, + /// Black card for the current round + pub current_black: Option, +} + +impl Game { + /// Build game decks from input data for game start. + /// This should only run once and at startup. + fn build_decks(&mut self, selected_packs: Vec) -> Result<()> { + // for pack in selected_packs { + // for pack in card_packs { + // if let Some(white) = pack.white { + // self.white.extend(white) + // } + // if let Some(black) = pack.black { + // self.black.extend(black) + // } + // } + // } + + Ok(()) + } + + pub fn new(request: NewGameManifest) -> Result { + let mut game = Game { + name: request.host.read().unwrap().name.clone(), + host: request.host.clone(), + white: vec![], + black: vec![], + white_discard: vec![], + black_discard: vec![], + players: HashMap::new(), + current_black: Option::None, + }; + tracing::debug!( + "Creating game {} with {} as host", + &request.name, + request.host.read().unwrap().name + ); + game.name = request.name; + game.host = request.host.clone(); + + game.build_decks(request.packs)?; + game.create_player(request.host)?; + game.deal_black()?; + + Ok(game) + } + + // pub fn join(request:GameJoinRequest) + + /// Log counts of current drawable cards + /// For testing + pub fn deck_counts(&self) { + tracing::debug!( + "Deck Counts:\n {} White cards\n {} Black cards", + self.white.len(), + self.black.len() + ); + } + + /// Draw one white card at random from play deck. + fn draw_one_white(&mut self) -> Result { + let deck = &mut self.white; + + // this feels sloppy + if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { + Ok(deck.swap_remove(index)) + } else { + Ok(CardWhite { + text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), + pack: 0, + }) + } + } + + /// Draw one black card at random from play deck. + fn draw_one_black(&mut self) -> Result { + let deck = &mut self.black; + + // this feels sloppy + if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { + Ok(deck.swap_remove(index)) + } else { + Ok(CardBlack { + text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), + pick: 0, + pack: 0, + }) + } + } + + /// Deal a black card and use it for the current round + fn deal_black(&mut self) -> Result<()> { + self.current_black = Some(self.draw_one_black()?); + + Ok(()) + } + + /// Create a new player and add them to the game. + pub fn create_player(&mut self, user: Arc>) -> Result<()> { + let mut new_player = Player { + user_uuid: user.read().unwrap().uuid.clone(), + white: vec![], + black: vec![], + }; + + let new_player_name = user.read().unwrap().name.clone(); + tracing::debug!("Creating player for {}", &new_player_name); + + let mut hand_buf = vec![]; + for _ in 0..10 { + hand_buf.push(self.draw_one_white()?); + } + tracing::debug!("Dealing hand to {}", &new_player_name); + + new_player.white.extend(hand_buf); + + self.players + .insert(user.read().unwrap().uuid.clone(), new_player); + + Ok(()) + } + + pub fn game_start(&mut self) -> Result<()> { + if let Some(black) = &self.current_black { + tracing::debug!("{}", black.text); + } else { + tracing::debug!("YOU DONE FUCKED UP (no current black card)"); + } + + Ok(()) + } +} + pub enum GameHandlerMessage { NewGame { addr: SocketAddr, @@ -57,8 +284,8 @@ impl GameHandler { .get(&addr) .unwrap() .clone(), + packs: new_game.packs, }; - tracing::debug!("Game Packs {:?}", new_game.packs); // create game if let Ok(new_game_object) = Game::new(manifest) { @@ -74,15 +301,11 @@ impl GameHandler { .tx .clone(); - tracing::debug!("{:#?}", &new_game_object); - let mut black_text = "Error".to_string(); if let Some(ref current_black) = new_game_object.current_black { black_text = current_black.text.to_owned() } - tracing::debug!("{:#?}", &new_game_object.white); - let meta = GameMeta { name: new_game_object.name.clone(), host: new_game_object.host.read().unwrap().name.clone(), @@ -114,7 +337,6 @@ impl GameHandler { .collect(), }; - tracing::debug!("{:#?}", &meta); tx.send(serde_json::to_string(&meta).unwrap()) .await .unwrap(); diff --git a/server/src/lib.rs b/server/src/lib.rs index c9b6221..ac57564 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,12 +1,10 @@ #![feature(if_let_guard)] +use crate::game_handler::*; use anyhow::{Context, Result}; use axum::extract::ws::Message; use game_handler::GameHandlerMessage; use lib::*; -use rand::prelude::IteratorRandom; -use rand::thread_rng; -use serde::Deserialize; use std::{ collections::{HashMap, HashSet}, fs::{read_to_string, File}, @@ -46,230 +44,6 @@ impl User { } } -/// Card Set -#[derive(Debug)] -pub struct CardSet { - pub white: Option>, - pub black: Option>, -} - -/// Card Packs -#[derive(Debug)] -pub struct CardPacks { - pub official: HashMap, - pub unofficial: HashMap, -} - -/// A white card -#[derive(Debug, Deserialize)] -pub struct CardWhite { - /// Card text - pub text: String, - /// ID of the pack it came from - pub pack: u8, -} - -/// A black card -#[derive(Debug, Deserialize)] -pub struct CardBlack { - /// Card text - pub text: String, - /// Amount of cards to submit for judging - pub pick: u8, - /// ID of the pack it came from - pub pack: u8, -} - -/// A card pack -#[derive(Debug, Deserialize)] -pub struct CardPack { - /// Name of the pack - pub name: String, - /// Whether or not this is an official card pack - pub official: bool, - /// White card data - pub white: Option>, - /// Black card data - pub black: Option>, -} - -/// New game request structure -#[derive(Debug)] -pub struct NewGameManifest { - /// Game name - pub name: String, - /// Game host - pub host: Arc>, -} - -/// A struct that represents a player -#[derive(Debug)] -pub struct Player { - /// Player's user's uuid - pub user_uuid: Uuid, - /// The player's hand - pub white: Vec, - /// The player's wins - pub black: Vec, -} - -/// The game master -#[derive(Debug)] -pub struct Game { - /// The name of the game - pub name: String, - /// The host user of the game - pub host: Arc>, - /// White draw pile - pub white: Vec, - /// Black draw pile - pub black: Vec, - /// White discard pile - pub white_discard: Vec, - /// Black discard pile - pub black_discard: Vec, - /// Indicates game active/game over - pub game_active: bool, - /// List of current players - pub players: HashMap, - // /// Reference to current card czar - // czar: &Player, - /// Black card for the current round - pub current_black: Option, -} - -impl Game { - /// Build game decks from input data for game start. - /// This should only run once and at startup. - fn _build_decks(&mut self, cards_json: Vec) -> Result<()> { - for pack in cards_json { - if let Some(white) = pack.white { - self.white.extend(white) - } - if let Some(black) = pack.black { - self.black.extend(black) - } - } - - Ok(()) - } - - pub fn new(request: NewGameManifest) -> Result { - let mut game = Game { - name: request.host.read().unwrap().name.clone(), - host: request.host.clone(), - white: vec![], - black: vec![], - white_discard: vec![], - black_discard: vec![], - game_active: false, - players: HashMap::new(), - current_black: Option::None, - }; - tracing::debug!( - "Creating game {} with {} as host", - &request.name, - request.host.read().unwrap().name - ); - game.name = request.name; - game.host = request.host.clone(); - - // game.build_decks(request.packs)?; - game.create_player(request.host)?; - game.deal_black()?; - - Ok(game) - } - - // pub fn join(request:GameJoinRequest) - - /// Log counts of current drawable cards - /// For testing - pub fn deck_counts(&self) { - tracing::debug!( - "Deck Counts:\n {} White cards\n {} Black cards", - self.white.len(), - self.black.len() - ); - } - - /// Draw one white card at random from play deck. - fn draw_one_white(&mut self) -> Result { - let deck = &mut self.white; - - // this feels sloppy - if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { - Ok(deck.swap_remove(index)) - } else { - Ok(CardWhite { - text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), - pack: 0, - }) - } - } - - /// Draw one black card at random from play deck. - fn draw_one_black(&mut self) -> Result { - let deck = &mut self.black; - - // this feels sloppy - if let Some(index) = (0..deck.len()).choose(&mut thread_rng()) { - Ok(deck.swap_remove(index)) - } else { - Ok(CardBlack { - text: "Error.\n\nbtw if you see this tell me I'm lazy :)".to_string(), - pick: 0, - pack: 0, - }) - } - } - - /// Deal a black card and use it for the current round - fn deal_black(&mut self) -> Result<()> { - self.current_black = Some(self.draw_one_black()?); - - Ok(()) - } - - /// Create a new player and add them to the game. - pub fn create_player(&mut self, user: Arc>) -> Result<()> { - let mut new_player = Player { - user_uuid: user.read().unwrap().uuid.clone(), - white: vec![], - black: vec![], - }; - - let new_player_name = user.read().unwrap().name.clone(); - tracing::debug!("Creating player for {}", &new_player_name); - - let mut hand_buf = vec![]; - for _ in 0..10 { - hand_buf.push(self.draw_one_white()?); - } - tracing::debug!("Dealing hand to {}", &new_player_name); - - new_player.white.extend(hand_buf); - - self.players - .insert(user.read().unwrap().uuid.clone(), new_player); - - Ok(()) - } - - pub fn game_start(&mut self) -> Result<()> { - self.game_active = true; - tracing::debug!("Game Active!"); - - if let Some(black) = &self.current_black { - tracing::debug!("{}", black.text); - } else { - tracing::debug!("YOU DONE FUCKED UP (no current black card)"); - } - - Ok(()) - } -} - /// Parse json for card data pub fn load_cards_from_json(path: &str) -> Result<(CardPacks, CardPacksMeta)> { let data: String =