pub struct User { state: tokio::sync::RwLock, } impl User { pub fn new(provider: std::sync::Arc) -> Self { Self { state: tokio::sync::RwLock::new(UserState::Unauthenticated(provider)), } } pub async fn authenticate(&self, info: rlnl::events::loading::GameGuidInfo) -> bool { let init_state_clone = self.state.read().await.clone(); match init_state_clone { UserState::Unauthenticated(auth) => { let result = >::multiplayer_authenticate::<'_, '_>(&auth, info.player_name.0.clone()).await; match result { Ok(user) => { *self.state.write().await = UserState::Authenticated(UserInfo { game: info.game_guid.0, user: std::sync::Arc::new(user), }); true }, Err(e) => { log::error!("Failed to authenticate {}: {}", info.player_name.0, e.message); false } } }, UserState::Authenticated(_) => { log::warn!("User already authenticated, ignoring"); true } } } pub async fn user(&self) -> Option>> { match &*self.state.read().await { UserState::Unauthenticated(_) => None, UserState::Authenticated(user) => Some(user.user.clone()), } } pub async fn game_guid(&self) -> Option { match &*self.state.read().await { UserState::Unauthenticated(_) => None, UserState::Authenticated(user) => Some(user.game.clone()), } } } #[derive(Clone)] enum UserState { Unauthenticated(std::sync::Arc), Authenticated(UserInfo), } #[derive(Clone)] pub struct UserInfo { pub game: String, pub user: std::sync::Arc>, }