split messages up based on state, refactored backend to decouple states more

This commit is contained in:
2025-05-23 21:32:04 -06:00
parent af0fd811b3
commit abb3f4c2da
15 changed files with 520 additions and 348 deletions
+5 -10
View File
@@ -1,7 +1,6 @@
use ewebsock::WsEvent;
use macroquad::prelude::{error, info};
use crate::model::{ClientMessage, ClientRequest, GameResponse};
use serde::{Serialize, de::DeserializeOwned};
pub struct Context {
pub sender: ewebsock::WsSender,
@@ -22,16 +21,12 @@ impl Context {
}
}
pub fn send_msg(&mut self, msg: &ClientMessage) {
let request = ClientRequest {
token: self.token.clone(),
msg: msg.clone(),
};
let msg = serde_json::to_string(&request).unwrap();
pub fn send_msg<T: Serialize>(&mut self, msg: &T) {
let msg = serde_json::to_string(msg).unwrap();
self.sender.send(ewebsock::WsMessage::Text(msg));
}
pub fn recv_msg(&mut self) -> Option<GameResponse> {
pub fn recv_msg<T: DeserializeOwned>(&mut self) -> Option<T> {
if let Some(msg) = self.reciever.try_recv() {
match msg {
WsEvent::Opened => {
@@ -40,7 +35,7 @@ impl Context {
}
WsEvent::Message(ws_message) => match ws_message {
ewebsock::WsMessage::Text(msg) => {
let game_resp: GameResponse = serde_json::from_str(&msg).unwrap();
let game_resp: T = serde_json::from_str(&msg).unwrap();
Some(game_resp)
}
+37 -5
View File
@@ -1,9 +1,30 @@
use macroquad::prelude::*;
use std::collections::HashMap;
use crate::{model::ClientMessage, screen::Screen};
use macroquad::prelude::*;
use serde::{Deserialize, Serialize};
use crate::{model::player::Player, screen::Screen};
#[allow(dead_code)]
#[derive(Serialize)]
#[serde(tag = "type")]
enum HostClientMessages {
ResetAllBuzers,
ResetPlayerBuzzer { user_id: u64 },
UpdateScore { user_id: u64, diff: u32 },
}
#[derive(Deserialize)]
#[serde(tag = "type")]
enum HostServerMessages {
Ack,
UpdatePlayerStates { players: HashMap<u64, Player> },
}
#[derive(Default)]
pub struct HostScreen {}
pub struct HostScreen {
players: HashMap<u64, Player>,
}
impl Screen for HostScreen {
fn handle_frame(&mut self, ctx: &mut crate::context::Context) {
@@ -32,15 +53,26 @@ impl Screen for HostScreen {
let normalize = loc - button_location;
if normalize.length() < button_size {
ctx.send_msg(&ClientMessage::ResetBuzzers);
ctx.send_msg(&HostClientMessages::ResetAllBuzers);
}
}
}
fn handle_messages(
&mut self,
_ctx: &mut crate::context::Context,
ctx: &mut crate::context::Context,
) -> Option<crate::StateTransition> {
if let Some(msg) = ctx.recv_msg() {
match msg {
HostServerMessages::Ack => {
// pass
}
HostServerMessages::UpdatePlayerStates { players } => {
self.players = players;
}
};
}
None
}
}
+21 -11
View File
@@ -1,10 +1,23 @@
use crate::StateTransition;
use crate::context::Context;
use crate::model::register::Register;
use crate::model::{ClientMessage, GameResponse};
use crate::screen::Screen;
use macroquad::hash;
use macroquad::{prelude::*, ui::root_ui};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
pub enum NewUserClientMessages {
Register { game_code: String, username: String },
CreateRoom { game_code: String, username: String },
}
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum NewUserServerMessages {
RegisterResponse { username: String, token: String },
HostRegisterResponse { username: String, token: String },
}
#[derive(Default)]
pub struct LoginScreen {
@@ -70,19 +83,19 @@ impl Screen for LoginScreen {
);
if pressed_join {
ctx.send_msg(&ClientMessage::Register(Register {
ctx.send_msg(&NewUserClientMessages::Register {
game_code: self.new_room_code.clone(),
username: self.new_username.clone(),
}));
});
self.sent_join = true;
}
if pressed_host {
ctx.send_msg(&ClientMessage::CreateRoom(Register {
ctx.send_msg(&NewUserClientMessages::CreateRoom {
game_code: self.new_room_code.clone(),
username: self.new_username.clone(),
}));
});
self.sent_host = true;
}
@@ -94,19 +107,16 @@ impl Screen for LoginScreen {
if let Some(msg) = msg {
match msg {
GameResponse::JoinResponse { username, token } => {
NewUserServerMessages::RegisterResponse { username, token } => {
ctx.username = username;
ctx.token = token;
return Some(StateTransition::JoinAsPlayer);
}
GameResponse::HostResponse { username, token } => {
NewUserServerMessages::HostRegisterResponse { username, token } => {
ctx.username = username;
ctx.token = token;
return Some(StateTransition::JoinAsHost);
}
_ => {
warn!("Got unexpected message: {:?}", msg)
}
}
}
-6
View File
@@ -1,6 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BuzzIn {
pub time: f64,
}
+1 -31
View File
@@ -1,31 +1 @@
use buzz_in::BuzzIn;
use register::Register;
use serde::{Deserialize, Serialize};
pub mod buzz_in;
pub mod register;
#[derive(Debug, Serialize, Clone)]
#[serde(tag = "type")]
pub enum ClientMessage {
BuzzIn(BuzzIn),
Register(Register),
CreateRoom(Register),
ResetBuzzers,
}
#[derive(Debug, Serialize)]
pub struct ClientRequest {
pub token: String,
pub msg: ClientMessage,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum GameResponse {
JoinResponse { username: String, token: String },
HostResponse { username: String, token: String },
AckBuzzer,
ResetBuzzer,
UpdatePointTotal { score: i32 },
}
pub mod player;
+8
View File
@@ -0,0 +1,8 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Player {
pub name: String,
pub id: u64,
pub score: i32,
}
-7
View File
@@ -1,7 +0,0 @@
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct Register {
pub game_code: String,
pub username: String,
}
+19 -10
View File
@@ -1,12 +1,25 @@
use serde::{Deserialize, Serialize};
use web_time::{SystemTime, UNIX_EPOCH};
use crate::StateTransition;
use crate::context::Context;
use crate::model::ClientMessage;
use crate::model::buzz_in::BuzzIn;
use crate::screen::Screen;
use macroquad::prelude::*;
#[derive(Serialize, Debug)]
#[serde(tag = "type")]
pub enum PlayerClientMessages {
BuzzIn { time: f64 },
}
#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
pub enum PlayerServerMessages {
Ack,
UpdatePointTotal { score: i32 },
ResetBuzzer,
}
#[derive(Default)]
pub struct PlayerScreen {
score: i32,
@@ -19,20 +32,18 @@ impl Screen for PlayerScreen {
if let Some(msg) = msg {
match msg {
crate::model::GameResponse::JoinResponse { .. } => {}
crate::model::GameResponse::AckBuzzer => {
PlayerServerMessages::Ack => {
info!("Button pressed ack");
self.button_pressed = true;
}
crate::model::GameResponse::ResetBuzzer => {
PlayerServerMessages::ResetBuzzer => {
info!("Button press reset");
self.button_pressed = false;
}
crate::model::GameResponse::UpdatePointTotal { score } => {
PlayerServerMessages::UpdatePointTotal { score } => {
info!("Score updated to: {}", score);
self.score = score;
}
_ => {}
}
}
@@ -81,9 +92,7 @@ impl Screen for PlayerScreen {
let time = unix_timestamp.as_secs_f64();
info!("Button pressed @ {}", time);
let buzz_in = BuzzIn { time };
ctx.send_msg(&ClientMessage::BuzzIn(buzz_in));
ctx.send_msg(&PlayerClientMessages::BuzzIn { time });
}
}
}