diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | src/account.cpp | 23 | ||||
-rw-r--r-- | src/account.h | 8 | ||||
-rw-r--r-- | src/accounthandler.cpp | 81 | ||||
-rw-r--r-- | src/client.cpp | 39 | ||||
-rw-r--r-- | src/dalstorage.cpp | 61 | ||||
-rw-r--r-- | src/defines.h | 4 | ||||
-rw-r--r-- | src/main.cpp | 2 |
8 files changed, 208 insertions, 15 deletions
@@ -1,5 +1,10 @@ 2005-12-11 Yohann Ferreira <bertram@cegetel.net> + * src/accounthandler.cpp, src/main.cpp, src/account.h, + src/account.cpp, src/dalstorage.cpp, src/client.cpp, + src/defines.h: Added Logout, and character deletion support. + Also changed the response code when trying to login when already + logged. * src/accounthandler.cpp, src/main.cpp, src/dalstorage.cpp, src/client.cpp, src/connectionhandler.cpp, src/defines.h: Added unregistering, checking on character's name and email diff --git a/src/account.cpp b/src/account.cpp index bf20ac34..86815ed4 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -176,6 +176,29 @@ Account::addCharacter(BeingPtr character) } } +/** + * Remove a character. + */ +bool +Account::delCharacter(std::string name) +{ + Beings::iterator it = + std::find_if(mCharacters.begin(), + mCharacters.end(), + std::bind2nd(obj_name_is<BeingPtr>(), name) + ); + + if (it != mCharacters.end()) { + // Exists, delete it. + mCharacters.erase(it++); + return true; + } + else + { + return false; + } +} + /** * Get all the characters. diff --git a/src/account.h b/src/account.h index f45ec7c4..5cb57ede 100644 --- a/src/account.h +++ b/src/account.h @@ -176,6 +176,14 @@ class Account void addCharacter(BeingPtr character); + /** + * Remove a character. + * + * @param name The character's name to delete. + */ + bool + delCharacter(std::string name); + /** * Get all the characters. diff --git a/src/accounthandler.cpp b/src/accounthandler.cpp index c2e2df5e..0ad9c1ba 100644 --- a/src/accounthandler.cpp +++ b/src/accounthandler.cpp @@ -69,7 +69,7 @@ void AccountHandler::receiveMessage(NetComputer &computer, MessageIn &message) << "." << std::endl; std::cout << "Please logout first." << std::endl; result.writeShort(SMSG_LOGIN_ERROR); - result.writeShort(LOGIN_UNKNOWN); + result.writeShort(LOGIN_ALREADY_LOGGED); break; } @@ -115,6 +115,37 @@ void AccountHandler::receiveMessage(NetComputer &computer, MessageIn &message) } break; + case CMSG_LOGOUT: + { + if ( computer.getAccount() == NULL ) + { + std::cout << "Can't logout. Not even logged in." << std::endl; + result.writeShort(SMSG_LOGOUT_ERROR); + result.writeByte(LOGOUT_UNSUCCESSFULL); + } + else + { + std::string username = computer.getAccount()->getName(); + if ( username == "" ) + { + std::cout << "Account without name ? Logged out anyway..." << std::endl; + computer.setCharacter(NULL); + computer.setAccount(NULL); + result.writeShort(SMSG_LOGOUT_ERROR); + result.writeByte(LOGOUT_UNKNOWN); + } + else + { + std::cout << computer.getAccount()->getName() << " logs out." << std::endl; + computer.setCharacter(NULL); + computer.setAccount(NULL); + result.writeShort(SMSG_LOGOUT_CONFIRM); + result.writeByte(LOGOUT_OK); + } + } + } + break; + case CMSG_REGISTER: { std::string username = message.readString(); @@ -319,8 +350,54 @@ void AccountHandler::receiveMessage(NetComputer &computer, MessageIn &message) std::cout << "Selected Character " << int(charNum) << " : " << computer.getCharacter()->getName() << std::endl; + } + break; + + case CMSG_CHAR_DELETE: + { + if (computer.getAccount() == NULL) + { + result.writeShort(SMSG_CHAR_DELETE_RESPONSE); + result.writeByte(DELETE_NOLOGIN); + std::cout << "Not logged in. Can't delete a Character." << std::endl; + break; // not logged in + } + + unsigned char charNum = message.readByte(); + + tmwserv::Beings &chars = computer.getAccount()->getCharacters(); + result.writeShort(SMSG_CHAR_DELETE_RESPONSE); + if ( chars.size() == 0 ) + { + result.writeByte(DELETE_NO_MORE_CHARACTERS); + std::cout << "Character Deletion : No characters in this account." << std::endl; + break; + } + // Character ID = 0 to Number of Characters - 1. + if (charNum >= chars.size()) { + // invalid char selection + result.writeByte(DELETE_INVALID_NAME); + std::cout << "Character Deletion : Selection out of ID range." << std::endl; + break; + } + + // Delete the character + // if the character to delete is the current character, get off of it in + // memory. + if ( computer.getCharacter() != NULL ) + { + if ( computer.getCharacter()->getName() == chars[charNum].get()->getName() ) + { + computer.setCharacter(NULL); + } + } + + std::string deletedCharacter = chars[charNum].get()->getName(); + computer.getAccount()->delCharacter(deletedCharacter); + store.flush(); + std::cout << deletedCharacter << ": Character deleted..." << std::endl; + result.writeByte(DELETE_OK); - //TODO: Add the character in the database and flush. } break; diff --git a/src/client.cpp b/src/client.cpp index c2115ce6..8bbcce4e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -51,12 +51,14 @@ int main(int argc, char *argv[]) printf ("1) Register\n"); printf ("2) Unregister\n"); printf ("3) Login\n"); - printf ("4) Chat\n"); - printf ("5) Create character\n"); - printf ("6) Character selection\n"); - printf ("7) Move character\n"); - printf ("8) Equip item\n"); - printf ("9) Ruby expression\n"); + printf ("4) Logout\n"); + printf ("5) Chat\n"); + printf ("6) Create character\n"); + printf ("7) Character selection\n"); + printf ("8) Delete Character\n"); + printf ("9) Move character\n"); + printf ("10) Equip item\n"); + printf ("11) Ruby expression\n"); printf ("Choose your option: "); std::cin >> answer; @@ -98,6 +100,12 @@ int main(int argc, char *argv[]) break; case 4: + // Logout + msg.writeShort(CMSG_LOGOUT); + std::cout << "Logout" << std::endl; + break; + + case 5: // Chat msg.writeShort(CMSG_SAY); printf("\nChat: ", line); @@ -107,7 +115,7 @@ int main(int argc, char *argv[]) responseRequired = false; break; - case 5: + case 6: { // Create character msg.writeShort(CMSG_CHAR_CREATE); @@ -117,7 +125,7 @@ int main(int argc, char *argv[]) msg.writeByte(0); } break; - case 6: + case 7: { // Select character msg.writeShort(CMSG_CHAR_SELECT); @@ -126,7 +134,16 @@ int main(int argc, char *argv[]) msg.writeByte(atoi(line)); } break; - case 7: + case 8: + { + // Delete character + msg.writeShort(CMSG_CHAR_DELETE); + printf("\nCharacter ID: "); + std::cin >> line; + msg.writeByte(atoi(line)); + } break; + + case 9: { // Move character long x, y; @@ -142,7 +159,7 @@ int main(int argc, char *argv[]) responseRequired = false; } break; - case 8: + case 10: { // Equip unsigned int itemId; @@ -156,7 +173,7 @@ int main(int argc, char *argv[]) msg.writeByte(slot); } break; - case 9: + case 11: { std::cout << "Expr: "; std::cin >> line; diff --git a/src/dalstorage.cpp b/src/dalstorage.cpp index 721b0b72..5d45ba56 100644 --- a/src/dalstorage.cpp +++ b/src/dalstorage.cpp @@ -625,7 +625,8 @@ DALStorage::_updAccount(const AccountPtr& account) // doublecheck that this account already exists in the database // and therefore its status must be AS_ACC_TO_UPDATE. if ((account_it->second).status != AS_ACC_TO_UPDATE) { - return; // should we throw an exception here instead? + return; // Should we throw an exception here instead? No, because this can happen + // without any bad consequences as long as we return -- Bertram. } // update the account. @@ -709,6 +710,62 @@ DALStorage::_updAccount(const AccountPtr& account) // TODO: inventories. } + + // Existing characters in memory have been inserted or updated in database. + // Now, let's remove those who are no more in memory from database. + + // specialize the string_to functor to convert + // a string to an unsigned int. + string_to<unsigned short> toUint; + + std::ostringstream sql4; + sql4 << "select name, id from " << CHARACTERS_TBL_NAME + << " where user_id = '" << (account_it->second).id << "';"; + const RecordSet& charInMemInfo = mDb->execSql(sql4.str()); + + // We compare chars from memory and those existing in db, + // And delete those not in mem but existing in db. + bool charFound; + for ( unsigned int i = 0; i < charInMemInfo.rows(); ++i) // in database + { + charFound = false; + it = characters.begin(); + for (; it != it_end; ++it) // In memory + { + if ( charInMemInfo(i, 0) == (*it)->getName() ) + { + charFound = true; + break; + } + } + if ( !charFound ) + { + // The char is db but not in memory, + // It will be removed from database. + // We store the id of the char to delete + // Because as deleted, the RecordSet is also emptied + // That creates an error. + unsigned int charId = toUint(charInMemInfo(i, 1)); + + // delete the inventory. + std::ostringstream sql5; + sql5 << "delete from "; + sql5 << INVENTORIES_TBL_NAME; + sql5 << " where owner_id = '"; + sql5 << charId; + sql5 << "';"; + mDb->execSql(sql5.str()); + + // now delete the character. + std::ostringstream sql6; + sql6 << "delete from "; + sql6 << CHARACTERS_TBL_NAME; + sql6 << " where id = '"; + sql6 << charId; + sql6 << "';"; + mDb->execSql(sql6.str()); + } + } } @@ -769,6 +826,8 @@ DALStorage::_delAccount(const std::string& userName) // TODO: we should start a transaction here so that in case of problem // the lost of data would be minimized. + // db.set-transaction-type of this-db to db.manual-commit, for instance + // Agreed, but will sqlite support this ? // actually removing data. vector<string>::const_iterator it = charIds.begin(); diff --git a/src/defines.h b/src/defines.h index 75991a63..a302796d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -94,7 +94,8 @@ enum { SMSG_LOGIN_ERROR = 0x0012, SMSG_LOGIN_CONFIRM = 0x0013, CMSG_LOGOUT = 0x0014, - SMSG_LOGOUT_CONFIRM = 0x0015, + SMSG_LOGOUT_ERROR = 0x0015, + SMSG_LOGOUT_CONFIRM = 0x0016, CMSG_CHAR_CREATE = 0x0020, SMSG_CHAR_CREATE_RESPONSE = 0x0021, CMSG_CHAR_DELETE = 0x0022, @@ -154,6 +155,7 @@ enum { LOGIN_SERVER_FULL, LOGIN_ACCOUNT_BANNED, LOGIN_ACCOUNT_REVIEW, + LOGIN_ALREADY_LOGGED, LOGIN_UNKNOWN }; diff --git a/src/main.cpp b/src/main.cpp index b9cda372..3c2406f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -227,10 +227,12 @@ int main(int argc, char *argv[]) // Register message handlers connectionHandler.registerHandler(CMSG_LOGIN, accountHandler); + connectionHandler.registerHandler(CMSG_LOGOUT, accountHandler); connectionHandler.registerHandler(CMSG_REGISTER, accountHandler); connectionHandler.registerHandler(CMSG_UNREGISTER, accountHandler); connectionHandler.registerHandler(CMSG_CHAR_CREATE, accountHandler); connectionHandler.registerHandler(CMSG_CHAR_SELECT, accountHandler); + connectionHandler.registerHandler(CMSG_CHAR_DELETE, accountHandler); connectionHandler.registerHandler(CMSG_SAY, chatHandler); connectionHandler.registerHandler(CMSG_ANNOUNCE, chatHandler); |