← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start into lp:widelands

 

Toni Förster has proposed merging lp:~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start into lp:widelands with lp:~widelands-dev/widelands/bug-1825932-open-games as a prerequisite.

Commit message:
redesigned login box

- limit the possible characters for usernames
- draw a red box around the input field for erroneous input
- tell user were to register their username
- clicking registered checkbox focuses password field
- remove check from registered clears password field
- password field is only accessible when checkbox is clicked
- when a password is set, ***** is shown on opening

multiplayer login redesign

- only show login dialog when no name is set
- always show login box settings button

Requested reviews:
  kaputtnik (franku)
Related bugs:
  Bug #1827786 in widelands: "reconsider the metaserver loginbox"
  https://bugs.launchpad.net/widelands/+bug/1827786

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start/+merge/367319
-- 
Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/bug-1825932-open-games.
=== modified file 'src/network/internet_gaming.cc'
--- src/network/internet_gaming.cc	2019-05-11 18:50:30 +0000
+++ src/network/internet_gaming.cc	2019-05-12 11:08:42 +0000
@@ -487,7 +487,7 @@
 				InternetGame* ing = new InternetGame();
 				ing->name = packet.string();
 				ing->build_id = packet.string();
-				ing->connectable = (packet.string() == INTERNET_GAME_SETUP);
+				ing->connectable = packet.string();
 				gamelist_.push_back(*ing);
 
 				bool found = false;
@@ -498,10 +498,13 @@
 						break;
 					}
 				}
-				if (!found)
+				if (!found && ing->connectable != INTERNET_GAME_RUNNING &&
+					(ing->build_id == build_id() || (ing->build_id.compare(0, 6, "build-") != 0
+					&& build_id().compare(0, 6, "build-") != 0))) {
 					format_and_add_chat(
-					   "", "", true,
-					   (boost::format(_("The game %s is now available")) % ing->name).str());
+						"", "", true,
+						(boost::format(_("The game %s is now available")) % ing->name).str());
+				}
 
 				delete ing;
 				ing = nullptr;

