diff options
author | Eugenio Favalli <elvenprogrammer@gmail.com> | 2005-12-30 16:27:24 +0000 |
---|---|---|
committer | Eugenio Favalli <elvenprogrammer@gmail.com> | 2005-12-30 16:27:24 +0000 |
commit | ea653b2e9e1b46a07440833f96b3d2b788592c61 (patch) | |
tree | 252bb23d2064d14d4aa0796aa159f94873cb6419 /src | |
parent | 57d63f1dd5df0beb1a3d81f014686a2f80dfe7fc (diff) | |
download | mana-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.gz mana-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.bz2 mana-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.xz mana-ea653b2e9e1b46a07440833f96b3d2b788592c61.zip |
Added a new item, improved smooth login sequence, added a registration window (a lot of duplicated code to be removed).
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/gui/char_select.cpp | 2 | ||||
-rw-r--r-- | src/gui/char_server.cpp | 2 | ||||
-rw-r--r-- | src/gui/login.cpp | 130 | ||||
-rw-r--r-- | src/gui/login.h | 45 | ||||
-rw-r--r-- | src/gui/register.cpp | 378 | ||||
-rw-r--r-- | src/gui/register.h | 90 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/main.h | 1 | ||||
-rw-r--r-- | src/net/network.cpp | 25 | ||||
-rw-r--r-- | src/net/network.h | 3 |
11 files changed, 558 insertions, 126 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a8f0dce5..6a990a9f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,8 @@ tmw_SOURCES = graphic/spriteset.cpp \ gui/progressbar.h \ gui/radiobutton.cpp \ gui/radiobutton.h \ + gui/register.cpp \ + gui/register.h \ gui/requesttrade.cpp \ gui/requesttrade.h \ gui/scrollarea.cpp \ diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index b1f649ec..734ed766 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -291,7 +291,7 @@ void CharSelectDialog::logic() if (mStatus == 1) { - if (in_size > 2) + if (packetReady()) { checkCharSelect(); } diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp index 6766092c..52b26b9f 100644 --- a/src/gui/char_server.cpp +++ b/src/gui/char_server.cpp @@ -128,6 +128,8 @@ ServerSelectDialog::logic() mStatus = NET_DATA; break; case NET_DATA: + // TODO: cannot substitute with packetReady() because of eAthena + // sending 4 unknown bytes. if (in_size > 6) { skip(4); diff --git a/src/gui/login.cpp b/src/gui/login.cpp index a8e906e1..ad469d22 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -39,52 +39,29 @@ #include "checkbox.h" #include "passwordfield.h" #include "textfield.h" -#include "ok_dialog.h" #include "../net/messagein.h" #include "../net/messageout.h" #include "../net/network.h" -OkDialog *wrongLoginNotice = NULL; SERVER_INFO **server_info; -WrongUsernameNoticeListener wrongUsernameNoticeListener; -WrongPasswordNoticeListener wrongPasswordNoticeListener; - void -WrongPasswordNoticeListener::setLoginDialog(LoginDialog *loginDialog) +WrongDataNoticeListener::setTarget(gcn::TextField *textField) { - mLoginDialog = loginDialog; + this->target = textField; } void -WrongPasswordNoticeListener::action(const std::string &eventId) +WrongDataNoticeListener::action(const std::string &eventId) { if (eventId == "ok") { - // Reset the password and put the caret ready to retype it. - mLoginDialog->passField->setText(""); - mLoginDialog->passField->setCaretPosition(0); - mLoginDialog->passField->requestFocus(); - wrongLoginNotice = NULL; - } -} - -void -WrongUsernameNoticeListener::setLoginDialog(LoginDialog *loginDialog) -{ - mLoginDialog = loginDialog; -} - -void -WrongUsernameNoticeListener::action(const std::string &eventId) -{ - if (eventId == "ok") - { - // Set the focus on the username Field - mLoginDialog->userField->setCaretPosition(LEN_MAX_USERNAME - 1); - mLoginDialog->userField->requestFocus(); - wrongLoginNotice = NULL; + // Reset the field + target->setText(""); + target->setCaretPosition(0); + target->requestFocus(); + //wrongLoginNotice = NULL; } } @@ -165,8 +142,16 @@ LoginDialog::LoginDialog(): serverField->setText(config.getValue("host", "")); - wrongUsernameNoticeListener.setLoginDialog(this); - wrongPasswordNoticeListener.setLoginDialog(this); + wrongDataNoticeListener = NULL; + wrongLoginNotice = NULL; +} + +LoginDialog::~LoginDialog() +{ + if (wrongLoginNotice) + { + delete wrongLoginNotice; + } } void @@ -193,9 +178,15 @@ LoginDialog::action(const std::string& eventId) // Check login if (user.length() == 0) { + wrongDataNoticeListener = new WrongDataNoticeListener(); + wrongDataNoticeListener->setTarget(this->passField); + if (wrongLoginNotice) + { + delete wrongLoginNotice; + } wrongLoginNotice = new OkDialog("Error", - "Enter your username first", - &wrongUsernameNoticeListener); + "Enter your username first", + wrongDataNoticeListener); } else { @@ -212,70 +203,7 @@ LoginDialog::action(const std::string& eventId) } else if (eventId == "register") { - const std::string user = userField->getText(); - logger->log("LoginDialog::register Username is %s", user.c_str()); - - // Store config settings - config.setValue("remember", keepCheck->isMarked()); - if (keepCheck->isMarked()) { - config.setValue("username", user); - } else { - config.setValue("username", ""); - } - - std::stringstream errorMsg; - bool error = false; - - // Check login - if (user.length() == 0) - { - // No username - errorMsg << "Enter your username first."; - } - else if (user.length() < LEN_MIN_USERNAME) - { - // Name too short - errorMsg << "The username needs to be at least " - << LEN_MIN_USERNAME - << " characters long."; - } - else if (user.length() > LEN_MAX_USERNAME - 1 ) - { - // Name too long - errorMsg << "The username needs to be less than " - << LEN_MAX_USERNAME - << " characters long."; - } - else if (passField->getText().length() < LEN_MIN_PASSWORD) - { - // Pass too short - errorMsg << "The password needs to be at least " - << LEN_MIN_PASSWORD - << " characters long."; - } - else if (passField->getText().length() > LEN_MAX_PASSWORD - 1 ) - { - // Pass too long - errorMsg << "The password needs to be less than " - << LEN_MAX_PASSWORD - << " characters long."; - } - - if (error) - { - wrongLoginNotice = new OkDialog("Error", errorMsg.str(), - &wrongPasswordNoticeListener); - } - else - { - // No errors detected, register the new user. - const std::string host(config.getValue("host", "animesites.de")); - short port = (short)config.getValue("port", 0); - // Attempt to connect to login server - openConnection(host.c_str(), port); - mStatus = NET_CONNECTING; - registration = true; - } + state = REGISTER_STATE; } } @@ -295,9 +223,7 @@ LoginDialog::logic() logger->log("Connection closed"); break; case NET_DATA: - // TODO: this is a very quick hack, we should implement something - // like a bool completePacket() in network functions. - if (in_size > 2) + if (packetReady()) { checkLogin(); closeConnection(); diff --git a/src/gui/login.h b/src/gui/login.h index 9fd866aa..ca50df96 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -28,9 +28,23 @@ #include <guichan/actionlistener.hpp> #include <SDL_events.h> +#include "ok_dialog.h" #include "window.h" #include "../guichanfwd.h" +class LoginDialog; + +/** + * Listener used for handling wrong data. + */ +class WrongDataNoticeListener : public gcn::ActionListener { + public: + void setTarget(gcn::TextField *textField); + void action(const std::string &eventId); + private: + gcn::TextField *target; +}; + /** * The login dialog. * @@ -44,6 +58,11 @@ class LoginDialog : public Window, public gcn::ActionListener { * @see Window::Window */ LoginDialog(); + + /** + * Destructor + */ + ~LoginDialog(); /** * Called when receiving actions from the widgets. @@ -74,32 +93,12 @@ class LoginDialog : public Window, public gcn::ActionListener { void attemptLogin(const std::string& user, const std::string& pass); void checkLogin(); + + WrongDataNoticeListener *wrongDataNoticeListener; + OkDialog *wrongLoginNotice; }; /** - * Listener used for handling wrong password. - */ -class WrongPasswordNoticeListener : public gcn::ActionListener { - public: - void setLoginDialog(LoginDialog *loginDialog); - void action(const std::string &eventId); - private: - LoginDialog *mLoginDialog; -}; - -/** - * Listener used for handling wrong username. - */ -class WrongUsernameNoticeListener : public gcn::ActionListener { - public: - void setLoginDialog(LoginDialog *loginDialog); - void action(const std::string &eventId); - private: - LoginDialog *mLoginDialog; -}; - - -/** * Handle input */ void loginInputHandler(SDL_KeyboardEvent *keyEvent); diff --git a/src/gui/register.cpp b/src/gui/register.cpp new file mode 100644 index 00000000..3e03b59e --- /dev/null +++ b/src/gui/register.cpp @@ -0,0 +1,378 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "register.h" + +#include <string> +#include <sstream> +#include <SDL.h> + +#include <guichan/widgets/label.hpp> + +#include "../main.h" +#include "../configuration.h" +#include "../graphics.h" +#include "../log.h" +#include "../serverinfo.h" + +#include "button.h" +#include "checkbox.h" +#include "passwordfield.h" +#include "radiobutton.h" +#include "textfield.h" +#include "ok_dialog.h" + +#include "../net/messagein.h" +#include "../net/messageout.h" +#include "../net/network.h" + +//OkDialog *wrongLoginNotice = NULL; +extern SERVER_INFO **server_info; + +RegisterDialog::RegisterDialog(): + Window("Register"), mStatus(NET_IDLE) +{ + userLabel = new gcn::Label("Name:"); + passwordLabel = new gcn::Label("Password:"); + confirmLabel = new gcn::Label("Confirm:"); + serverLabel = new gcn::Label("Server:"); + userField = new TextField("player"); + passwordField = new PasswordField(); + confirmField = new PasswordField(); + serverField = new TextField(); + maleButton = new RadioButton("Male", "sex", true); + maleButton->setEnabled(false); + femaleButton = new RadioButton("Female", "sex", false); + femaleButton->setEnabled(false); + registerButton = new Button("Register"); + cancelButton = new Button("Cancel"); + + int width = 200; + int height = 150; + setContentSize(width, height); + + userField->setPosition(65, 5); + userField->setWidth(130); + passwordField->setPosition( + 65, userField->getY() + userField->getHeight() + 7); + passwordField->setWidth(130); + confirmField->setPosition( + 65, passwordField->getY() + passwordField->getHeight() + 7); + confirmField->setWidth(130); + serverField->setPosition( + 65, 23 + confirmField->getY() + confirmField->getHeight() + 7); + serverField->setWidth(130); + + userLabel->setPosition(5, userField->getY() + 1); + passwordLabel->setPosition(5, passwordField->getY() + 1); + confirmLabel->setPosition(5, confirmField->getY() + 1); + serverLabel->setPosition(5, serverField->getY() + 1); + + femaleButton->setPosition(width - femaleButton->getWidth() - 10, + confirmField->getY() + confirmField->getHeight() + 7); + maleButton->setPosition(femaleButton->getX() - maleButton->getWidth() - 5, + femaleButton->getY()); + + registerButton->setPosition(5, height - registerButton->getHeight() - 5); + cancelButton->setPosition(10 + registerButton->getWidth(), + registerButton->getY()); + + + /*userField->setEventId("register"); + passwordField->setEventId("register"); + confirmField->setEventId("register"); + serverField->setEventId("register");*/ + registerButton->setEventId("register"); + cancelButton->setEventId("cancel"); + + + /*userField->addActionListener(this); + passwordField->addActionListener(this); + confirmField->addActionListener(this); + serverField->addActionListener(this);*/ + registerButton->addActionListener(this); + cancelButton->addActionListener(this); + + add(userLabel); + add(passwordLabel); + add(serverLabel); + add(confirmLabel); + add(userField); + add(passwordField); + add(confirmField); + add(serverField); + add(maleButton); + add(femaleButton); + add(registerButton); + add(cancelButton); + + setLocationRelativeTo(getParent()); + userField->requestFocus(); + userField->setCaretPosition(userField->getText().length()); + + serverField->setText(config.getValue("host", "")); + + wrongDataNoticeListener = NULL; + wrongRegisterNotice = NULL; +} + +void +RegisterDialog::action(const std::string& eventId) +{ + if (eventId == "cancel") + { + state = EXIT_STATE; + } + else if (eventId == "register") + { + const std::string user = userField->getText(); + logger->log("RegisterDialog::register Username is %s", user.c_str()); + + std::stringstream errorMsg; + int error = 0; + + // Check login + if (user.length() == 0) + { + // No username + errorMsg << "Enter your username first."; + error = 1; + } + else if (user.length() < LEN_MIN_USERNAME) + { + // Name too short + errorMsg << "The username needs to be at least " + << LEN_MIN_USERNAME + << " characters long."; + error = 1; + } + else if (user.length() > LEN_MAX_USERNAME - 1 ) + { + // Name too long + errorMsg << "The username needs to be less than " + << LEN_MAX_USERNAME + << " characters long."; + error = 1; + } + else if (passwordField->getText().length() < LEN_MIN_PASSWORD) + { + // Pass too short + errorMsg << "The password needs to be at least " + << LEN_MIN_PASSWORD + << " characters long."; + error = 2; + } + else if (passwordField->getText().length() > LEN_MAX_PASSWORD - 1 ) + { + // Pass too long + errorMsg << "The password needs to be less than " + << LEN_MAX_PASSWORD + << " characters long."; + error = 2; + } + else if (passwordField->getText() != confirmField->getText()) + { + // Password does not match with the confirmation one + errorMsg << "Passwords do not match."; + error = 2; + } + + if (error > 0) + { + wrongDataNoticeListener = new WrongDataNoticeListener(); + if (error == 1) + { + wrongDataNoticeListener->setTarget(this->userField); + } + else if (error == 2) + { + wrongDataNoticeListener->setTarget(this->passwordField); + // Reset password confirmation + confirmField->setText(""); + } + + if (wrongRegisterNotice) + { + delete wrongRegisterNotice; + } + wrongRegisterNotice = new OkDialog("Error", errorMsg.str(), + wrongDataNoticeListener); + } + else + { + // No errors detected, register the new user. + const std::string host(config.getValue("host", "animesites.de")); + short port = (short)config.getValue("port", 0); + // Attempt to connect to login server + openConnection(host.c_str(), port); + mStatus = NET_CONNECTING; + } + } +} + +void +RegisterDialog::logic() +{ + switch (mStatus) + { + case NET_CONNECTING: + mStatus = pollConnection(); + break; + case NET_ERROR: + logger->log("Register::Unable to connect"); + errorMessage = "Unable to connect to login server"; + state = ERROR_STATE; + closeConnection(); + logger->log("Connection closed"); + break; + case NET_DATA: + if (packetReady()) + { + checkRegistration(); + closeConnection(); + } + else + { + flush(); + } + break; + case NET_CONNECTED: + logger->log("Connected..."); + std::string user = userField->getText(); + const std::string password = passwordField->getText(); + if (femaleButton->isMarked()) + { + user += "_F"; + } + else + { + user += "_M"; + } + attemptRegistration(user, password); + mStatus = NET_DATA; + break; + } +} + +void +RegisterDialog::attemptRegistration(const std::string& user, + const std::string& pass) +{ + // Send login infos + MessageOut outMsg; + outMsg.writeInt16(0x0064); + outMsg.writeInt32(0); // client version + outMsg.writeString(user, 24); + outMsg.writeString(pass, 24); + outMsg.writeInt8(0); // unknown +} + +void +RegisterDialog::checkRegistration() +{ + // Receive reply + MessageIn msg = get_next_message(); + if (state == ERROR_STATE) + { + return; + } + + // Login ok + if (msg.getId() == 0x0069) + { + // Skip the length word + msg.skip(2); + + n_server = (msg.getLength() - 47) / 32; + server_info = (SERVER_INFO**)malloc(sizeof(SERVER_INFO*) * n_server); + + session_ID1 = msg.readInt32(); + account_ID = msg.readInt32(); + session_ID2 = msg.readInt32(); + msg.skip(30); // unknown + sex = msg.readInt8(); + + for (int i = 0; i < n_server; i++) + { + server_info[i] = new SERVER_INFO; + + server_info[i]->address = msg.readInt32(); + server_info[i]->port = msg.readInt16(); + server_info[i]->name = msg.readString(20); + server_info[i]->online_users = msg.readInt32(); + msg.skip(2); // unknown + + logger->log("Network: Server: %s (%s:%d)", + server_info[i]->name.c_str(), + iptostring(server_info[i]->address), + server_info[i]->port); + } + skip(msg.getLength()); + + state = CHAR_SERVER_STATE; + } + else if (msg.getId() == 0x006a) + { + int loginError = msg.readInt8(); + logger->log("Login::error code: %i", loginError); + + switch (loginError) { + case 0: + errorMessage = "Unregistered ID"; + break; + case 1: + errorMessage = "Wrong password"; + break; + case 2: + errorMessage = "Account expired"; + break; + case 3: + errorMessage = "Rejected from server"; + break; + case 4: + errorMessage = "You have been blocked by the GM Team"; + break; + case 9: + errorMessage = "This account is already logged in"; + break; + } + skip(msg.getLength()); + state = ERROR_STATE; + } + else { + skip(msg.getLength()); + logger->log("Login::Unknown error"); + errorMessage = "Unknown error"; + state = ERROR_STATE; + } + // Todo: add other packets, also encrypted +} + +void +registerInputHandler(SDL_KeyboardEvent *keyEvent) +{ + if (keyEvent->keysym.sym == SDLK_ESCAPE) + { + state = EXIT_STATE; + } +} diff --git a/src/gui/register.h b/src/gui/register.h new file mode 100644 index 00000000..25a867bd --- /dev/null +++ b/src/gui/register.h @@ -0,0 +1,90 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_REGISTER_H +#define _TMW_REGISTER_H + +#include <iosfwd> +#include <guichan/actionlistener.hpp> +#include <SDL_events.h> + +#include "window.h" +#include "login.h" +#include "../guichanfwd.h" + +/** + * The login dialog. + * + * \ingroup Interface + */ +class RegisterDialog : public Window, public gcn::ActionListener { + public: + /** + * Constructor + * + * @see Window::Window + */ + RegisterDialog(); + + /** + * Called when receiving actions from the widgets. + */ + void action(const std::string& eventId); + + /** + * Updates dialog logic. + */ + void logic(); + + // Made them public to have the possibility to request focus + // from external functions. + gcn::TextField *userField; + gcn::TextField *passwordField; + gcn::TextField *confirmField; + + private: + gcn::Label *userLabel; + gcn::Label *passwordLabel; + gcn::Label *confirmLabel; + gcn::Label *serverLabel; + gcn::TextField *serverField; + gcn::Button *registerButton; + gcn::Button *cancelButton; + gcn::RadioButton *maleButton; + gcn::RadioButton *femaleButton; + int mStatus; + + void attemptRegistration(const std::string& user, + const std::string& pass); + void checkRegistration(); + + WrongDataNoticeListener *wrongDataNoticeListener; + OkDialog *wrongRegisterNotice; +}; + +/** + * Handle input + */ +void registerInputHandler(SDL_KeyboardEvent *keyEvent); + +#endif diff --git a/src/main.cpp b/src/main.cpp index 7daba4bf..3121f57f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,6 +56,7 @@ #include "gui/gui.h" #include "gui/login.h" #include "gui/ok_dialog.h" +#include "gui/register.h" #include "gui/updatewindow.h" #include "resources/image.h" @@ -465,6 +466,11 @@ int main(int argc, char *argv[]) currentDialog = new LoginDialog(); inputHandler = loginInputHandler; break; + case REGISTER_STATE: + logger->log("State: REGISTER"); + currentDialog = new RegisterDialog(); + inputHandler = loginInputHandler; + break; case CHAR_SERVER_STATE: logger->log("State: CHAR_SERVER"); currentDialog = new ServerSelectDialog(); @@ -44,6 +44,7 @@ class Sound; enum { EXIT_STATE, LOGIN_STATE, + REGISTER_STATE, CHAR_SERVER_STATE, CHAR_SELECT_STATE, CHAR_NEW_STATE, diff --git a/src/net/network.cpp b/src/net/network.cpp index e94acee7..4504a944 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -332,6 +332,31 @@ unsigned short readWord(int pos) #endif } +bool packetReady() +{ + bool ret = false; + if (in_size >= 2) + { + int length = packet_lengths[readWord(0)]; + if (length == -1) + { + if (in_size >= 4) + { + length = readWord(2); + if (in_size >= length) + { + ret = true; + } + } + } + else if (in_size >= length) + { + ret = true; + } + } + return ret; +} + MessageIn get_next_message() { diff --git a/src/net/network.h b/src/net/network.h index 50638683..db95d7c3 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -47,6 +47,9 @@ void closeConnection(); /** Send and receive data waiting in the buffers */ void flush(); +/** Check if a packet is complete */ +bool packetReady(); + /** * Returns the next arriving message, waiting for it if necessary. */ |