damnit, i changed again

This commit is contained in:
Adam 2024-05-03 23:17:39 -04:00
parent e595bd2d1b
commit e01e8370fe
3 changed files with 121 additions and 82 deletions

View file

@ -1,5 +1,6 @@
use crate::AppState;
use crate::gamemaster::*;
use crate::AppState;
use axum::extract::ConnectInfo;
use axum::{
extract::{
ws::{Message, WebSocket, WebSocketUpgrade},
@ -9,7 +10,7 @@ use axum::{
};
use futures::{sink::SinkExt, stream::StreamExt};
use serde::Deserialize;
use std::sync::Arc;
use std::{net::SocketAddr, sync::Arc};
/// New game request structure
#[derive(Debug, Deserialize)]
@ -34,66 +35,100 @@ pub struct GameJoinRequest {
pub async fn websocket_handler(
ws: WebSocketUpgrade,
// user_agent: Option<TypedHeader<headers::UserAgent>>,
ConnectInfo(addr): ConnectInfo<SocketAddr>,
State(state): State<Arc<AppState>>,
) -> impl IntoResponse {
ws.on_upgrade(|socket| websocket(socket, state))
tracing::debug!("New connection from {addr}");
ws.on_upgrade(move |socket| websocket(socket, state, addr))
}
pub async fn websocket(stream: WebSocket, state: Arc<AppState>) {
fn greeting(state: &Arc<AppState>) -> String {
format!(
"{:#?} Card packs loaded\n\
{:#?} Current active games",
state.all_cards.lock().unwrap().len(),
state.games.lock().unwrap().len(),
)
}
pub async fn websocket(stream: WebSocket, state: Arc<AppState>, who: SocketAddr) {
// By splitting, we can send and receive at the same time.
let (mut sender, mut receiver) = stream.split();
let _greeting = sender
.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;
let _greeting = sender.send(Message::Text(greeting(&state))).await;
// Loop until a text message is found.
while let Some(Ok(message)) = receiver.next().await {
match message {
Message::Text(text) => {
tracing::debug!("Text: {}", text);
// subscribe to channel
let mut rx = state.tx.subscribe();
if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) {
tracing::debug!("{:#?}", &new_game);
// create game
if let Ok(new_game_object) = CAHGame::new(new_game) {
state.games.lock().unwrap().push(new_game_object);
} else {
let _res = sender
.send(Message::Text(format!("error creating game")))
.await;
}
} else {
// just echo
let _res = sender.send(Message::Text(text)).await;
}
}
Message::Binary(data) => {
tracing::debug!("Binary: {:?}", data)
}
Message::Close(c) => {
if let Some(cf) = c {
tracing::debug!(
"Close received with code: {} and reason: {}",
cf.code,
cf.reason
)
} else {
tracing::debug!("close received without close frame")
}
}
Message::Pong(ping) => {
tracing::debug!("Pong received with: {:?}", ping);
}
Message::Ping(pong) => {
tracing::debug!("Pong received with: {:?}", pong);
// broadcast join
let msg = format!("{who} is here bitches");
tracing::debug!("{msg}");
let _ = state.tx.send(msg);
let mut send_task = tokio::spawn(async move {
while let Ok(msg) = rx.recv().await {
if sender.send(Message::Text(msg)).await.is_err() {
break;
}
}
}
});
// clone things for receiving task
let tx = state.tx.clone();
let name = who.clone();
let mut recv_task = tokio::spawn(async move {
while let Some(Ok(message)) = receiver.next().await {
match message {
Message::Text(text) => {
tracing::debug!("{who}: {}", text);
if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) {
tracing::debug!("{:#?}", &new_game);
// create game
if let Ok(new_game_object) = CAHGame::new(new_game) {
state.games.lock().unwrap().push(new_game_object);
let _update = tx.send(greeting(&state));
} else {
let _res = tx.send(format!("error creating game"));
}
} else {
// just echo
let msg = format!{"{who}: {text}"};
tracing::debug!("{msg}");
let _res = tx.send(msg);
}
}
Message::Binary(data) => {
tracing::debug!("Binary: {:?}", data)
}
Message::Close(c) => {
if let Some(cf) = c {
tracing::debug!(
"Close received from {who} with code: {} and reason: {}",
cf.code,
cf.reason
)
} else {
tracing::debug!("close received without close frame")
}
let msg = format!("{name} left.");
tracing::debug!("{msg}");
let _ = tx.send(msg);
}
Message::Pong(ping) => {
tracing::debug!("Pong received with: {:?}", ping);
}
Message::Ping(pong) => {
tracing::debug!("Pong received with: {:?}", pong);
}
}
}
});
// if either task completes then abort the other
tokio::select! {
_ = (&mut send_task) => recv_task.abort(),
_ = (&mut recv_task) => send_task.abort(),
};
}

View file

@ -1,6 +1,7 @@
use axum::{response::Html, routing::get, Router};
use axum::{response::Html, routing::get, Router, ServiceExt};
use std::{
collections::HashSet,
net::SocketAddr,
sync::{Arc, Mutex},
};
use std::{error::Error, fs, result::Result};
@ -120,7 +121,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
let listener = tokio::net::TcpListener::bind("0.0.0.0:3030").await?;
tracing::debug!("listening on {}", listener.local_addr()?);
axum::serve(listener, app).await?;
axum::serve(
listener,
app.into_make_service_with_connect_info::<SocketAddr>(),
)
.await?;
Ok(())
}

View file

@ -37,7 +37,7 @@
<div id="chat">
<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"></textarea>
<input id="chat-input" type="text" style="width: 30rem;" placeholder="chat" />
<input id="chat-input" type="text" style="width: 30rem;" placeholder="talk shit" />
</form>
</div>
<hr />
@ -61,7 +61,6 @@
</div>
<script type="text/javascript">
socket = new WebSocket("ws://localhost:3030/websocket");
socket.binaryType = "ArrayBuffer";
function socketTest() {
let code = testCloseCode.value;
@ -70,52 +69,52 @@
};
function createGame() {
let CAHPlayer = {
name: username.value,
role: 'Host',
white: [],
black: [],
};
let CAHPlayer = {
name: username.value,
role: 'Host',
white: [],
black: [],
};
let NewGameRequest = {
name: gamename.value,
host: CAHPlayer,
packs: [0],
};
let NewGameRequest = {
name: gamename.value,
host: CAHPlayer,
packs: [0],
};
socket.send(JSON.stringify(NewGameRequest));
};
function joinGame() {
console.log('not done yet');
console.log('not done yet');
}
socket.onopen = function() {
console.log("connection opened",socket.extensions, socket.protocol, socket.readyState);
document.getElementById("status").innerHTML = '<p><em>Connected!</em></p>';
console.log("connection opened",socket.extensions, socket.protocol, socket.readyState);
document.getElementById("status").innerHTML = '<p><em>Connected!</em></p>';
}
socket.onclose = function() {
console.log("connection closed");
document.getElementById("status").innerHTML = '<p><em>Disconnected...</em></p>';
document.getElementById("chat-history").value = "";
console.log("connection closed");
document.getElementById("status").innerHTML = '<p><em>Disconnected...</em></p>';
document.getElementById("chat-history").value = "";
}
socket.onmessage = function(e) {
const history = document.getElementById("chat-history")
console.log("received message: "+e.data);
history.value += e.data+"\r";
history.scrollTop = history.scrollHeight;
const history = document.getElementById("chat-history")
console.log("received message: "+e.data);
history.value += e.data+"\r";
history.scrollTop = history.scrollHeight;
}
function chatSubmit() {
let input = document.getElementById("chat-input");
socket.send(input.value);
input.value = "";
let input = document.getElementById("chat-input");
socket.send(input.value);
input.value = "";
};
socket.addEventListener("error", (event) => {
console.log("WebSocket error: ", event);
console.log("WebSocket error: ", event);
});
</script>
</body>