=== modified file 'src/network/internet_gaming.h'
--- src/network/internet_gaming.h	2019-05-11 18:50:30 +0000
+++ src/network/internet_gaming.h	2019-05-12 11:08:42 +0000
@@ -43,7 +43,7 @@
 struct InternetGame {
 	std::string name;
 	std::string build_id;
-	bool connectable;
+	std::string connectable;
 };
 
 /**
@@ -178,6 +178,11 @@
 		return true;
 	}
 
+	void format_and_add_chat(const std::string& from,
+	                         const std::string& to,
+	                         bool system,
+	                         const std::string& msg);
+
 private:
 	InternetGaming();
 
@@ -202,11 +207,6 @@
 	bool str2bool(std::string);
 	std::string bool2str(bool);
 
-	void format_and_add_chat(const std::string& from,
-	                         const std::string& to,
-	                         bool system,
-	                         const std::string& msg);
-
 	/**
 	 * Does the real work of the login.
 	 * \param relogin Whether this is a relogin. Only difference is that

=== modified file 'src/ui_basic/editbox.cc'
--- src/ui_basic/editbox.cc	2019-05-11 18:50:30 +0000
+++ src/ui_basic/editbox.cc	2019-05-12 11:08:42 +0000
@@ -85,7 +85,8 @@
    : Panel(parent, x, y, w, h > 0 ? h : text_height(font_size) + 2 * margin_y),
      m_(new EditBoxImpl),
      history_active_(false),
-     history_position_(-1) {
+     history_position_(-1),
+     warning_(false) {
 	set_thinks(false);
 
 	m_->background_style = g_gr->styles().editbox_style(style);
@@ -346,7 +347,7 @@
 	draw_background(dst, *m_->background_style);
 
 	// Draw border.
-	if (get_w() >= 2 && get_h() >= 2) {
+	if (get_w() >= 2 && get_h() >= 2 && !warning_) {
 		static const RGBColor black(0, 0, 0);
 
 		// bottom edge
@@ -359,6 +360,25 @@
 		// left edge
 		dst.fill_rect(Recti(0, 0, 1, get_h() - 1), black);
 		dst.fill_rect(Recti(1, 0, 1, get_h() - 2), black);
+
+	} else {
+		// Draw a red border for warnings.
+		static const RGBColor red(255, 22, 22);
+
+		// bottom edge
+		dst.fill_rect(Recti(0, get_h() - 2, get_w(), 2), red);
+		// right edge
+		dst.fill_rect(Recti(get_w() - 2, 0, 2, get_h() -2), red);
+		// top edge
+		dst.fill_rect(Recti(0, 0, get_w() - 1, 1), red);
+		dst.fill_rect(Recti(0, 1, get_w() - 2, 1), red);
+		dst.brighten_rect(Recti(0, 0, get_w() - 1, 1), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(0, 1, get_w() - 2, 1), BUTTON_EDGE_BRIGHT_FACTOR);
+		// left edge
+		dst.fill_rect(Recti(0, 0, 1, get_h() - 1), red);
+		dst.fill_rect(Recti(1, 0, 1, get_h() - 2), red);
+		dst.brighten_rect(Recti(0, 0, 1, get_h() - 1), BUTTON_EDGE_BRIGHT_FACTOR);
+		dst.brighten_rect(Recti(1, 0, 1, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
 	}
 
 	if (has_focus()) {

=== modified file 'src/ui_basic/editbox.h'
--- src/ui_basic/editbox.h	2019-05-11 18:50:30 +0000
+++ src/ui_basic/editbox.h	2019-05-12 11:08:42 +0000
@@ -72,6 +72,10 @@
 
 	void draw(RenderTarget&) override;
 
+	void set_warning(bool warn) {
+		warning_ = warn;
+	}
+
 private:
 	std::unique_ptr<EditBoxImpl> m_;
 
@@ -80,6 +84,7 @@
 	bool history_active_;
 	int16_t history_position_;
 	std::string history_[CHAT_HISTORY_SIZE];
+	bool warning_;
 };
 }  // namespace UI
 

=== modified file 'src/ui_fsmenu/internet_lobby.cc'
--- src/ui_fsmenu/internet_lobby.cc	2019-05-11 18:50:30 +0000
+++ src/ui_fsmenu/internet_lobby.cc	2019-05-12 11:08:42 +0000
@@ -63,7 +63,7 @@
      // Text labels
      title(this, get_w() / 2, get_h() / 20, _("Metaserver Lobby"), UI::Align::kCenter),
      clients_(this, get_w() * 4 / 125, get_h() * 15 / 100, _("Clients online:")),
-     opengames_(this, get_w() * 17 / 25, get_h() * 15 / 100, _("List of games:")),
+     opengames_(this, get_w() * 17 / 25, get_h() * 15 / 100, _("Open Games:")),
      servername_(this, get_w() * 17 / 25, get_h() * 63 / 100, _("Name of your server:")),
 
      // Buttons
@@ -198,6 +198,9 @@
 	if (!chat.has_focus()) {
 		chat.unfocus_edit();
 	}
+	if (edit_servername_.has_focus()) {
+		change_servername();
+	}
 }
 
 void FullscreenMenuInternetLobby::clicked_ok() {
@@ -225,26 +228,22 @@
 	hostgame_.set_enabled(true);
 	joingame_.set_enabled(false);
 	std::string localservername = edit_servername_.text();
+	std::string localbuildid = build_id();
 
 	if (games != nullptr) {  // If no communication error occurred, fill the list.
 		for (const InternetGame& game : *games) {
 			const Image* pic;
-			if (game.connectable) {
-				if (game.build_id == build_id())
-					pic = g_gr->images().get("images/ui_basic/continue.png");
-				else {
+			if (game.connectable == INTERNET_GAME_SETUP && game.build_id == localbuildid) {
+				// only clients with the same build number are displayed
+				pic = g_gr->images().get("images/ui_basic/continue.png");
+				opengames_list_.add(game.name, game, pic, false, game.build_id);
+			} else if (game.connectable == INTERNET_GAME_SETUP &&
+				game.build_id.compare(0, 6, "build-") != 0 &&
+				localbuildid.compare(0, 6, "build-") != 0) {
+					// only development clients are allowed to see games openend by such
 					pic = g_gr->images().get("images/ui_basic/different.png");
-				}
-			} else {
-				pic = g_gr->images().get("images/ui_basic/stop.png");
-			}
-			// If one of the servers has the same name as the local name of the
-			// clients server, we disable the 'hostgame' button to avoid having more
-			// than one server with the same name.
-			if (game.name == localservername) {
-				hostgame_.set_enabled(false);
-			}
-			opengames_list_.add(game.name, game, pic, false, game.build_id);
+					opengames_list_.add(game.name, game, pic, false, game.build_id);
+			}
 		}
 	}
 }
@@ -341,10 +340,8 @@
 	// remove focus from chat
 	if (opengames_list_.has_selection()) {
 		const InternetGame* game = &opengames_list_.get_selected();
-		if (game->connectable)
+		if (game->connectable == INTERNET_GAME_SETUP)
 			joingame_.set_enabled(true);
-		else
-			joingame_.set_enabled(false);
 	}
 }
 
@@ -353,7 +350,7 @@
 	// if the game is open try to connect it, if not do nothing.
 	if (opengames_list_.has_selection()) {
 		const InternetGame* game = &opengames_list_.get_selected();
-		if (game->connectable)
+		if (game->connectable == INTERNET_GAME_SETUP)
 			clicked_joingame();
 	}
 }
@@ -362,7 +359,8 @@
 void FullscreenMenuInternetLobby::change_servername() {
 	// Allow client to enter a servername manually
 	hostgame_.set_enabled(true);
-
+	edit_servername_.set_tooltip("");
+	edit_servername_.set_warning(false);
 	// Check whether a server of that name is already open.
 	// And disable 'hostgame' button if yes.
 	const std::vector<InternetGame>* games = InternetGaming::ref().games();
@@ -370,6 +368,11 @@
 		for (const InternetGame& game : *games) {
 			if (game.name == edit_servername_.text()) {
 				hostgame_.set_enabled(false);
+				edit_servername_.set_warning(true);
+				edit_servername_.set_tooltip((boost::format
+					(_("The game %s is already running. Please choose a different name."))
+					% (boost::format("%s%s%s%s%s") %"<font bold=1 color="
+					% UI_FONT_CLR_WARNING.hex_value() % ">" % game.name % "</font>")).str());
 			}
 		}
 	}
@@ -415,10 +418,22 @@
 	// Save selected servername as default for next time and during that take care that the name is
 	// not empty.
 	std::string servername_ui = edit_servername_.text();
-	if (servername_ui.empty()) {
-		/** TRANSLATORS: This is shown for multiplayer games when no host */
-		/** TRANSLATORS: server to connect to has been specified yet. */
-		servername_ui = pgettext("server_name", "unnamed");
+
+	const std::vector<InternetGame>* games = InternetGaming::ref().games();
+	if (games != nullptr) {
+		for (const InternetGame& game : *games) {
+			if (servername_ui.empty()) {
+				uint32_t i = 1;
+				do {
+					/** TRANSLATORS: This is shown for multiplayer games when no host */
+					/** TRANSLATORS: server to connect to has been specified yet. */
+					servername_ui = (boost::format(_("unnamed %u")) % i++).str();
+				} while (servername_ui == game.name);
+			} else if (game.name == servername_ui) {
+				change_servername();
+				return;
+			}
+		}
 	}
 
 	g_options.pull_section("global").set_string("servername", servername_ui);

