let game handler own the games
This commit is contained in:
parent
3fb3d2f521
commit
c8375d1b15
4 changed files with 60 additions and 84 deletions
|
@ -142,7 +142,7 @@ impl Game {
|
|||
}
|
||||
|
||||
/// Judge Game
|
||||
pub fn judge_round(&mut self, request: JudgeDecisionRequest, player_user_id: String) {
|
||||
pub fn judge_round(&mut self, request: &JudgeDecisionRequest, player_user_id: String) {
|
||||
// Check if player is czar
|
||||
if self.czar.read().unwrap().uuid.to_string() == player_user_id {
|
||||
if let Some(winner_id) = self.judge_pile_meta.get(&request.winning_cards) {
|
||||
|
@ -158,7 +158,7 @@ impl Game {
|
|||
/// Process player move
|
||||
pub fn player_move(
|
||||
&mut self,
|
||||
request: PlayerMoveRequest,
|
||||
request: &PlayerMoveRequest,
|
||||
player_user_id: String,
|
||||
) -> Result<Option<(JudgeRound, String)>, String> {
|
||||
if self.czar.read().unwrap().uuid == player_user_id {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::game::*;
|
||||
|
||||
use crate::AppState;
|
||||
use crate::DmUserMethod::*;
|
||||
use crate::GameHandlerMessage::*;
|
||||
|
@ -6,10 +7,8 @@ use crate::SendUserMessage::*;
|
|||
use crate::UserHandlerMessage::*;
|
||||
use lib::*;
|
||||
use serde_json::to_string;
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
/// For interacting with the game handler
|
||||
#[derive(Debug)]
|
||||
|
@ -28,20 +27,22 @@ pub enum GameHandlerMessage {
|
|||
pub struct GameHandler {
|
||||
/// Global state pointer
|
||||
state: Arc<AppState>,
|
||||
games: HashMap<String, Game>,
|
||||
}
|
||||
|
||||
impl GameHandler {
|
||||
/// Returns a new game handler
|
||||
pub fn new(state: Arc<AppState>) -> Self {
|
||||
GameHandler { state }
|
||||
let games = HashMap::new();
|
||||
GameHandler { state, games }
|
||||
}
|
||||
|
||||
/// Handles incoming messages
|
||||
pub async fn handle(&self, message: GameHandlerMessage) {
|
||||
pub async fn handle(&mut self, message: GameHandlerMessage) {
|
||||
match message {
|
||||
NewGame(request, addr) => self.create_new_game(request, addr).await,
|
||||
JoinGame(request, addr) => self.join_game(request, addr).await,
|
||||
MoveRequest(request, addr) => self.handle_player_move(request, addr).await,
|
||||
MoveRequest(request, addr) => self.handle_player_move(request, addr),
|
||||
JudgeDecision(request, addr) => self.handle_judging(request, addr).await,
|
||||
DeleteGame(request) => self.delete_game(request).await,
|
||||
SendGameStateUpdate(game_ids) => self.send_game_state_update_all(game_ids),
|
||||
|
@ -51,16 +52,9 @@ impl GameHandler {
|
|||
}
|
||||
|
||||
/// Delete game
|
||||
async fn delete_game(&self, request: GameDeleteRequest) {
|
||||
async fn delete_game(&mut self, request: GameDeleteRequest) {
|
||||
// TODO: add auth lol
|
||||
if self
|
||||
.state
|
||||
.games
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&request.delete_game_id)
|
||||
.is_some()
|
||||
{
|
||||
if self.games.remove(&request.delete_game_id).is_some() {
|
||||
self.broadcast_game_browser_update();
|
||||
} else {
|
||||
tracing::error!("User tried to delete a nonexistent game!");
|
||||
|
@ -68,17 +62,14 @@ impl GameHandler {
|
|||
}
|
||||
|
||||
/// Process judging
|
||||
async fn handle_judging(&self, request: JudgeDecisionRequest, addr: SocketAddr) {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&request.game_id) {
|
||||
async fn handle_judging(&mut self, request: JudgeDecisionRequest, addr: SocketAddr) {
|
||||
if let Some(this_game) = self.games.get_mut(&request.game_id) {
|
||||
if let Some(player_user) = self.state.online_users.read().unwrap().get(&addr) {
|
||||
let player_user_id = player_user.read().unwrap().uuid.to_string();
|
||||
let game_id = request.game_id.to_string();
|
||||
|
||||
// Send to game
|
||||
this_game
|
||||
.write()
|
||||
.unwrap()
|
||||
.judge_round(request.clone(), player_user_id);
|
||||
this_game.judge_round(&request, player_user_id);
|
||||
|
||||
self.send_game_state_update_all(vec![game_id.clone()]);
|
||||
self.send_game_meta_update(vec![game_id]);
|
||||
|
@ -95,44 +86,38 @@ impl GameHandler {
|
|||
}
|
||||
|
||||
/// Process player move request
|
||||
async fn handle_player_move(&self, request: PlayerMoveRequest, addr: SocketAddr) {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&request.game_id) {
|
||||
fn handle_player_move(&mut self, request: PlayerMoveRequest, addr: SocketAddr) {
|
||||
if let Some(this_game) = self.games.get_mut(&request.game_id) {
|
||||
if let Some(player_user) = self.state.online_users.read().unwrap().get(&addr) {
|
||||
let player_user_id = player_user.read().unwrap().uuid.to_string();
|
||||
|
||||
// Do the stuff
|
||||
match this_game
|
||||
.write()
|
||||
.unwrap()
|
||||
.player_move(request.clone(), player_user_id)
|
||||
{
|
||||
match this_game.player_move(&request, player_user_id) {
|
||||
Err(err) => {
|
||||
let message = ChatMessage { text: err };
|
||||
let tx = self.state.users_tx.clone();
|
||||
let users_tx = self.state.users_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) =
|
||||
tx.send(DmUser(SendChatMessage(message), Addr(addr))).await
|
||||
if let Err(e) = users_tx
|
||||
.send(DmUser(SendChatMessage(message), Addr(addr)))
|
||||
.await
|
||||
{
|
||||
tracing::error!("Could not send message: {}", e);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
Ok(None) => {
|
||||
tokio::spawn(
|
||||
async move { tracing::debug!("TODO: whatever i'm supposed to do") },
|
||||
)
|
||||
tracing::debug!("TODO: whatever i'm supposed to do")
|
||||
}
|
||||
Ok(Some((judge_round, czar_id))) => {
|
||||
let tx = self.state.users_tx.clone();
|
||||
|
||||
let users_tx = self.state.users_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = tx
|
||||
if let Err(e) = users_tx
|
||||
.send(DmUser(SendJudgeRound(judge_round), Id(czar_id)))
|
||||
.await
|
||||
{
|
||||
tracing::error!("Could not send message: {}", e);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
@ -176,8 +161,8 @@ impl GameHandler {
|
|||
}
|
||||
|
||||
/// Puts a user in a game
|
||||
async fn join_game(&self, game_id: String, addr: SocketAddr) {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&game_id) {
|
||||
async fn join_game(&mut self, game_id: String, addr: SocketAddr) {
|
||||
if self.games.contains_key(&game_id) {
|
||||
if let Some(this_user) = self.state.online_users.read().unwrap().get(&addr) {
|
||||
let this_user_id = this_user.read().unwrap().uuid.clone();
|
||||
|
||||
|
@ -185,7 +170,10 @@ impl GameHandler {
|
|||
self.register_user_in_game(game_id.clone(), this_user_id.clone());
|
||||
|
||||
// Create player
|
||||
this_game.write().unwrap().create_player(this_user.clone());
|
||||
self.games
|
||||
.get_mut(&game_id)
|
||||
.unwrap()
|
||||
.create_player(this_user.clone());
|
||||
|
||||
// Send cards
|
||||
self.send_game_state_update_single(this_user_id, game_id.clone())
|
||||
|
@ -208,18 +196,14 @@ impl GameHandler {
|
|||
/// Send game meta update for all players of a game
|
||||
fn send_game_meta_update(&self, game_ids: Vec<String>) {
|
||||
for game_id in game_ids {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&game_id) {
|
||||
if let Some(this_game) = self.games.get(&game_id) {
|
||||
let players = this_game
|
||||
.read()
|
||||
.unwrap()
|
||||
.players
|
||||
.values()
|
||||
.map(|player| GamePlayerMeta {
|
||||
name: player.user.read().unwrap().name.clone(),
|
||||
score: player.black.len(),
|
||||
submitted: this_game
|
||||
.read()
|
||||
.unwrap()
|
||||
.judge_pile_meta
|
||||
.values()
|
||||
.collect::<Vec<&String>>()
|
||||
|
@ -227,18 +211,18 @@ impl GameHandler {
|
|||
})
|
||||
.collect::<Vec<GamePlayerMeta>>();
|
||||
|
||||
for player in this_game.read().unwrap().players.values() {
|
||||
for player in this_game.players.values() {
|
||||
// Create update for user's game view
|
||||
let meta = GameMeta {
|
||||
uuid: game_id.clone(),
|
||||
name: this_game.read().unwrap().name.clone(),
|
||||
host: this_game.read().unwrap().host.read().unwrap().name.clone(),
|
||||
name: this_game.name.clone(),
|
||||
host: this_game.host.read().unwrap().name.clone(),
|
||||
players: players.clone(),
|
||||
czar: this_game.read().unwrap().czar.read().unwrap().name.clone(),
|
||||
packs: this_game.read().unwrap().packs.clone(),
|
||||
white_count: this_game.read().unwrap().white.len(),
|
||||
black_count: this_game.read().unwrap().black.len(),
|
||||
white_discard_count: this_game.read().unwrap().white_discard.len(),
|
||||
czar: this_game.czar.read().unwrap().name.clone(),
|
||||
packs: this_game.packs.clone(),
|
||||
white_count: this_game.white.len(),
|
||||
black_count: this_game.black.len(),
|
||||
white_discard_count: this_game.white_discard.len(),
|
||||
};
|
||||
|
||||
// Send user's update
|
||||
|
@ -263,13 +247,13 @@ impl GameHandler {
|
|||
/// Send game state update for all players of a game
|
||||
fn send_game_state_update_all(&self, game_ids: Vec<String>) {
|
||||
for game_id in game_ids {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&game_id) {
|
||||
for player in this_game.read().unwrap().players.values() {
|
||||
if let Some(this_game) = self.games.get(&game_id) {
|
||||
for player in this_game.players.values() {
|
||||
// Create update for user's game view
|
||||
let meta = GameStateMeta {
|
||||
black: (
|
||||
this_game.read().unwrap().current_black.text.clone(),
|
||||
this_game.read().unwrap().current_black.pick,
|
||||
this_game.current_black.text.clone(),
|
||||
this_game.current_black.pick,
|
||||
),
|
||||
white: player
|
||||
.white
|
||||
|
@ -294,13 +278,13 @@ impl GameHandler {
|
|||
|
||||
/// Send game state update for a single user
|
||||
fn send_game_state_update_single(&self, user_id: String, game_id: String) {
|
||||
if let Some(this_game) = self.state.games.read().unwrap().get(&game_id) {
|
||||
if let Some(player) = this_game.read().unwrap().players.get(&user_id) {
|
||||
if let Some(this_game) = self.games.get(&game_id) {
|
||||
if let Some(player) = this_game.players.get(&user_id) {
|
||||
// Create update for user's game view
|
||||
let meta = GameStateMeta {
|
||||
black: (
|
||||
this_game.read().unwrap().current_black.text.clone(),
|
||||
this_game.read().unwrap().current_black.pick,
|
||||
this_game.current_black.text.clone(),
|
||||
this_game.current_black.pick,
|
||||
),
|
||||
white: player
|
||||
.white
|
||||
|
@ -325,7 +309,7 @@ impl GameHandler {
|
|||
}
|
||||
|
||||
/// Creates a new game
|
||||
async fn create_new_game(&self, new_game: NewGameRequest, addr: SocketAddr) {
|
||||
async fn create_new_game(&mut self, new_game: NewGameRequest, addr: SocketAddr) {
|
||||
if new_game.packs.is_empty() {
|
||||
tracing::error!("New game cards are empty!");
|
||||
return;
|
||||
|
@ -364,10 +348,8 @@ impl GameHandler {
|
|||
let game_id = new_game_object.uuid.to_string();
|
||||
|
||||
// Add game to active list
|
||||
self.state.games.write().unwrap().insert(
|
||||
new_game_object.uuid.to_string(),
|
||||
Arc::new(RwLock::new(new_game_object)),
|
||||
);
|
||||
self.games
|
||||
.insert(new_game_object.uuid.to_string(), new_game_object);
|
||||
|
||||
// Register game to user
|
||||
self.register_user_in_game(game_id.clone(), host.read().unwrap().uuid.clone());
|
||||
|
@ -386,17 +368,14 @@ impl GameHandler {
|
|||
// TODO: this may get expensive if there are many games
|
||||
|
||||
let games = self
|
||||
.state
|
||||
.games
|
||||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.map(|game| GameBrowserMeta {
|
||||
uuid: game.read().unwrap().uuid.to_string(),
|
||||
name: game.read().unwrap().name.clone(),
|
||||
host: game.read().unwrap().host.read().unwrap().name.clone(),
|
||||
players: game.read().unwrap().players.len(),
|
||||
packs: game.read().unwrap().packs.clone(),
|
||||
uuid: game.uuid.to_string(),
|
||||
name: game.name.clone(),
|
||||
host: game.host.read().unwrap().name.clone(),
|
||||
players: game.players.len(),
|
||||
packs: game.packs.clone(),
|
||||
})
|
||||
.collect::<Vec<GameBrowserMeta>>();
|
||||
|
||||
|
@ -412,7 +391,7 @@ impl GameHandler {
|
|||
/// Broadcast updated game count
|
||||
fn broadcast_game_count(&self) {
|
||||
let tx = self.state.broadcast_tx.clone();
|
||||
let active_games = self.state.games.read().unwrap().len();
|
||||
let active_games = self.games.len();
|
||||
let msg = to_string(&ServerActiveGames { active_games }).unwrap();
|
||||
tokio::spawn(async move { tx.send(msg) });
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@ pub struct AppState {
|
|||
pub offline_users: RwLock<HashMap<String, Arc<RwLock<User>>>>,
|
||||
pub packs: CardPacks,
|
||||
pub packs_meta: CardPacksMeta,
|
||||
pub games: RwLock<HashMap<String, Arc<RwLock<Game>>>>,
|
||||
}
|
||||
|
||||
/// Card Set
|
||||
|
|
|
@ -80,7 +80,6 @@ async fn main() -> Result<()> {
|
|||
let online_users = RwLock::new(HashMap::<SocketAddr, Arc<RwLock<User>>>::new());
|
||||
let offline_users = RwLock::new(HashMap::<String, Arc<RwLock<User>>>::new());
|
||||
let (packs, packs_meta, white_cards_by_id) = load_cards_from_json("data/cah-cards-full.json")?;
|
||||
let games = RwLock::new(HashMap::new());
|
||||
|
||||
let app_state = Arc::new(AppState {
|
||||
white_cards_by_id,
|
||||
|
@ -97,7 +96,6 @@ async fn main() -> Result<()> {
|
|||
offline_users,
|
||||
packs,
|
||||
packs_meta,
|
||||
games,
|
||||
});
|
||||
|
||||
// Spawn task to handle incoming messages, also handles outging messages
|
||||
|
@ -126,7 +124,7 @@ async fn main() -> Result<()> {
|
|||
.unwrap();
|
||||
|
||||
// Spawn task to handle Game things
|
||||
let game_handler = GameHandler::new(app_state.clone());
|
||||
let mut game_handler = GameHandler::new(app_state.clone());
|
||||
tokio::task::Builder::new()
|
||||
.name("Game Handler")
|
||||
.spawn(async move {
|
||||
|
|
Loading…
Add table
Reference in a new issue