mmm big sloppy commit

This commit is contained in:
Adam 2024-05-03 18:48:12 -04:00
parent f9b6e57503
commit 10a72d3e4b
5 changed files with 42 additions and 116 deletions

4
Cargo.lock generated
View file

@ -39,9 +39,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "axum" name = "axum"

View file

@ -1,3 +1,4 @@
use crate::api::NewGameRequest; // change this
use rand::prelude::IteratorRandom; use rand::prelude::IteratorRandom;
use rand::thread_rng; use rand::thread_rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -85,28 +86,6 @@ pub struct CAHGame {
pub current_black: Option<CAHCardBlack>, pub current_black: Option<CAHCardBlack>,
} }
/// New game request structure
#[derive(Debug, Deserialize)]
pub struct NewGameRequest {
/// Game name
pub name: String,
/// Game host
pub host: CAHPlayer,
/// Chosen packs
pub packs: Vec<u8>,
}
/// Game join request structure
pub struct GameJoinRequest {
/// Game id
pub id: u8, // increase later
/// Game password
pub password: String,
/// Player info
pub player: CAHPlayer,
}
impl CAHGame { impl CAHGame {
/// Build game decks from input data for game start. /// Build game decks from input data for game start.
/// This should only run once and at startup. /// This should only run once and at startup.
@ -188,10 +167,7 @@ impl CAHGame {
/// Create a new player and add them to the game. /// Create a new player and add them to the game.
pub fn create_player(&mut self, mut player: CAHPlayer) -> Result<()> { pub fn create_player(&mut self, mut player: CAHPlayer) -> Result<()> {
println!( println!("Creating player {} as {:?}", &player.name, &player.role);
"Creating player {} as {:?}",
&player.name, &player.role
);
let mut hand_buf = vec![]; let mut hand_buf = vec![];
for _ in 0..10 { for _ in 0..10 {

View file

@ -8,8 +8,30 @@ use axum::{
response::IntoResponse, response::IntoResponse,
}; };
use futures::{sink::SinkExt, stream::StreamExt}; use futures::{sink::SinkExt, stream::StreamExt};
use serde::Deserialize;
use std::sync::Arc; use std::sync::Arc;
/// New game request structure
#[derive(Debug, Deserialize)]
pub struct NewGameRequest {
/// Game name
pub name: String,
/// Game host
pub host: CAHPlayer,
/// Chosen packs
pub packs: Vec<u8>,
}
/// Game join request structure
pub struct GameJoinRequest {
/// Game id
pub id: u8, // increase later
/// Game password
pub password: String,
/// Player info
pub player: CAHPlayer,
}
pub async fn websocket_handler( pub async fn websocket_handler(
ws: WebSocketUpgrade, ws: WebSocketUpgrade,
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
@ -21,14 +43,21 @@ pub async fn websocket(stream: WebSocket, state: Arc<AppState>) {
// By splitting, we can send and receive at the same time. // By splitting, we can send and receive at the same time.
let (mut sender, mut receiver) = stream.split(); let (mut sender, mut receiver) = stream.split();
// Username gets set in the receive loop, if it's valid. let _greeting = sender
let mut newplayer = String::new(); .send(Message::Text(format!(
"Greetings! \n\
{:#?} Card packs loaded\n\
{:#?} Current active games",
state.all_cards.lock().unwrap().len(),
state.games.lock().unwrap().len(),
)))
.await;
// Loop until a text message is found. // Loop until a text message is found.
while let Some(Ok(message)) = receiver.next().await { while let Some(Ok(message)) = receiver.next().await {
match message { match message {
Message::Text(text) => { Message::Text(text) => {
tracing::debug!("Text: {}", text); tracing::debug!("Text: {}", text);
// let message_str: &str = message.to_text().unwrap();
if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) { if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) {
tracing::debug!("{:#?}", new_game); tracing::debug!("{:#?}", new_game);
} else { } else {
@ -46,88 +75,15 @@ pub async fn websocket(stream: WebSocket, state: Arc<AppState>) {
cf.reason cf.reason
) )
} else { } else {
tracing::debug!("close sent without close frame") tracing::debug!("close received without close frame")
} }
} }
Message::Pong(ping) => { Message::Pong(ping) => {
tracing::debug!("Pong sent with {:?}", ping); tracing::debug!("Pong received with: {:?}", ping);
} }
Message::Ping(pong) => { Message::Ping(pong) => {
tracing::debug!("Pong sent with {:?}", pong); tracing::debug!("Pong received with: {:?}", pong);
} }
} }
// if let Message::Text(name) = message {
// // 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 !newplayer.is_empty() {
// break;
// } else {
// // Only send our client that newplayer is taken.
// let _ = sender
// .send(Message::Text(String::from("Username already taken.")))
// .await;
//
// return;
// }
// }
}
// We subscribe *before* sending the "joined" message, so that we will also
// display it to our client.
let mut rx = state.tx.subscribe();
// Now send the "joined" message to all subscribers.
let msg = format!("{newplayer} joined.");
tracing::debug!("{msg}");
let _ = state.tx.send(msg);
// Spawn the first task that will receive broadcast messages and send text
// messages over the websocket to our client.
let mut send_task = tokio::spawn(async move {
while let Ok(msg) = rx.recv().await {
// In any websocket error, break loop.
if sender.send(Message::Text(msg)).await.is_err() {
break;
}
}
});
// Clone things we want to pass (move) to the receiving task.
let tx = state.tx.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 newplayer before message.
let _ = tx.send(format!("{name}: {text}"));
}
});
// If any one of the tasks run to completion, we abort the other.
tokio::select! {
_ = (&mut send_task) => recv_task.abort(),
_ = (&mut recv_task) => send_task.abort(),
};
// Send "user left" message (similar to "joined" above).
let msg = format!("{newplayer} left.");
tracing::debug!("{msg}");
let _ = state.tx.send(msg);
// 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) {
let mut user_set = state.user_set.lock().unwrap();
if !user_set.contains(name) {
user_set.insert(name.to_owned());
string.push_str(name);
} }
} }

View file

@ -113,13 +113,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
games, games,
}); });
tracing::debug!(
"Loaded {} Card packs!",
&app_state.all_cards.lock().unwrap().len()
);
tracing::debug!("{} active games", &app_state.games.lock().unwrap().len());
let app = Router::new() let app = Router::new()
.route("/", get(index)) .route("/", get(index))
.route("/test", get(spawnclients)) .route("/test", get(spawnclients))

