summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugenio Favalli <elvenprogrammer@gmail.com>2005-12-30 16:27:24 +0000
committerEugenio Favalli <elvenprogrammer@gmail.com>2005-12-30 16:27:24 +0000
commitea653b2e9e1b46a07440833f96b3d2b788592c61 (patch)
tree252bb23d2064d14d4aa0796aa159f94873cb6419 /src
parent57d63f1dd5df0beb1a3d81f014686a2f80dfe7fc (diff)
downloadmana-client-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.gz
mana-client-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.bz2
mana-client-ea653b2e9e1b46a07440833f96b3d2b788592c61.tar.xz
mana-client-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.am2
-rw-r--r--src/gui/char_select.cpp2
-rw-r--r--src/gui/char_server.cpp2
-rw-r--r--src/gui/login.cpp130
-rw-r--r--src/gui/login.h45
-rw-r--r--src/gui/register.cpp378
-rw-r--r--src/gui/register.h90
-rw-r--r--src/main.cpp6
-rw-r--r--src/main.h1
-rw-r--r--src/net/network.cpp25
-rw-r--r--src/net/network.h3
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();
diff --git a/src/main.h b/src/main.h
index b5c5155d..69d54a5a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -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.
*/