From eacf63c7a4c660b38329325c3958bbc63d10ee5c Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 7 Mar 2012 22:56:05 +0300 Subject: Add support for many update hosts (evol server only). --- src/client.cpp | 16 +++++-- src/client.h | 1 + src/gui/logindialog.cpp | 100 +++++++++++++++++++++++++++++++++++++----- src/gui/logindialog.h | 7 ++- src/gui/quitdialog.cpp | 1 + src/gui/register.cpp | 2 +- src/gui/worldselectdialog.cpp | 2 +- src/net/ea/loginhandler.cpp | 1 + src/net/ea/loginhandler.h | 2 + src/net/logindata.h | 2 + src/net/tmwa/loginhandler.cpp | 48 ++++++++++++++++++++ src/net/tmwa/loginhandler.h | 4 ++ src/net/tmwa/network.cpp | 2 + src/net/tmwa/protocol.h | 3 ++ 14 files changed, 174 insertions(+), 17 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 95e49c6aa..98a0fa8fa 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -237,7 +237,7 @@ class LoginListener : public gcn::ActionListener public: void action(const gcn::ActionEvent &) { - Client::setState(STATE_LOGIN); + Client::setState(STATE_PRE_LOGIN); } } loginListener; @@ -945,12 +945,12 @@ int Client::gameExec() mOldState != STATE_CHOOSE_SERVER && Net::getLoginHandler()->isConnected()) { - mState = STATE_LOGIN; + mState = STATE_PRE_LOGIN; } else if (mState == STATE_WORLD_SELECT && mOldState == STATE_UPDATE) { if (Net::getLoginHandler()->getWorlds().size() < 2) - mState = STATE_LOGIN; + mState = STATE_PRE_LOGIN; } else if (mOldState == STATE_START || (mOldState == STATE_GAME && mState != STATE_GAME)) @@ -1038,6 +1038,9 @@ int Client::gameExec() case STATE_CHOOSE_SERVER: logger->log1("State: CHOOSE SERVER"); + loginData.clear(); + serverVersion = 0; + // Allow changing this using a server choice dialog // We show the dialog box only if the command-line // options weren't set. @@ -1064,11 +1067,18 @@ int Client::gameExec() case STATE_CONNECT_SERVER: logger->log1("State: CONNECT SERVER"); + loginData.updateHosts.clear(); mCurrentDialog = new ConnectionDialog( _("Connecting to server"), STATE_SWITCH_SERVER); TranslationManager::loadCurrentLang(); break; + case STATE_PRE_LOGIN: + logger->log1("State: PRE_LOGIN"); +// if (serverVersion < 5) +// setState(STATE_LOGIN); + break; + case STATE_LOGIN: logger->log1("State: LOGIN"); // Don't allow an alpha opacity diff --git a/src/client.h b/src/client.h index 54de27824..000f8749e 100644 --- a/src/client.h +++ b/src/client.h @@ -84,6 +84,7 @@ enum State STATE_START = 0, STATE_CHOOSE_SERVER, STATE_CONNECT_SERVER, + STATE_PRE_LOGIN, STATE_LOGIN, STATE_LOGIN_ATTEMPT, STATE_WORLD_SELECT, // 5 diff --git a/src/gui/logindialog.cpp b/src/gui/logindialog.cpp index cafc4f72c..a139e6b37 100644 --- a/src/gui/logindialog.cpp +++ b/src/gui/logindialog.cpp @@ -82,6 +82,36 @@ public: } }; +class UpdateListModel : public gcn::ListModel +{ + public: + UpdateListModel(LoginData *data) : + gcn::ListModel(), + mLoginData(data) + { + } + + virtual ~UpdateListModel() + { } + + virtual int getNumberOfElements() + { + if (!mLoginData) + return 0; + return mLoginData->updateHosts.size(); + } + + virtual std::string getElementAt(int i) + { + if (!mLoginData || i >= getNumberOfElements() || i < 0) + return _("???"); + + return mLoginData->updateHosts[i]; + } + protected: + LoginData *mLoginData; +}; + LoginDialog::LoginDialog(LoginData *data, std::string serverName, std::string *updateHost): Window(_("Login"), false, nullptr, "login.xml"), @@ -89,12 +119,29 @@ LoginDialog::LoginDialog(LoginData *data, std::string serverName, mUpdateHost(updateHost), mServerName(serverName) { - gcn::Label *serverLabel1 = new Label(_("Server:")); gcn::Label *serverLabel2 = new Label(serverName); serverLabel2->adjustSize(); gcn::Label *userLabel = new Label(_("Name:")); gcn::Label *passLabel = new Label(_("Password:")); + if (mLoginData && mLoginData->updateHosts.size() > 1) + { + mUpdateHostLabel = new Label(strprintf(_("Update host: %s"), + mLoginData->updateHost.c_str())); + mUpdateListModel = new UpdateListModel(mLoginData); + mUpdateHostDropDown = new DropDown(mUpdateListModel, + this, "updateselect"); + const std::string str = serverConfig.getValue("updateHost2", ""); + if (!str.empty()) + mUpdateHostDropDown->setSelectedString(str); + } + else + { + mUpdateHostLabel = nullptr; + mUpdateListModel = nullptr; + mUpdateHostDropDown = nullptr; + } + mCustomUpdateHost = new CheckBox(_("Custom update host"), mLoginData->updateType & LoginData::Upd_Custom, this, "customhost"); @@ -135,20 +182,30 @@ LoginDialog::LoginDialog(LoginData *data, std::string serverName, place(0, 0, serverLabel1); place(1, 0, serverLabel2, 8); place(0, 1, userLabel); - place(0, 2, passLabel); place(1, 1, mUserField, 8); + place(0, 2, passLabel); place(1, 2, mPassField, 8); place(0, 6, mUpdateTypeLabel, 1); place(1, 6, mUpdateTypeDropDown, 8); - place(0, 7, mCustomUpdateHost, 9); - place(0, 8, mUpdateHostText, 9); - place(0, 9, mKeepCheck, 9); - place(0, 10, mRegisterButton).setHAlign(LayoutCell::LEFT); - place(2, 10, mServerButton); - place(3, 10, mLoginButton); + int n = 7; + if (mUpdateHostLabel) + { + place(0, 7, mUpdateHostLabel, 9); + place(0, 8, mUpdateHostDropDown, 9); + n += 2; + } + place(0, n, mCustomUpdateHost, 9); + place(0, n + 1, mUpdateHostText, 9); + place(0, n + 2, mKeepCheck, 9); + place(0, n + 3, mRegisterButton).setHAlign(LayoutCell::LEFT); + place(2, n + 3, mServerButton); + place(3, n + 3, mLoginButton); addKeyListener(this); - setContentSize(300, 200); + if (mUpdateHostLabel) + setContentSize(300, 250); + else + setContentSize(300, 200); center(); setVisible(true); @@ -196,6 +253,22 @@ void LoginDialog::action(const gcn::ActionEvent &event) *mUpdateHost = ""; } } + else if (mUpdateHostDropDown) + { + const std::string str = mUpdateHostDropDown->getSelectedString(); + serverConfig.setValue("updateHost2", str); + if (!str.empty() && checkPath(str)) + { + mLoginData->updateHost = str; + *mUpdateHost = str; + } + else + { + mLoginData->updateHost = ""; + *mUpdateHost = ""; + } + } + mLoginData->updateType = updateType; serverConfig.setValue("updateType", updateType); @@ -228,6 +301,11 @@ void LoginDialog::action(const gcn::ActionEvent &event) { mUpdateHostText->setVisible(mCustomUpdateHost->isSelected()); } + else if (event.getId() == "updateselect") + { + mCustomUpdateHost->setSelected(false); + mUpdateHostText->setVisible(false); + } } void LoginDialog::keyPressed(gcn::KeyEvent &keyEvent) @@ -245,6 +323,6 @@ void LoginDialog::keyPressed(gcn::KeyEvent &keyEvent) bool LoginDialog::canSubmit() const { return !mUserField->getText().empty() && - !mPassField->getText().empty() && - Client::getState() == STATE_LOGIN; + !mPassField->getText().empty() && + Client::getState() == STATE_LOGIN; } diff --git a/src/gui/logindialog.h b/src/gui/logindialog.h index 08799b1c2..53149fe0d 100644 --- a/src/gui/logindialog.h +++ b/src/gui/logindialog.h @@ -32,7 +32,9 @@ #include #include +class DropDown; class LoginData; +class UpdateListModel; class UpdateTypeModel; /** @@ -78,12 +80,15 @@ class LoginDialog : public Window, public gcn::ActionListener, gcn::TextField *mPassField; gcn::CheckBox *mKeepCheck; gcn::Label *mUpdateTypeLabel; - gcn::DropDown *mUpdateTypeDropDown; + gcn::Label *mUpdateHostLabel; + DropDown *mUpdateTypeDropDown; gcn::Button *mServerButton; gcn::Button *mLoginButton; gcn::Button *mRegisterButton; gcn::CheckBox *mCustomUpdateHost; gcn::TextField *mUpdateHostText; + UpdateListModel *mUpdateListModel; + DropDown *mUpdateHostDropDown; LoginData *mLoginData; std::string *mUpdateHost; diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp index dff5a570c..a0f734adf 100644 --- a/src/gui/quitdialog.cpp +++ b/src/gui/quitdialog.cpp @@ -64,6 +64,7 @@ QuitDialog::QuitDialog(QuitDialog** pointerToMe): if (state == STATE_CHOOSE_SERVER || state == STATE_CONNECT_SERVER || state == STATE_LOGIN || + state == STATE_PRE_LOGIN || state == STATE_LOGIN_ATTEMPT || state == STATE_UPDATE || state == STATE_LOAD_DATA) diff --git a/src/gui/register.cpp b/src/gui/register.cpp index bf0cb299e..4f696dc9d 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -154,7 +154,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "cancel") { - Client::setState(STATE_LOGIN); + Client::setState(STATE_PRE_LOGIN); } else if (event.getId() == "register" && canSubmit()) { diff --git a/src/gui/worldselectdialog.cpp b/src/gui/worldselectdialog.cpp index 19e6b81f7..26fd19208 100644 --- a/src/gui/worldselectdialog.cpp +++ b/src/gui/worldselectdialog.cpp @@ -132,7 +132,7 @@ void WorldSelectDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "login") { - Client::setState(STATE_LOGIN); + Client::setState(STATE_PRE_LOGIN); } } diff --git a/src/net/ea/loginhandler.cpp b/src/net/ea/loginhandler.cpp index 39a920f03..560893a4f 100644 --- a/src/net/ea/loginhandler.cpp +++ b/src/net/ea/loginhandler.cpp @@ -151,6 +151,7 @@ void LoginHandler::processUpdateHost(Net::MessageIn &msg) len = msg.readInt16() - 4; mUpdateHost = msg.readString(len); + if (!checkPath(mUpdateHost)) { mUpdateHost = ""; diff --git a/src/net/ea/loginhandler.h b/src/net/ea/loginhandler.h index 555de6385..c3bd2a4e8 100644 --- a/src/net/ea/loginhandler.h +++ b/src/net/ea/loginhandler.h @@ -79,6 +79,8 @@ class LoginHandler : public Net::LoginHandler virtual void processUpdateHost(Net::MessageIn &msg); + virtual void processUpdateHost2(Net::MessageIn &msg) = 0; + virtual void processLoginData(Net::MessageIn &msg); virtual void processLoginError(Net::MessageIn &msg); diff --git a/src/net/logindata.h b/src/net/logindata.h index e5d3fc97a..0f41b02ae 100644 --- a/src/net/logindata.h +++ b/src/net/logindata.h @@ -59,6 +59,7 @@ class LoginData std::string password; std::string newPassword; std::string updateHost; + std::vector updateHosts; std::string lastLogin; int updateType; @@ -79,6 +80,7 @@ class LoginData password.clear(); newPassword.clear(); updateHost.clear(); + updateHosts.clear(); updateType = Upd_Normal; email.clear(); captchaResponse.clear(); diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index 3b53bbf7c..a2c5034d6 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -32,6 +32,7 @@ #include "net/tmwa/protocol.h" #include "utils/gettext.h" +#include "utils/paths.h" #include "debug.h" @@ -47,6 +48,7 @@ LoginHandler::LoginHandler() static const Uint16 _messages[] = { SMSG_UPDATE_HOST, + SMSG_UPDATE_HOST2, SMSG_LOGIN_DATA, SMSG_LOGIN_ERROR, SMSG_CHAR_PASSWORD_RESPONSE, @@ -73,6 +75,10 @@ void LoginHandler::handleMessage(Net::MessageIn &msg) processUpdateHost(msg); break; + case SMSG_UPDATE_HOST2: + processUpdateHost2(msg); + break; + case SMSG_LOGIN_DATA: processLoginData(msg); break; @@ -144,6 +150,13 @@ ServerInfo *LoginHandler::getCharServer() return &charServer; } +void LoginHandler::requestUpdateHosts() +{ + MessageOut outMsg(CMSG_SEND_CLIENT_INFO); + outMsg.writeInt8(CLIENT_PROTOCOL_VERSION); + outMsg.writeInt8(0); // unused +} + void LoginHandler::processServerVersion(Net::MessageIn &msg) { char b1 = msg.readInt8(); // -1 @@ -156,6 +169,8 @@ void LoginHandler::processServerVersion(Net::MessageIn &msg) mRegistrationEnabled = options; msg.skip(2); // 0 unused serverVersion = msg.readInt8(); + if (serverVersion >= 5) + requestUpdateHosts(); } else { @@ -163,9 +178,42 @@ void LoginHandler::processServerVersion(Net::MessageIn &msg) mRegistrationEnabled = options; serverVersion = 0; } + logger->log("Server version: %d", serverVersion); + if (serverVersion < 5) + { + if (Client::getState() != STATE_LOGIN) + Client::setState(STATE_LOGIN); + } // Leave this last mVersionResponse = true; } +void LoginHandler::processUpdateHost2(Net::MessageIn &msg) +{ + int len; + + len = msg.readInt16() - 4; + std::string updateHost = msg.readString(len); + + splitToStringVector(loginData.updateHosts, updateHost, '|'); + std::vector::iterator it = loginData.updateHosts.begin(); + std::vector::iterator it_end = loginData.updateHosts.end(); + for (; it != it_end; ++ it) + { + if (!checkPath(*it)) + { + logger->log1("Warning: incorrect update server name"); + loginData.updateHosts.clear(); + break; + } + } + + logger->log("Received update hosts \"%s\" from login server.", + updateHost.c_str()); + + if (Client::getState() == STATE_PRE_LOGIN) + Client::setState(STATE_LOGIN); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/loginhandler.h b/src/net/tmwa/loginhandler.h index e2b8beec7..b27b0af77 100644 --- a/src/net/tmwa/loginhandler.h +++ b/src/net/tmwa/loginhandler.h @@ -67,6 +67,10 @@ class LoginHandler : public MessageHandler, public Ea::LoginHandler void processServerVersion(Net::MessageIn &msg); + void requestUpdateHosts(); + + void processUpdateHost2(Net::MessageIn &msg); + private: void sendLoginRegister(const std::string &username, const std::string &password); diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index 5d5a84a64..0e0c09d5f 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -331,6 +331,8 @@ MessageIn Network::getNextMessage() int len; if (msgId == SMSG_SERVER_VERSION_RESPONSE) len = 10; + else if (msgId == SMSG_UPDATE_HOST2) + len = -1; else len = packet_lengths[msgId]; diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 256f1dce4..130268b82 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -338,4 +338,7 @@ enum #define SMSG_NPC_COMMAND 0x0212 #define CMSG_SET_STATUS 0x0213 +#define CMSG_SEND_CLIENT_INFO 0x7533 +#define SMSG_UPDATE_HOST2 0x7534 + #endif -- cgit v1.2.3-70-g09d2