View file

@ -67,7 +67,7 @@
<div id="chat"> <div id="chat">
<h3>Chat</h3> <h3>Chat</h3>
<form id="chat" onsubmit="chatSubmit();return false"> <form id="chat" onsubmit="chatSubmit();return false">
<textarea id="chat-history" readonly="true" wrap="soft" style="display:block; width:30rem; height:10rem; box-sizing: border-box" cols="30" rows="10">Not in game</textarea> <textarea id="chat-history" readonly="true" wrap="soft" style="display:block; width:30rem; height:10rem; box-sizing: border-box" cols="30" rows="10"></textarea>
<input id="chat-input" type="text" style="width: 30rem;" placeholder="chat" /> <input id="chat-input" type="text" style="width: 30rem;" placeholder="chat" />
</form> </form>
</div> </div>
@ -99,7 +99,7 @@
}; };
function joinGame() { function joinGame() {
console.log('not done yet'); console.log('not done yet');
} }
socket.onopen = function() { socket.onopen = function() {
@ -110,6 +110,7 @@
socket.onclose = function() { socket.onclose = function() {
console.log("connection closed"); console.log("connection closed");
document.getElementById("status").innerHTML = '<p><em>Disconnected...</em></p>'; document.getElementById("status").innerHTML = '<p><em>Disconnected...</em></p>';
document.getElementById("chat-history").value = "";
} }
socket.onmessage = function(e) { socket.onmessage = function(e) {