106 lines
3.4 KiB
Rust
106 lines
3.4 KiB
Rust
use crate::game_handler::*;
|
|
use crate::message_handler::*;
|
|
use crate::websocket::*;
|
|
use anyhow::{Context, Result};
|
|
use axum::{routing::get, Router};
|
|
use server::*;
|
|
use std::{
|
|
collections::{HashMap, HashSet},
|
|
net::SocketAddr,
|
|
sync::{Arc, RwLock},
|
|
};
|
|
use tokio::sync::{broadcast, mpsc};
|
|
use tower::ServiceBuilder;
|
|
use tower_http::{compression::CompressionLayer, services::ServeDir};
|
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
use user_handler::UserHandler;
|
|
use uuid::Uuid;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
// stuff for logging
|
|
tracing_subscriber::registry()
|
|
.with(
|
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| "server=trace,tower_http=trace,lib=trace".into()),
|
|
)
|
|
.with(tracing_subscriber::fmt::layer())
|
|
.init();
|
|
|
|
// Set up state
|
|
let (broadcast_tx, _rx) = broadcast::channel(100);
|
|
let (users_tx, mut users_rx) = mpsc::channel(100);
|
|
let (messages_tx, mut messages_rx) = mpsc::channel(100);
|
|
let (games_tx, mut games_rx) = mpsc::channel(100);
|
|
let first_names = load_names("data/first.txt")?;
|
|
let last_names = load_names("data/last.txt")?;
|
|
let reserved_names = RwLock::new(HashSet::<String>::new());
|
|
let users_by_id = RwLock::new(HashMap::<Uuid, Arc<RwLock<User>>>::new());
|
|
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) = load_cards_from_json("data/cah-cards-full.json")?;
|
|
let games = RwLock::new(HashMap::new());
|
|
|
|
let app_state = Arc::new(AppState {
|
|
broadcast_tx,
|
|
users_tx,
|
|
messages_tx,
|
|
games_tx,
|
|
first_names,
|
|
last_names,
|
|
reserved_names,
|
|
users_by_id,
|
|
online_users,
|
|
offline_users,
|
|
packs,
|
|
packs_meta,
|
|
games,
|
|
});
|
|
|
|
// Spawn task to handle incoming messages, also handles outging messages
|
|
let message_handler = MessageHandler::new(app_state.clone());
|
|
tokio::spawn(async move {
|
|
while let Some((addr, message)) = messages_rx.recv().await {
|
|
message_handler.handle(addr, message).await;
|
|
}
|
|
});
|
|
|
|
// TODO: Make an outgoing message handler handler
|
|
|
|
// Spawn task to handle User things
|
|
let user_handler = UserHandler::new(app_state.clone());
|
|
tokio::spawn(async move {
|
|
while let Some(message) = users_rx.recv().await {
|
|
user_handler.handle(message).await;
|
|
}
|
|
});
|
|
|
|
// Spawn task to handle Game things
|
|
let game_handler = GameHandler::new(app_state.clone());
|
|
tokio::spawn(async move {
|
|
while let Some(message) = games_rx.recv().await {
|
|
game_handler.handle(message).await;
|
|
}
|
|
});
|
|
|
|
// Router
|
|
let app = Router::new()
|
|
.route("/websocket", get(websocket_connection_handler))
|
|
.nest_service("/", ServeDir::new("dist"))
|
|
.layer(ServiceBuilder::new().layer(CompressionLayer::new()))
|
|
.with_state(app_state);
|
|
|
|
// send it
|
|
let address = "0.0.0.0:3030";
|
|
let listener = tokio::net::TcpListener::bind(address)
|
|
.await
|
|
.with_context(|| format!("{} is not a valid bind address.", address))?;
|
|
tracing::info!("listening on {}", listener.local_addr()?);
|
|
axum::serve(
|
|
listener,
|
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
|
)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|