=== modified file 'src/ui_fsmenu/multiplayer.cc'
--- src/ui_fsmenu/multiplayer.cc	2019-05-11 18:50:30 +0000
+++ src/ui_fsmenu/multiplayer.cc	2019-05-12 11:08:42 +0000
@@ -58,21 +58,46 @@
 	vbox_.add_inf_space();
 	vbox_.add(&back, UI::Box::Resizing::kFullSize);
 
-	Section& s = g_options.pull_section("global");
-	auto_log_ = s.get_bool("auto_log", false);
-	if (auto_log_) {
-		showloginbox =
+	showloginbox =
 		   new UI::Button(this, "login_dialog", 0, 0, 0, 0, UI::ButtonStyle::kFsMenuSecondary,
 		                  g_gr->images().get("images/ui_basic/continue.png"), _("Show login dialog"));
-		showloginbox->sigclicked.connect(
+	showloginbox->sigclicked.connect(
 		   boost::bind(&FullscreenMenuMultiPlayer::show_internet_login, boost::ref(*this)));
-	}
 	layout();
 }
 
 /// called if the showloginbox button was pressed
 void FullscreenMenuMultiPlayer::show_internet_login() {
-	auto_log_ = false;
+	Section& s = g_options.pull_section("global");
+	LoginBox lb(*this);
+	if (lb.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {
+		nickname_ = lb.get_nickname();
+		s.set_string("nickname", nickname_);
+		/// NOTE: The password is only stored (in memory and on disk) and transmitted (over the
+		/// network
+		/// to the metaserver) as cryptographic hash. This does NOT mean that the password is
+		/// stored
+		/// securely on the local disk. While the password should be secure while transmitted to
+		/// the
+		/// metaserver (no-one can use the transmitted data to log in as the user) this is not the
+		/// case
+		/// for local storage. The stored hash of the password makes it hard to look at the
+		/// configuration
+		/// file and figure out the plaintext password to, e.g., log in on the forum. However, the
+		/// stored hash can be copied to another system and used to log in as the user on the
+		/// metaserver.
+		// Further note: SHA-1 is considered broken and shouldn't be used anymore. But since the
+		// passwords on the server are protected by SHA-1 we have to use it here, too
+		if (lb.get_password() != "*****") {
+			password_ = crypto::sha1(lb.get_password());
+			s.set_string("password_sha1", password_);
+		}
+
+		register_ = lb.registered();
+		s.set_bool("registered", lb.registered());
+	} else {
+		return;
+	}
 	internet_login();
 }
 
@@ -90,37 +115,15 @@
  */
 void FullscreenMenuMultiPlayer::internet_login() {
 	Section& s = g_options.pull_section("global");
-	if (auto_log_) {
-		nickname_ = s.get_string("nickname", _("nobody"));
-		password_ = s.get_string("password_sha1", "nobody");
-		register_ = s.get_bool("registered", false);
-	} else {
-		LoginBox lb(*this);
-		if (lb.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {
-			nickname_ = lb.get_nickname();
-			/// NOTE: The password is only stored (in memory and on disk) and transmitted (over the
-			/// network
-			/// to the metaserver) as cryptographic hash. This does NOT mean that the password is
-			/// stored
-			/// securely on the local disk. While the password should be secure while transmitted to
-			/// the
-			/// metaserver (no-one can use the transmitted data to log in as the user) this is not the
-			/// case
-			/// for local storage. The stored hash of the password makes it hard to look at the
-			/// configuration
-			/// file and figure out the plaintext password to, e.g., log in on the forum. However, the
-			/// stored hash can be copied to another system and used to log in as the user on the
-			/// metaserver.
-			// Further note: SHA-1 is considered broken and shouldn't be used anymore. But since the
-			// passwords on the server are protected by SHA-1 we have to use it here, too
-			password_ = crypto::sha1(lb.get_password());
-			register_ = lb.registered();
-
-			s.set_bool("registered", lb.registered());
-			s.set_bool("auto_log", lb.set_automaticlog());
-		} else {
-			return;
-		}
+
+	nickname_ = s.get_string("nickname", "");
+	password_ = s.get_string("password_sha1", "nobody");
+	register_ = s.get_bool("registered", false);
+
+	if (nickname_.empty() || nickname_.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@.+-_") <= nickname_.size()) {
+		show_internet_login();
+		return;
 	}
 
 	// Try to connect to the metaserver

=== modified file 'src/ui_fsmenu/multiplayer.h'
--- src/ui_fsmenu/multiplayer.h	2019-05-11 18:50:30 +0000
+++ src/ui_fsmenu/multiplayer.h	2019-05-12 11:08:42 +0000
@@ -61,7 +61,6 @@
 	std::string nickname_;
 	std::string password_;
 	bool register_;
-	bool auto_log_;
 };
 
 #endif  // end of include guard: WL_UI_FSMENU_MULTIPLAYER_H

=== modified file 'src/wui/login_box.cc'
--- src/wui/login_box.cc	2019-05-11 18:50:30 +0000
+++ src/wui/login_box.cc	2019-05-12 11:08:42 +0000
@@ -26,69 +26,65 @@
 #include "ui_basic/messagebox.h"
 
 LoginBox::LoginBox(Panel& parent)
-   : Window(&parent, "login_box", 0, 0, 500, 220, _("Metaserver login")) {
+   : Window(&parent, "login_box", 0, 0, 500, 280, _("Metaserver login")) {
 	center_to_parent();
 
 	int32_t margin = 10;
 
 	ta_nickname = new UI::Textarea(this, margin, margin, _("Nickname:"));
-	ta_password = new UI::Textarea(this, margin, 40, _("Password:"));
+	ta_password = new UI::Textarea(this, margin, 70, _("Password:"));
 	eb_nickname = new UI::EditBox(this, 150, margin, 330, 20, 2, UI::PanelStyle::kWui);
-	eb_password = new UI::EditBox(this, 150, 40, 330, 20, 2, UI::PanelStyle::kWui);
-
-	pwd_warning =
-	   new UI::MultilineTextarea(this, margin, 65, 505, 50, UI::PanelStyle::kWui,
-	                             _("WARNING: Password will be shown and saved readable!"));
-
-	cb_register = new UI::Checkbox(this, Vector2i(margin, 110), _("Log in to a registered account"),
+	eb_password = new UI::EditBox(this, 150, 70, 330, 20, 2, UI::PanelStyle::kWui);
+
+	cb_register = new UI::Checkbox(this, Vector2i(margin, 40), _("Log in to a registered account."),
 	                               "", get_inner_w() - 2 * margin);
-	cb_auto_log = new UI::Checkbox(this, Vector2i(margin, 135),
-	                               _("Automatically use this login information from now on."), "",
-	                               get_inner_w() - 2 * margin);
-
-	UI::Button* loginbtn = new UI::Button(
+
+	register_account = new UI::MultilineTextarea(this, margin, 105, 470, 140, UI::PanelStyle::kWui,
+			(boost::format(_("You need an account on the widelands website, to use a registered "
+				"account. Please visit: %s Log in to your newly created account and set an online "
+				"gaming password on your profile page."))
+				% "\n\nhttps://widelands.org/accounts/register/\n\n";).str());
+
+	loginbtn = new UI::Button(
 	   this, "login",
 	   UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 :
 	                                   (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2,
 	   get_inner_h() - 20 - margin, 200, 20, UI::ButtonStyle::kWuiPrimary, _("Login"));
-	loginbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_ok, boost::ref(*this)));
-	UI::Button* cancelbtn = new UI::Button(
+
+	cancelbtn = new UI::Button(
 	   this, "cancel",
 	   UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2 :
 	                                   (get_inner_w() / 2 - 200) / 2,
 	   loginbtn->get_y(), 200, 20, UI::ButtonStyle::kWuiSecondary, _("Cancel"));
+
+	loginbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_ok, boost::ref(*this)));
 	cancelbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_back, boost::ref(*this)));
+	eb_nickname->changed.connect(boost::bind(&LoginBox::change_playername, this));
+	cb_register->clickedto.connect(boost::bind(&LoginBox::clicked_register, this));
 
 	Section& s = g_options.pull_section("global");
 	eb_nickname->set_text(s.get_string("nickname", _("nobody")));
 	cb_register->set_state(s.get_bool("registered", false));
+
+	if (registered()) {
+		eb_password->set_text("*****");
+	} else {
+		eb_password->set_can_focus(false);
+		ta_password->set_color(UI_FONT_CLR_DISABLED);
+	}
+
 	eb_nickname->focus();
 }
 
+/// think function of the UI (main loop)
+void LoginBox::think() {
+	verify_input();
+}
+
 /**
  * called, if "login" is pressed.
  */
 void LoginBox::clicked_ok() {
-	// Check if all needed input fields are valid
-	if (eb_nickname->text().empty()) {
-		UI::WLMessageBox mb(
-		   this, _("Empty Nickname"), _("Please enter a nickname!"), UI::WLMessageBox::MBoxType::kOk);
-		mb.run<UI::Panel::Returncodes>();
-		return;
-	}
-	if (eb_nickname->text().find(' ') <= eb_nickname->text().size()) {
-		UI::WLMessageBox mb(this, _("Space in Nickname"),
-		                    _("Sorry, but spaces are not allowed in nicknames!"),
-		                    UI::WLMessageBox::MBoxType::kOk);
-		mb.run<UI::Panel::Returncodes>();
-		return;
-	}
-	if (eb_password->text().empty() && cb_register->get_state()) {
-		UI::WLMessageBox mb(this, _("Empty Password"), _("Please enter your password!"),
-		                    UI::WLMessageBox::MBoxType::kOk);
-		mb.run<UI::Panel::Returncodes>();
-		return;
-	}
 	end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kOk);
 }
 
@@ -97,6 +93,11 @@
 	end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
 }
 
