#![allow(dead_code)] use sparse::Sparse; use pool::Pool; use trie::Trie; use crate::{ system::filesystem::FileSystem, util::Chain, protocol::QRPacket, }; pub mod connection; use connection::Connection; pub mod user; use user::User; pub mod authentication; use authentication::Authentication; pub mod session; use session::{Session, SessionToken}; pub mod context; pub struct App { pub filesystem:FileSystem, pub connections:Pool, pub users:Pool, pub user_id:Sparse, pub user_handle:Trie, pub salts:Sparse<[u8; 16]>, pub auths:Trie, pub sessions:Trie, pub session_time:Chain, } impl App { pub fn init() -> Result { if let Ok(mut filesystem) = FileSystem::init() { // Load salts println!("Loading salts.."); let mut salts = Sparse::new(); let salt_count = filesystem.salt_count()?; for id in 0..salt_count { let salt = filesystem.salt_fetch(id as u32).unwrap(); salts.set(id as isize, salt); } // Load handles println!("Loading handles.."); let mut user_handle = Trie::new(); let handle_count = filesystem.handle_count()?; for id in 0..handle_count { let (handle, user_id) = filesystem.handle_fetch(id as u32).unwrap(); user_handle.set(handle.as_bytes(), user_id); } // Load users println!("Loading users.."); let mut users = Pool::new(); let mut user_id = Sparse::new(); let user_count = filesystem.user_count()?; for id in 0..user_count { let user = filesystem.user_fetch(id as u32).unwrap(); let user_local_id = users.add(user); user_id.set(user_local_id as isize, id); } // Load sessions println!("Loading sessions.."); let mut sessions = Trie::new(); let mut times = Vec::<(u64, SessionToken)>::new(); let session_count = filesystem.session_count()?; for id in 0..session_count { let mut session = filesystem.session_fetch(id as u32).unwrap(); times.push((session.time, session.token.clone())); // Load session history if let Ok(history) = filesystem.session_history_fetch(id as u32) { session.game.apply_history(&history).ok(); } sessions.set(&session.token.clone(), session); } // Organize sessions by most recent let mut session_time = Chain::new(); times.sort_by(|(a, _), (b, _)| { if a > b { std::cmp::Ordering::Greater } else { std::cmp::Ordering::Less } }); for (_, token) in times { let id = session_time.add(token); sessions.get_mut(&token).unwrap().chain_id = id; } println!("App data ready."); Ok(Self { filesystem:filesystem, connections:Pool::new(), users, user_id, user_handle, salts, auths:Trie::new(), sessions, session_time, }) } else { Err(()) } } pub fn get_user_by_id(&self, id:u32) -> Option<&User> { if let Some(uid) = self.user_id.get(id as isize) { self.users.get(*uid) } else { None } } pub async fn send_response(&mut self, response:QRPacket) { use crate::protocol::*; use tokio_tungstenite::tungstenite::Message; use futures::SinkExt; fn encode_response(code:u16, data:Vec) -> Vec { [ crate::util::pack::pack_u16(code), data, ].concat() } if match response.data { QRPacketData::None => false, _ => true } { if let Some(conn) = self.connections.get_mut(response.id as usize) { let mut socket = conn.stream.write().await; match response.data { QRPacketData::RRegister(response) => { socket.send(Message::Binary( encode_response(CODE_REGISTER, response.encode()) )).await.ok(); } QRPacketData::RAuth(response) => { socket.send(Message::Binary( encode_response(CODE_AUTH, response.encode()) )).await.ok(); } QRPacketData::RAuthResume(response) => { socket.send(Message::Binary( encode_response(CODE_AUTH_RESUME, response.encode()) )).await.ok(); } QRPacketData::RSessionList(response) => { socket.send(Message::Binary( encode_response(CODE_SESSION_LIST, response.encode()) )).await.ok(); } QRPacketData::RSessionCreate(response) => { socket.send(Message::Binary( encode_response(CODE_SESSION_CREATE, response.encode()) )).await.ok(); } QRPacketData::RSessionJoin(response) => { socket.send(Message::Binary( encode_response(CODE_SESSION_JOIN, response.encode()) )).await.ok(); } QRPacketData::RGameState(response) => { socket.send(Message::Binary( encode_response(CODE_GAME_STATE, response.encode()) )).await.ok(); } QRPacketData::QGamePlay(response) => { socket.send(Message::Binary( encode_response(CODE_GAME_PLAY, response.encode()) )).await.ok(); } QRPacketData::RGameHistory(response) => { socket.send(Message::Binary( encode_response(CODE_GAME_HISTORY, response.encode()) )).await.ok(); } _ => { } } } } } }