diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2007-02-04 21:52:17 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2007-02-04 21:52:17 +0000 |
commit | cade1ba618bd1883e044999a0cbda201f1f76dd4 (patch) | |
tree | 978d8e0d97b0f5b0eec3a77a8d25e54b870ed786 | |
parent | 9c0421f5926d22a44c978fff683c51748a19e976 (diff) | |
download | manaserv-cade1ba618bd1883e044999a0cbda201f1f76dd4.tar.gz manaserv-cade1ba618bd1883e044999a0cbda201f1f76dd4.tar.bz2 manaserv-cade1ba618bd1883e044999a0cbda201f1f76dd4.tar.xz manaserv-cade1ba618bd1883e044999a0cbda201f1f76dd4.zip |
Added support for switching character by reconnecting to the account server and
fixed the issue where a client is not logged in after registering (patch by
Rogier Polak).
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | src/account-server/accounthandler.cpp | 141 | ||||
-rw-r--r-- | src/account-server/accounthandler.hpp | 3 | ||||
-rw-r--r-- | src/account-server/dalstorage.cpp | 89 | ||||
-rw-r--r-- | src/account-server/dalstorage.hpp | 10 | ||||
-rw-r--r-- | src/account-server/serverhandler.cpp | 23 | ||||
-rw-r--r-- | src/account-server/storage.hpp | 10 | ||||
-rw-r--r-- | src/chat-server/chathandler.cpp | 18 | ||||
-rw-r--r-- | src/defines.h | 11 | ||||
-rw-r--r-- | src/game-server/accountconnection.cpp | 10 | ||||
-rw-r--r-- | src/game-server/accountconnection.hpp | 6 | ||||
-rw-r--r-- | src/game-server/gamehandler.cpp | 28 | ||||
-rw-r--r-- | src/playerdata.cpp | 5 | ||||
-rw-r--r-- | src/playerdata.hpp | 16 |
14 files changed, 363 insertions, 22 deletions
@@ -1,3 +1,18 @@ +2007-02-04 Rogier Polak <rogier_polak@users.sourceforge.net> + + * src/chat-server/chathandler.cpp, + src/account-server/accounthandler.hpp, + src/account-server/serverhandler.cpp, + src/account-server/dalstorage.cpp, src/account-server/storage.hpp, + src/account-server/accounthandler.cpp, + src/account-server/dalstorage.hpp, src/defines.h, src/playerdata.cpp, + src/playerdata.hpp, src/game-server/gamehandler.cpp, + src/game-server/accountconnection.cpp, + src/game-server/accountconnection.hpp: Added support for switching + character by reconnecting to the account server and fixed the issue + where a client is not logged in after registering (patch applied by + Bjørn Lindeijer). + 2007-02-01 Rogier Polak <rogier_polak@users.sourceforge.net> * src/account-server/main-account.cpp, diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index 3b0663af..c6a086ea 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -21,9 +21,11 @@ * $Id$ */ +#include "account-server/accounthandler.hpp" + +#include "defines.h" #include "configuration.h" #include "point.h" -#include "account-server/accounthandler.hpp" #include "account-server/account.hpp" #include "account-server/accountclient.hpp" #include "account-server/serverhandler.hpp" @@ -36,6 +38,27 @@ #include "utils/logger.h" #include "utils/stringfilter.h" +// TODO: Implement a class to handle these tokens more generally + +typedef std::map< std::string, AccountClient* > AccountPendingClients; +typedef std::map< std::string, int > AccountPendingReconnects; + +/** + * Client is faster then game server + */ +static AccountPendingClients pendingClients; + +/** + * Game server is faster then client + */ +static AccountPendingReconnects pendingReconnects; + +void +registerAccountReconnect(int accountID, const std::string& magic_token); + +void +handleReconnectedAccount(AccountClient &computer, int accountID); + bool AccountHandler::startListen(enet_uint16 port) { @@ -81,23 +104,33 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) switch (message.getId()) { case PAMSG_LOGIN: + LOG_DEBUG("Received msg ... PAMSG_LOGIN"); handleLoginMessage(computer, message); break; case PAMSG_LOGOUT: + LOG_DEBUG("Received msg ... PAMSG_LOGOUT"); handleLogoutMessage(computer); break; + case PAMSG_RECONNECT: + LOG_DEBUG("Received msg ... PAMSG_RECONNECT"); + handleReconnectMessage(computer, message); + break; + case PAMSG_REGISTER: + LOG_DEBUG("Received msg ... PAMSG_REGISTER"); handleRegisterMessage(computer, message); break; case PAMSG_UNREGISTER: + LOG_DEBUG("Received msg ... PAMSG_UNREGISTER"); handleUnregisterMessage(computer, message); break; case PAMSG_EMAIL_CHANGE: { + LOG_DEBUG("Received msg ... PAMSG_EMAIL_CHANGE"); result.writeShort(APMSG_EMAIL_CHANGE_RESPONSE); if (computer.getAccount().get() == NULL) { @@ -128,6 +161,7 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) case PAMSG_EMAIL_GET: { + LOG_DEBUG("Received msg ... PAMSG_EMAIL_GET"); result.writeShort(APMSG_EMAIL_GET_RESPONSE); if (computer.getAccount().get() == NULL) { result.writeByte(ERRMSG_NO_LOGIN); @@ -142,15 +176,18 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) break; case PAMSG_PASSWORD_CHANGE: + LOG_DEBUG("Received msg ... PAMSG_PASSWORD_CHANGE"); handlePasswordChangeMessage(computer, message); break; case PAMSG_CHAR_CREATE: + LOG_DEBUG("Received msg ... PAMSG_CHAR_CREATE"); handleCharacterCreateMessage(computer, message); break; case PAMSG_CHAR_SELECT: { + LOG_DEBUG("Received msg ... PAMSG_CHAR_SELECT"); result.writeShort(APMSG_CHAR_SELECT_RESPONSE); if (computer.getAccount().get() == NULL) @@ -205,6 +242,7 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) case PAMSG_CHAR_DELETE: { + LOG_DEBUG("Received msg ... PAMSG_CHAR_DELETE"); result.writeShort(APMSG_CHAR_DELETE_RESPONSE); if (computer.getAccount().get() == NULL) @@ -244,7 +282,8 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) break; default: - LOG_WARN("Invalid message type"); + LOG_WARN("AccountHandler::processMessage, Invalid message type " + << message.getId()); result.writeShort(XXMSG_INVALID); break; } @@ -340,6 +379,34 @@ AccountHandler::handleLogoutMessage(AccountClient &computer) } void +AccountHandler::handleReconnectMessage(AccountClient &computer, MessageIn &msg) +{ + if (computer.getAccount().get() == NULL) + { + std::string magic_token = msg.readString(32); + AccountPendingReconnects::iterator i = pendingReconnects.find(magic_token); + if (i == pendingReconnects.end()) + { + for (AccountPendingClients::iterator j = pendingClients.begin(), + j_end = pendingClients.end(); j != j_end; ++j) + { + if (j->second == &computer) return; //Allready inserted + } + pendingClients.insert(std::make_pair(magic_token, &computer)); + return; //Waiting for the gameserver, note: using return instead of an else + } + // Gameserver communication was faster, connect the client + int accountID = i->second; + pendingReconnects.erase(i); + handleReconnectedAccount(computer, accountID); + } + else + { + LOG_WARN("Account tried to reconnect, but was allready logged in."); + } +} + +void AccountHandler::handleRegisterMessage(AccountClient &computer, MessageIn &msg) { unsigned long clientVersion = msg.readLong(); @@ -400,6 +467,9 @@ AccountHandler::handleRegisterMessage(AccountClient &computer, MessageIn &msg) AccountPtr acc(new Account(username, password, email)); store.addAccount(acc); reply.writeByte(ERRMSG_OK); + + // Associate account with connection + computer.setAccount(acc); } } @@ -410,6 +480,7 @@ void AccountHandler::handleUnregisterMessage(AccountClient &computer, MessageIn &msg) { + LOG_DEBUG("AccountHandler::handleUnregisterMessage"); std::string username = msg.readString(); std::string password = msg.readString(); @@ -424,13 +495,18 @@ AccountHandler::handleUnregisterMessage(AccountClient &computer, // See if the account exists Storage &store = Storage::instance("tmw"); AccountPtr accPtr = store.getAccount(username); - + LOG_INFO("Unregister for " << username << " with passwords #" << accPtr->getPassword() << "#" << password << "#"); if (!accPtr.get() || accPtr->getPassword() != password) { reply.writeByte(ERRMSG_INVALID_ARGUMENT); } else { + // Delete account and associated characters + LOG_DEBUG("Farewell " << username << " ..."); + store.delAccount(accPtr); + reply.writeByte(ERRMSG_OK); + // If the account to delete is the current account we're logged in. // Get out of it in memory. if (computer.getAccount().get() != NULL ) @@ -440,11 +516,6 @@ AccountHandler::handleUnregisterMessage(AccountClient &computer, computer.unsetAccount(); } } - - // Delete account and associated characters - LOG_INFO("Farewell " << username << " ..."); - store.delAccount(accPtr); - reply.writeByte(ERRMSG_OK); } } @@ -627,3 +698,57 @@ AccountHandler::handleCharacterCreateMessage(AccountClient &computer, computer.send(reply); } + +void +registerAccountReconnect(int accountID, const std::string& magic_token) +{ + AccountPendingClients::iterator i = pendingClients.find(magic_token); + if (i == pendingClients.end()) + { + pendingReconnects.insert(std::make_pair(magic_token, accountID)); + } + else + { + AccountClient &computer = *(i->second); + handleReconnectedAccount(computer, accountID); + pendingClients.erase(i); + } +} + +void +handleReconnectedAccount(AccountClient &computer, int accountID) +{ + MessageOut reply(APMSG_RECONNECT_RESPONSE); + + // Check if the account exists + Storage &store = Storage::instance("tmw"); + AccountPtr acc = store.getAccountByID(accountID); + + // Associate account with connection + computer.setAccount(acc); + + reply.writeByte(ERRMSG_OK); + computer.send(reply); + + // Return information about available characters + Players &chars = computer.getAccount()->getCharacters(); + + // Send characters list + for (unsigned int i = 0; i < chars.size(); i++) + { + MessageOut charInfo(APMSG_CHAR_INFO); + charInfo.writeByte(i); // Slot + charInfo.writeString(chars[i]->getName()); + charInfo.writeByte((unsigned char) chars[i]->getGender()); + charInfo.writeByte(chars[i]->getHairStyle()); + charInfo.writeByte(chars[i]->getHairColor()); + charInfo.writeByte(chars[i]->getLevel()); + charInfo.writeShort(chars[i]->getMoney()); + + for (int j = 0; j < NB_RSTAT; ++j) + { + charInfo.writeShort(chars[i]->getRawStat(j)); + } + computer.send(charInfo); + } +} diff --git a/src/account-server/accounthandler.hpp b/src/account-server/accounthandler.hpp index 712cde9a..da9140e4 100644 --- a/src/account-server/accounthandler.hpp +++ b/src/account-server/accounthandler.hpp @@ -67,6 +67,9 @@ class AccountHandler : public ConnectionHandler handleLogoutMessage(AccountClient &computer); void + handleReconnectMessage(AccountClient &computer, MessageIn &msg); + + void handleRegisterMessage(AccountClient &computer, MessageIn &msg); void diff --git a/src/account-server/dalstorage.cpp b/src/account-server/dalstorage.cpp index c4dad80f..5cc8dd0f 100644 --- a/src/account-server/dalstorage.cpp +++ b/src/account-server/dalstorage.cpp @@ -155,9 +155,10 @@ DALStorage::open(void) // we will stick with strategy2 for the moment as we are focusing // on SQLite. - // FIXME: The tables should be checked/created at startup in order to avoid - // a DbSqlQueryExecFailure assert on sqlite while registering. - // Also, this would initialize connection to the database earlier in memory. + // FIXME: The tables should be checked/created at startup in order to + // avoid a DbSqlQueryExecFailure assert on sqlite while registering. + // Also, this would initialize connection to the database earlier in + // memory. createTable(ACCOUNTS_TBL_NAME, SQL_ACCOUNTS_TABLE); createTable(CHARACTERS_TBL_NAME, SQL_CHARACTERS_TABLE); @@ -167,7 +168,7 @@ DALStorage::open(void) createTable(CHANNELS_TBL_NAME, SQL_CHANNELS_TABLE); } catch (const DbConnectionFailure& e) { - LOG_ERROR("unable to connect to the database: " << e.what()); + LOG_ERROR("Unable to connect to the database: " << e.what()); } catch (const DbSqlQueryExecFailure& e) { LOG_ERROR("SQL query failure: " << e.what()); @@ -269,6 +270,85 @@ DALStorage::getAccount(const std::string& userName) } } +/** + * Get an account by ID. + */ +AccountPtr +DALStorage::getAccountByID(int accountID) +{ + // connect to the database (if not connected yet). + open(); + + // look for the account in the list first. + Accounts::iterator it = mAccounts.find(accountID); + + if (it != mAccounts.end()) + return it->second; + + using namespace dal; + + // the account was not in the list, look for it in the database. + try { + std::ostringstream sql; + sql << "select * from " << ACCOUNTS_TBL_NAME << " where id = '" + << accountID << "';"; + const RecordSet& accountInfo = mDb->execSql(sql.str()); + + // if the account is not even in the database then + // we have no choice but to return nothing. + if (accountInfo.isEmpty()) { + return AccountPtr(NULL); + } + + // specialize the string_to functor to convert + // a string to an unsigned int. + string_to< unsigned > toUint; + unsigned id = toUint(accountInfo(0, 0)); + + // create an Account instance + // and initialize it with information about the user. + AccountPtr account(new Account(accountInfo(0, 1), + accountInfo(0, 2), + accountInfo(0, 3), id)); + + mAccounts.insert(std::make_pair(id, account)); + + // load the characters associated with the account. + sql.str(std::string()); + sql << "select id from " << CHARACTERS_TBL_NAME << " where user_id = '" + << accountInfo(0, 0) << "';"; + RecordSet const &charInfo = mDb->execSql(sql.str()); + + if (!charInfo.isEmpty()) + { + int size = charInfo.rows(); + Players players; + + LOG_DEBUG("AccountID: "<< accountID << "; has " << size + << " character(s) in database."); + + // Two steps: it seems like multiple requests cannot be alive at the same time. + std::vector< unsigned > playerIDs; + for (int k = 0; k < size; ++k) + { + playerIDs.push_back(toUint(charInfo(k, 0))); + } + + for (int k = 0; k < size; ++k) + { + players.push_back(getCharacter(playerIDs[k])); + } + + account->setCharacters(players); + } + + return account; + } + catch (const DbSqlQueryExecFailure& e) + { + return AccountPtr(NULL); // TODO: Throw exception here + } +} /** * Gets a character by database ID. @@ -310,6 +390,7 @@ PlayerPtr DALStorage::getCharacter(int id) string_to< unsigned short > toUshort; PlayerData *player = new PlayerData(charInfo(0, 2), toUint(charInfo(0, 0))); + player->setAccountID(toUint(charInfo(0, 1))); player->setGender(toUshort(charInfo(0, 3))); player->setHairStyle(toUshort(charInfo(0, 4))); player->setHairColor(toUshort(charInfo(0, 5))); diff --git a/src/account-server/dalstorage.hpp b/src/account-server/dalstorage.hpp index d2633e23..674b67f6 100644 --- a/src/account-server/dalstorage.hpp +++ b/src/account-server/dalstorage.hpp @@ -66,6 +66,16 @@ class DALStorage: public Storage getAccount(const std::string& userName); /** + * Get an account by ID. + * + * @param accountID the ID of the account. + * + * @return the account associated with the ID. + */ + AccountPtr + getAccountByID(int accountID); + + /** * Gets a character by database ID. * * @param id the ID of the character. diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index 2340d581..e4ec218f 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -31,6 +31,9 @@ #include "net/netcomputer.hpp" #include "utils/logger.h" +extern void registerAccountReconnect(int accountID, + const std::string &magic_token); + bool ServerHandler::startListen(enet_uint16 port) { LOG_INFO("Game server handler started:"); @@ -91,6 +94,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) { case GAMSG_REGISTER: { + LOG_DEBUG("GAMSG_REGISTER"); // TODO: check the credentials of the game server std::string address = msg.readString(); int port = msg.readShort(); @@ -118,6 +122,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) case GAMSG_PLAYER_DATA: { + LOG_DEBUG("GAMSG_PLAYER_DATA"); int id = msg.readLong(); Storage &store = Storage::instance("tmw"); PlayerPtr ptr = store.getCharacter(id); @@ -135,6 +140,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) case GAMSG_REDIRECT: { + LOG_DEBUG("GAMSG_REDIRECT"); int id = msg.readLong(); std::string magic_token(32, ' '); for (int i = 0; i < 32; ++i) @@ -162,8 +168,23 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) } } break; + case GAMSG_PLAYER_RECONNECT: + { + LOG_DEBUG("GAMSG_PLAYER_RECONNECT"); + int characterID = msg.readLong(); + std::string magic_token = msg.readString(32); + + Storage &store = Storage::instance("tmw"); + PlayerPtr ptr = store.getCharacter(characterID); + + int accountID = ptr->getAccountID(); + registerAccountReconnect(accountID, magic_token); + + } break; + default: - LOG_WARN("Invalid message type: " << msg.getId()); + LOG_WARN("ServerHandler::processMessage, Invalid message type: " + << msg.getId()); result.writeShort(XXMSG_INVALID); break; } diff --git a/src/account-server/storage.hpp b/src/account-server/storage.hpp index d530f6f2..031acf4d 100644 --- a/src/account-server/storage.hpp +++ b/src/account-server/storage.hpp @@ -173,6 +173,16 @@ class Storage getAccount(const std::string& userName) = 0; /** + * Get an account by ID. + * + * @param accountID the ID of the account. + * + * @return the account associated with the ID. + */ + virtual AccountPtr + getAccountByID(int accountID) = 0; + + /** * Gets a character by database ID. * * @param id the ID of the character. diff --git a/src/chat-server/chathandler.cpp b/src/chat-server/chathandler.cpp index 90193821..8269a6be 100644 --- a/src/chat-server/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -445,7 +445,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) break; default: - LOG_WARN("Invalid message type"); + LOG_WARN("ChatHandler::processMessage, Invalid message type" + << message.getId()); result.writeShort(XXMSG_INVALID); break; } @@ -454,7 +455,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) computer.send(result); } -void ChatHandler::handleCommand(ChatClient &computer, std::string const &command) +void +ChatHandler::handleCommand(ChatClient &computer, std::string const &command) { LOG_INFO("Chat: Received unhandled command: " << command); MessageOut result; @@ -463,7 +465,8 @@ void ChatHandler::handleCommand(ChatClient &computer, std::string const &command computer.send(result); } -void ChatHandler::warnPlayerAboutBadWords(ChatClient &computer) +void +ChatHandler::warnPlayerAboutBadWords(ChatClient &computer) { // We could later count if the player is really often unpolite. MessageOut result; @@ -474,7 +477,8 @@ void ChatHandler::warnPlayerAboutBadWords(ChatClient &computer) LOG_INFO(computer.characterName << " says bad words."); } -void ChatHandler::announce(ChatClient &computer, std::string const &text) +void +ChatHandler::announce(ChatClient &computer, std::string const &text) { MessageOut result; if (computer.accountLevel == AL_ADMIN || @@ -501,7 +505,8 @@ ChatHandler::sayToPlayer(ChatClient &computer, std::string const &playerName, std::string const &text) { MessageOut result; - LOG_DEBUG(computer.characterName << " says to " << playerName << ": " << text); + LOG_DEBUG(computer.characterName << " says to " << playerName << ": " + << text); // Send it to the being if the being exists result.writeShort(CPMSG_PRIVMSG); result.writeString(computer.characterName); @@ -521,7 +526,8 @@ ChatHandler::sayInChannel(ChatClient &computer, short channel, std::string const &text) { MessageOut result; - LOG_DEBUG(computer.characterName << " says in channel " << channel << ": " << text); + LOG_DEBUG(computer.characterName << " says in channel " << channel << ": " + << text); // Send it to every beings in channel result.writeShort(CPMSG_PUBMSG); result.writeShort(channel); diff --git a/src/defines.h b/src/defines.h index 25e6bb56..b9f81b65 100644 --- a/src/defines.h +++ b/src/defines.h @@ -108,7 +108,7 @@ enum { // Login/Register PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email APMSG_REGISTER_RESPONSE = 0x0002, // B error - PAMSG_UNREGISTER = 0x0003, // - + PAMSG_UNREGISTER = 0x0003, // S username, S password APMSG_UNREGISTER_RESPONSE = 0x0004, // B error PAMSG_LOGIN = 0x0010, // L version, S username, S password APMSG_LOGIN_RESPONSE = 0x0012, // B error @@ -133,6 +133,14 @@ enum { PCMSG_CONNECT = 0x0053, // B*32 token CPMSG_CONNECT_RESPONSE = 0x0054, // B error + PGMSG_DISCONNECT = 0x0060, // B reconnect account + GPMSG_DISCONNECT_RESPONSE = 0x0061, // B error, B*32 token + PCMSG_DISCONNECT = 0x0063, // - + CPMSG_DISCONNECT_RESPONSE = 0x0064, // B error + + PAMSG_RECONNECT = 0x0065, // B*32 token + APMSG_RECONNECT_RESPONSE = 0x0066, // B error + // Game GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y GPMSG_PLAYER_SERVER_CHANGE = 0x0101, // B*32 token, S game address, W game port @@ -183,6 +191,7 @@ enum { GAMSG_PLAYER_DATA = 0x520, // L id, B* player data GAMSG_REDIRECT = 0x530, // L id AGMSG_REDIRECT_RESPONSE = 0x531, // L id, B*32 token, S game address, W game port + GAMSG_PLAYER_RECONNECT = 0x532, // L id, B*32 token XXMSG_INVALID = 0x7FFF }; diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index d681cb64..a5c7bddd 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -98,3 +98,13 @@ void AccountConnection::processMessage(MessageIn &msg) break; } } + +void AccountConnection::playerReconnectAccount(int id, const std::string magic_token) +{ + LOG_INFO("Send GAMSG_PLAYER_RECONNECT."); + MessageOut msg(GAMSG_PLAYER_RECONNECT); + msg.writeLong(id); + msg.writeString(magic_token); + send(msg); + +} diff --git a/src/game-server/accountconnection.hpp b/src/game-server/accountconnection.hpp index e418a111..5f8ae0e9 100644 --- a/src/game-server/accountconnection.hpp +++ b/src/game-server/accountconnection.hpp @@ -45,6 +45,12 @@ class AccountConnection: public Connection */ void sendPlayerData(PlayerData *); + /** + * Prepares the account server for a reconnecting player + */ + void playerReconnectAccount(int id, const std::string magic_token); + + protected: /** * Processes server messages. diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 98a10938..05e4d2b0 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -24,6 +24,7 @@ #include <cassert> #include <map> +#include "game-server/accountconnection.hpp" #include "game-server/gamehandler.hpp" #include "game-server/inventory.hpp" #include "game-server/item.hpp" @@ -303,6 +304,33 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) computer.character->setAction(PLAYER_ATTACK); } break; + case PGMSG_DISCONNECT: + { + bool reconnectAccount = (bool) message.readByte(); + + result.writeShort(GPMSG_DISCONNECT_RESPONSE); + result.writeShort(ERRMSG_OK); // It is when control reaches here + + if (reconnectAccount) + { + LOG_INFO("Making a magic_token."); + std::string magic_token(32, ' '); + for (int i = 0; i < 32; ++i) { + magic_token[i] = + 1 + (int) (127 * (rand() / (RAND_MAX + 1.0))); + } + result.writeString(magic_token, 32); + //No accountserver data, the client should remember that + accountHandler->playerReconnectAccount( + computer.character->getDatabaseID(), + magic_token); + } + // TODO: check if the character's updated info is send to the database + gameState->remove(computer.character); + delete computer.character; + computer.character = NULL; + computer.status = CLIENT_LOGIN; + } break; default: LOG_WARN("Invalid message type"); result.writeShort(XXMSG_INVALID); diff --git a/src/playerdata.cpp b/src/playerdata.cpp index 1b9760d2..52f35e98 100644 --- a/src/playerdata.cpp +++ b/src/playerdata.cpp @@ -24,8 +24,9 @@ #include "net/messagein.hpp" #include "net/messageout.hpp" -PlayerData::PlayerData(std::string const &name, int id) - : mDatabaseID(id), +PlayerData::PlayerData(std::string const &name, int id): + mAccountID(-1), + mDatabaseID(id), mName(name) { for (int j = 0; j < EQUIPMENT_SLOTS; ++j) diff --git a/src/playerdata.hpp b/src/playerdata.hpp index a7fffe99..1c5b1ad9 100644 --- a/src/playerdata.hpp +++ b/src/playerdata.hpp @@ -205,6 +205,20 @@ class PlayerData { return mRawStats.stats[numStat]; } /** + * Gets account ID. + * + * @return the account ID, a negative number if none yet. + */ + int getAccountID() const + { return mAccountID; } + + /** + * Sets account ID. + */ + void setAccountID(int id) + { mAccountID = id; } + + /** * Gets database ID. * * @return the database ID, a negative number if none yet. @@ -269,6 +283,8 @@ class PlayerData PlayerData(PlayerData const &); PlayerData &operator=(PlayerData const &); + int mAccountID; /**< Account ID of the account the player + belongs to. */ int mDatabaseID; /**< Player database ID. */ std::string mName; /**< Name of the being. */ unsigned char mGender; /**< Gender of the being. */ |