+/// Calles when nickname was changed
+void LoginBox::change_playername() {
+	cb_register->set_state(false);
+}
+
 bool LoginBox::handle_key(bool down, SDL_Keysym code) {
 	if (down) {
 		switch (code.sym) {
@@ -113,3 +114,44 @@
 	}
 	return UI::Panel::handle_key(down, code);
 }
+
+void LoginBox::clicked_register() {
+	if (cb_register->get_state()) {
+		ta_password->set_color(UI_FONT_CLR_DISABLED);
+		eb_password->set_can_focus(false);
+		eb_password->set_text("");
+	} else {
+		ta_password->set_color(UI_FONT_CLR_FG);
+		eb_password->set_can_focus(true);
+		eb_password->focus();
+	}
+}
+
+void LoginBox::verify_input() {
+	// Check if all needed input fields are valid
+	loginbtn->set_enabled(true);
+	eb_nickname->set_tooltip("");
+	eb_password->set_tooltip("");
+	eb_nickname->set_warning(false);
+
+	if (eb_nickname->text().empty()) {
+		eb_nickname->set_warning(true);
+		eb_nickname->set_tooltip(_("Please enter a nickname!"));
+		loginbtn->set_enabled(false);
+	} else if (eb_nickname->text().find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@.+-_") <= eb_nickname->text().size()) {
+			eb_nickname->set_warning(true);
+			eb_nickname->set_tooltip(_("Enter a valid nickname. This value may contain only "
+													  "English letters, numbers, and @ . + - _ characters."));
+			loginbtn->set_enabled(false);
+	}
+
+	if (eb_password->text().empty() && cb_register->get_state()) {
+		eb_password->set_tooltip(_("Please enter your password!"));
+		loginbtn->set_enabled(false);
+	}
+
+	if (eb_password->has_focus() && eb_password->text() == "*****") {
+		eb_password->set_text("");
+	}
+}

=== modified file 'src/wui/login_box.h'
--- src/wui/login_box.h	2019-05-11 18:50:30 +0000
+++ src/wui/login_box.h	2019-05-12 11:08:42 +0000
@@ -29,6 +29,8 @@
 struct LoginBox : public UI::Window {
 	explicit LoginBox(UI::Panel&);
 
+	void think() override;
+
 	std::string get_nickname() {
 		return eb_nickname->text();
 	}
@@ -38,24 +40,25 @@
 	bool registered() {
 		return cb_register->get_state();
 	}
-	bool set_automaticlog() {
-		return cb_auto_log->get_state();
-	}
 
 	/// Handle keypresses
 	bool handle_key(bool down, SDL_Keysym code) override;
 
 private:
+	void change_playername();
 	void clicked_back();
 	void clicked_ok();
+	void clicked_register();
+	void verify_input();
 
+	UI::Button* loginbtn;
+	UI::Button* cancelbtn;
 	UI::EditBox* eb_nickname;
 	UI::EditBox* eb_password;
 	UI::Checkbox* cb_register;
-	UI::Checkbox* cb_auto_log;
 	UI::Textarea* ta_nickname;
 	UI::Textarea* ta_password;
-	UI::MultilineTextarea* pwd_warning;
+	UI::MultilineTextarea* register_account;
 };
 
 #endif  // end of include guard: WL_WUI_LOGIN_BOX_H


Follow ups