diff --git a/client/src/error.rs b/client/src/error.rs index 20f3319649..27ff6b9142 100644 --- a/client/src/error.rs +++ b/client/src/error.rs @@ -7,6 +7,7 @@ pub enum Error { ServerTimeout, ServerShutdown, TooManyPlayers, + InvalidAuth, //TODO: InvalidAlias, Other(String), } diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index ee07025a55..a4dc1ba7da 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -19,6 +19,7 @@ pub enum Error { NoAddress, // Parsing/host name resolution successful but could not connect. ConnectionFailed(ClientError), + InvalidAuth, ClientCrashed, ServerIsFull, } @@ -81,6 +82,9 @@ impl ClientInit { last_err = Some(Error::ServerIsFull); break; } + ClientError::InvalidAuth => { + last_err = Some(Error::InvalidAuth); + } // TODO: Handle errors? _ => panic!( "Unexpected non-network error when creating client: {:?}", diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 13f24e53d3..33f7d22493 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -64,6 +64,7 @@ impl PlayState for MainMenuState { self.main_menu_ui.login_error( match err { InitError::BadAddress(_) | InitError::NoAddress => "Server not found", + InitError::InvalidAuth => "Invalid username or password", InitError::ServerIsFull => "Server is Full!", InitError::ConnectionFailed(_) => "Connection failed", InitError::ClientCrashed => "Client crashed", @@ -82,10 +83,12 @@ impl PlayState for MainMenuState { match event { MainMenuEvent::LoginAttempt { username, + password, server_address, } => { let mut net_settings = &mut global_state.settings.networking; net_settings.username = username.clone(); + net_settings.password = password.clone(); if !net_settings.servers.contains(&server_address) { net_settings.servers.push(server_address.clone()); } @@ -107,7 +110,7 @@ impl PlayState for MainMenuState { ))); } else { self.main_menu_ui - .login_error("Invalid username".to_string()); + .login_error("Invalid username or password".to_string()); } } MainMenuEvent::StartSingleplayer => { diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 3b7941d24b..b1602adc72 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -38,10 +38,14 @@ widget_ids! { username_text, username_bg, username_field, + password_text, + password_bg, + password_field, singleplayer_button, singleplayer_text, usrnm_bg, srvr_bg, + passwd_bg, // Server list servers_button, servers_frame, @@ -87,6 +91,7 @@ font_ids! { pub enum Event { LoginAttempt { username: String, + password: String, server_address: String, }, StartSingleplayer, @@ -101,6 +106,7 @@ pub struct MainMenuUi { imgs: Imgs, fonts: Fonts, username: String, + password: String, server_address: String, login_error: Option, connecting: Option, @@ -129,6 +135,7 @@ impl MainMenuUi { imgs, fonts, username: networking.username.clone(), + password: "".to_owned(), server_address: networking.servers[networking.default_server].clone(), login_error: None, connecting: None, @@ -227,6 +234,7 @@ impl MainMenuUi { self.connecting = Some(std::time::Instant::now()); events.push(Event::LoginAttempt { username: self.username.clone(), + password: self.password.clone(), server_address: self.server_address.clone(), }); }; @@ -240,6 +248,7 @@ impl MainMenuUi { events.push(Event::StartSingleplayer); events.push(Event::LoginAttempt { username: "singleplayer".to_string(), + password: String::default(), server_address: "localhost".to_string(), }); }; @@ -274,6 +283,35 @@ impl MainMenuUi { } } } + // Password + Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97)) + .down_from(self.ids.usrnm_bg, 30.0) + .set(self.ids.passwd_bg, ui_widgets); + Image::new(self.imgs.input_bg) + .w_h(337.0, 67.0) + .middle_of(self.ids.passwd_bg) + .set(self.ids.password_bg, ui_widgets); + for event in TextBox::new(&self.password) + .w_h(290.0, 30.0) + .mid_bottom_with_margin_on(self.ids.password_bg, 44.0 / 2.0) + .font_size(22) + .font_id(self.fonts.opensans) + .text_color(TEXT_COLOR) + // transparent background + .color(TRANSPARENT) + .border_color(TRANSPARENT) + .set(self.ids.password_field, ui_widgets) + { + match event { + TextBoxEvent::Update(password) => { + // Note: TextBox limits the input string length to what fits in it + self.password = password; + } + TextBoxEvent::Enter => { + login!(); + } + } + } // Login error if let Some(msg) = &self.login_error { let text = Text::new(&msg) @@ -369,7 +407,7 @@ impl MainMenuUi { } // Server address Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97)) - .down_from(self.ids.usrnm_bg, 30.0) + .down_from(self.ids.passwd_bg, 30.0) .set(self.ids.srvr_bg, ui_widgets); Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 8495bde99a..46b11a77c1 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -100,6 +100,7 @@ impl Default for GameplaySettings { #[serde(default)] pub struct NetworkingSettings { pub username: String, + pub password: String, pub servers: Vec, pub default_server: usize, } @@ -108,6 +109,7 @@ impl Default for NetworkingSettings { fn default() -> Self { Self { username: "Username".to_string(), + password: String::default(), servers: vec!["server.veloren.net".to_string()], default_server: 0, }