damnit, i changed again
This commit is contained in:
parent
e595bd2d1b
commit
e01e8370fe
3 changed files with 121 additions and 82 deletions
141
src/api.rs
141
src/api.rs
|
@ -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(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue