00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "account-server/dalstorage.hpp"
00024
00025 #include <cassert>
00026
00027 #include "configuration.h"
00028 #include "point.h"
00029 #include "account-server/characterdata.hpp"
00030 #include "account-server/dalstoragesql.hpp"
00031 #include "dal/dalexcept.h"
00032 #include "dal/dataproviderfactory.h"
00033 #include "utils/functors.h"
00034 #include "utils/logger.h"
00035
00039 class account_by_name
00040 {
00041 public:
00042 account_by_name(const std::string& name)
00043 : mName(name)
00044 {}
00045
00046 bool operator()(std::pair<unsigned, AccountPtr> const &elem) const
00047 { return elem.second->getName() == mName; }
00048
00049 private:
00050 std::string mName;
00051 };
00052
00056 class character_by_id
00057 {
00058 public:
00059 character_by_id(int id)
00060 : mID(id)
00061 {}
00062
00063 bool operator()(CharacterPtr const &elem) const
00064 { return elem->getDatabaseID() == mID; }
00065
00066 private:
00067 int mID;
00068 };
00069
00070
00074 DALStorage::DALStorage()
00075 : mDb(dal::DataProviderFactory::createDataProvider())
00076 {
00077
00078
00079 }
00080
00081
00085 DALStorage::~DALStorage()
00086 throw()
00087 {
00088 if (mDb->isConnected()) {
00089 close();
00090 }
00091
00092
00093
00094 }
00095
00096
00100 void
00101 DALStorage::open(void)
00102 {
00103
00104 if (mDb->isConnected()) {
00105 return;
00106 }
00107
00108 using namespace dal;
00109
00110 static bool dbFileShown = false;
00111 std::string dbFile(getName());
00112 try {
00113
00114 #if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT)
00115 mDb->connect(getName(), getUser(), getPassword());
00116 if (!dbFileShown)
00117 {
00118 LOG_INFO("Using " << dbFile << " as Database Name.");
00119 dbFileShown = true;
00120 }
00121 #elif defined (SQLITE_SUPPORT)
00122
00123 dbFile += ".db";
00124 mDb->connect(dbFile, "", "");
00125 if (!dbFileShown)
00126 {
00127 LOG_INFO("SQLite uses ./" << dbFile << " as DB.");
00128 dbFileShown = true;
00129 }
00130 #endif
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 createTable(ACCOUNTS_TBL_NAME, SQL_ACCOUNTS_TABLE);
00166 createTable(CHARACTERS_TBL_NAME, SQL_CHARACTERS_TABLE);
00167 createTable(ITEMS_TBL_NAME, SQL_ITEMS_TABLE);
00168 createTable(WORLD_ITEMS_TBL_NAME, SQL_WORLD_ITEMS_TABLE);
00169 createTable(INVENTORIES_TBL_NAME, SQL_INVENTORIES_TABLE);
00170 createTable(CHANNELS_TBL_NAME, SQL_CHANNELS_TABLE);
00171 }
00172 catch (const DbConnectionFailure& e) {
00173 LOG_ERROR("(DALStorage::open #1) Unable to connect to the database: "
00174 << e.what());
00175 }
00176 catch (const DbSqlQueryExecFailure& e) {
00177 LOG_ERROR("(DALStorage::open #2) SQL query failure: " << e.what());
00178 }
00179
00180 mIsOpen = mDb->isConnected();
00181 }
00182
00183
00187 void
00188 DALStorage::close(void)
00189 {
00190 mDb->disconnect();
00191 mIsOpen = mDb->isConnected();
00192 }
00193
00194
00198 AccountPtr
00199 DALStorage::getAccount(const std::string& userName)
00200 {
00201
00202 open();
00203
00204
00205 Accounts::iterator it_end = mAccounts.end(),
00206 it = std::find_if(mAccounts.begin(), it_end, account_by_name(userName));
00207
00208 if (it != it_end)
00209 return it->second;
00210
00211 using namespace dal;
00212
00213
00214 try {
00215 std::ostringstream sql;
00216 sql << "select * from " << ACCOUNTS_TBL_NAME << " where username = \""
00217 << userName << "\";";
00218 const RecordSet& accountInfo = mDb->execSql(sql.str());
00219
00220
00221
00222 if (accountInfo.isEmpty()) {
00223 return AccountPtr(NULL);
00224 }
00225
00226
00227
00228 string_to< unsigned > toUint;
00229 unsigned id = toUint(accountInfo(0, 0));
00230
00231
00232
00233 AccountPtr account(new Account(accountInfo(0, 1),
00234 accountInfo(0, 2),
00235 accountInfo(0, 3), id));
00236
00237 mAccounts.insert(std::make_pair(id, account));
00238
00239
00240 sql.str(std::string());
00241 sql << "select id from " << CHARACTERS_TBL_NAME << " where user_id = '"
00242 << accountInfo(0, 0) << "';";
00243 RecordSet const &charInfo = mDb->execSql(sql.str());
00244
00245 if (!charInfo.isEmpty())
00246 {
00247 int size = charInfo.rows();
00248 Characters characters;
00249
00250 LOG_DEBUG(userName << "'s account has " << size
00251 << " character(s) in database.");
00252
00253
00254 std::vector< unsigned > characterIDs;
00255 for (int k = 0; k < size; ++k)
00256 {
00257 characterIDs.push_back(toUint(charInfo(k, 0)));
00258 }
00259
00260 for (int k = 0; k < size; ++k)
00261 {
00262 characters.push_back(getCharacter(characterIDs[k]));
00263 }
00264
00265 account->setCharacters(characters);
00266 }
00267
00268 return account;
00269 }
00270 catch (const DbSqlQueryExecFailure& e)
00271 {
00272 return AccountPtr(NULL);
00273 }
00274 }
00275
00279 AccountPtr
00280 DALStorage::getAccountByID(int accountID)
00281 {
00282
00283 open();
00284
00285
00286 Accounts::iterator it = mAccounts.find(accountID);
00287
00288 if (it != mAccounts.end())
00289 return it->second;
00290
00291 using namespace dal;
00292
00293
00294 try {
00295 std::ostringstream sql;
00296 sql << "select * from " << ACCOUNTS_TBL_NAME << " where id = '"
00297 << accountID << "';";
00298 const RecordSet& accountInfo = mDb->execSql(sql.str());
00299
00300
00301
00302 if (accountInfo.isEmpty()) {
00303 return AccountPtr(NULL);
00304 }
00305
00306
00307
00308 string_to< unsigned > toUint;
00309 unsigned id = toUint(accountInfo(0, 0));
00310
00311
00312
00313 AccountPtr account(new Account(accountInfo(0, 1),
00314 accountInfo(0, 2),
00315 accountInfo(0, 3), id));
00316
00317 mAccounts.insert(std::make_pair(id, account));
00318
00319
00320 sql.str(std::string());
00321 sql << "select id from " << CHARACTERS_TBL_NAME << " where user_id = '"
00322 << accountInfo(0, 0) << "';";
00323 RecordSet const &charInfo = mDb->execSql(sql.str());
00324
00325 if (!charInfo.isEmpty())
00326 {
00327 int size = charInfo.rows();
00328 Characters characters;
00329
00330 LOG_DEBUG("AccountID: "<< accountID << "; has " << size
00331 << " character(s) in database.");
00332
00333
00334 std::vector< unsigned > characterIDs;
00335 for (int k = 0; k < size; ++k)
00336 {
00337 characterIDs.push_back(toUint(charInfo(k, 0)));
00338 }
00339
00340 for (int k = 0; k < size; ++k)
00341 {
00342 characters.push_back(getCharacter(characterIDs[k]));
00343 }
00344
00345 account->setCharacters(characters);
00346 }
00347
00348 return account;
00349 }
00350 catch (const DbSqlQueryExecFailure& e)
00351 {
00352 return AccountPtr(NULL);
00353 }
00354 }
00355
00359 CharacterPtr DALStorage::getCharacter(int id)
00360 {
00361
00362 open();
00363
00364
00365 Characters::iterator it_end = mCharacters.end(),
00366 it = std::find_if(mCharacters.begin(), it_end, character_by_id(id));
00367
00368 if (it != it_end)
00369 return *it;
00370
00371 using namespace dal;
00372
00373
00374 try {
00375 std::ostringstream sql;
00376 sql << "select * from " << CHARACTERS_TBL_NAME << " where id = '"
00377 << id << "';";
00378 RecordSet const &charInfo = mDb->execSql(sql.str());
00379
00380
00381
00382 if (charInfo.isEmpty())
00383 {
00384 return CharacterPtr(NULL);
00385 }
00386
00387
00388
00389 string_to< unsigned > toUint;
00390
00391
00392
00393 string_to< unsigned short > toUshort;
00394
00395 CharacterData *character = new CharacterData(charInfo(0, 2),
00396 toUint(charInfo(0, 0)));
00397 character->setAccountID(toUint(charInfo(0, 1)));
00398 character->setGender(toUshort(charInfo(0, 3)));
00399 character->setHairStyle(toUshort(charInfo(0, 4)));
00400 character->setHairColor(toUshort(charInfo(0, 5)));
00401 character->setLevel(toUshort(charInfo(0, 6)));
00402 character->setMoney(toUint(charInfo(0, 7)));
00403 Point pos(toUshort(charInfo(0, 8)), toUshort(charInfo(0, 9)));
00404 character->setPosition(pos);
00405 for (int i = 0; i < NB_BASE_ATTRIBUTES; ++i)
00406 {
00407 character->setBaseAttribute(i, toUshort(charInfo(0, 11 + i)));
00408 }
00409
00410 int mapId = toUint(charInfo(0, 10));
00411 if (mapId > 0)
00412 {
00413 character->setMapId(mapId);
00414 }
00415 else
00416 {
00417
00418
00419 character->setMapId((int)config.getValue("defaultMap", 1));
00420 }
00421
00422 CharacterPtr ptr(character);
00423 mCharacters.push_back(ptr);
00424 return ptr;
00425 }
00426 catch (const DbSqlQueryExecFailure& e)
00427 {
00428 return CharacterPtr(NULL);
00429 }
00430 }
00431
00432
00436 std::list<std::string>
00437 DALStorage::getEmailList()
00438 {
00439
00440 open();
00441
00442 std::list <std::string> emailList;
00443
00444 try {
00445 std::string sql("select email from ");
00446 sql += ACCOUNTS_TBL_NAME;
00447 sql += ";";
00448 const dal::RecordSet& accountInfo = mDb->execSql(sql);
00449
00450
00451
00452 if (accountInfo.isEmpty()) {
00453 return emailList;
00454 }
00455 for (unsigned int i = 0; i < accountInfo.rows(); i++)
00456 {
00457
00458 emailList.push_front(accountInfo(i, 0));
00459 }
00460 }
00461 catch (const dal::DbSqlQueryExecFailure& e) {
00462
00463 LOG_ERROR("(DALStorage::getEmailList) SQL query failure: " << e.what());
00464 }
00465
00466 return emailList;
00467 }
00468
00473 bool DALStorage::doesEmailAddressExist(std::string const &email)
00474 {
00475
00476 open();
00477
00478 try {
00479 std::ostringstream sql;
00480 sql << "select count(email) from " << ACCOUNTS_TBL_NAME
00481 << " where upper(email) = upper(\"" << email << "\");";
00482 dal::RecordSet const &accountInfo = mDb->execSql(sql.str());
00483
00484 std::istringstream ssStream(accountInfo(0, 0));
00485 unsigned int iReturn = 1;
00486 ssStream >> iReturn;
00487 return iReturn != 0;
00488 } catch (std::exception const &e) {
00489
00490 LOG_ERROR("(DALStorage::doesEmailAddressExist) SQL query failure: " << e.what());
00491 }
00492
00493 return true;
00494 }
00495
00500 bool DALStorage::doesCharacterNameExist(const std::string& name)
00501 {
00502
00503 open();
00504
00505 try {
00506 std::ostringstream sql;
00507 sql << "select count(name) from " << CHARACTERS_TBL_NAME
00508 << " where name = \"" << name << "\";";
00509 dal::RecordSet const &accountInfo = mDb->execSql(sql.str());
00510
00511 std::istringstream ssStream(accountInfo(0, 0));
00512 int iReturn = 1;
00513 ssStream >> iReturn;
00514 return iReturn != 0;
00515 } catch (std::exception const &e) {
00516
00517 LOG_ERROR("(DALStorage::doesCharacterNameExist) SQL query failure: "
00518 << e.what());
00519 }
00520
00521 return true;
00522 }
00523
00524 bool
00525 DALStorage::updateCharacter(CharacterPtr character)
00526 {
00527
00528 open();
00529
00530
00531 try
00532 {
00533 std::ostringstream sqlUpdateCharacterInfo;
00534 sqlUpdateCharacterInfo
00535 << "update " << CHARACTERS_TBL_NAME << " "
00536 << "set "
00537 << "gender = '" << character->getGender()
00538 << "', "
00539 << "hair_style = '" << (int)character->getHairStyle()
00540 << "', "
00541 << "hair_color = '" << (int)character->getHairColor()
00542 << "', "
00543 << "level = '" << (int)character->getLevel()
00544 << "', "
00545 << "money = '" << character->getMoney()
00546 << "', "
00547 << "x = '" << character->getPosition().x
00548 << "', "
00549 << "y = '" << character->getPosition().y
00550 << "', "
00551 << "map_id = '" << character->getMapId()
00552 << "', "
00553 << "str = '" << character->getBaseAttribute(BASE_ATTR_STRENGTH)
00554 << "', "
00555 << "agi = '" << character->getBaseAttribute(BASE_ATTR_AGILITY)
00556 << "', "
00557 << "dex = '" << character->getBaseAttribute(BASE_ATTR_DEXTERITY)
00558 << "', "
00559 << "vit = '" << character->getBaseAttribute(BASE_ATTR_VITALITY)
00560 << "', "
00561 #if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT)
00562 << "`int` = '"
00563 #else
00564 << "int = '"
00565 #endif
00566 << character->getBaseAttribute(BASE_ATTR_INTELLIGENCE)
00567 << "', "
00568
00569 << "will = '" << character->getBaseAttribute(BASE_ATTR_WILLPOWER)
00570 << "', "
00571 << "charisma = '" << character->getBaseAttribute(BASE_ATTR_CHARISMA)
00572 << "' "
00573 << "where id = '" << character->getDatabaseID()
00574 << "';";
00575
00576 mDb->execSql(sqlUpdateCharacterInfo.str());
00577 }
00578 catch (const dal::DbSqlQueryExecFailure& e)
00579 {
00580
00581 LOG_ERROR("(DALStorage::updateCharacter #1) SQL query failure: " << e.what());
00582 return false;
00583 }
00584
00589
00590 try
00591 {
00592 std::ostringstream sqlDeleteCharacterInventory;
00593 sqlDeleteCharacterInventory
00594 << "delete from " << INVENTORIES_TBL_NAME
00595 << " where owner_id = '" << character->getDatabaseID() << "';";
00596 mDb->execSql(sqlDeleteCharacterInventory.str());
00597 }
00598 catch (const dal::DbSqlQueryExecFailure& e)
00599 {
00600
00601 LOG_ERROR("(DALStorage::updateCharacter #2) SQL query failure: " << e.what());
00602 return false;
00603 }
00604
00605
00606 if (character->getNumberOfInventoryItems())
00607 {
00608 try
00609 {
00610 std::ostringstream sqlInsertCharacterInventory;
00611
00612 sqlInsertCharacterInventory
00613 << "insert into " << INVENTORIES_TBL_NAME
00614 << " (owner_id, class_id, amount, equipped) "
00615 << "values ";
00616
00617 for (int j = 0; j < character->getNumberOfInventoryItems(); j++)
00618 {
00619 sqlInsertCharacterInventory
00620 << "(" << character->getDatabaseID() << ", "
00621 << character->getInventoryItem(j).itemClassId << ", "
00622 << character->getInventoryItem(j).numberOfItemsInSlot
00623 << ", "
00624 << (unsigned short)
00625 character->getInventoryItem(j).isEquiped
00626 << ")";
00627
00628
00629 if (j < (character->getNumberOfInventoryItems() - 1))
00630 sqlInsertCharacterInventory << ", ";
00631 }
00632 sqlInsertCharacterInventory << ";";
00633
00634 mDb->execSql(sqlInsertCharacterInventory.str());
00635 }
00636 catch (const dal::DbSqlQueryExecFailure& e)
00637 {
00638
00639 LOG_ERROR("(DALStorage::updateCharacter #3) SQL query failure: " << e.what());
00640 return false;
00641 }
00642 }
00643 return true;
00644 }
00645
00646 std::map<short, ChatChannel>
00647 DALStorage::getChannelList()
00648 {
00649
00650 open();
00651
00652
00653
00654 string_to<short> toShort;
00655 string_to<bool> toBool;
00656
00657
00658 std::map<short, ChatChannel> channels;
00659
00660 try {
00661 std::stringstream sql;
00662 sql << "select id, name, announcement, password, privacy from ";
00663 sql << CHANNELS_TBL_NAME;
00664 sql << ";";
00665
00666 const dal::RecordSet& channelInfo = mDb->execSql(sql.str());
00667
00668
00669 if (channelInfo.isEmpty()) {
00670 return channels;
00671 }
00672
00673 for ( unsigned int i = 0; i < channelInfo.rows(); ++i)
00674 {
00675 channels.insert(std::make_pair(toShort(channelInfo(i,0)),
00676 ChatChannel(channelInfo(i,1),
00677 channelInfo(i,2),
00678 channelInfo(i,3),
00679 toBool(channelInfo(i,4)))));
00680
00681 LOG_DEBUG("Channel (" << channelInfo(i,0) << ") loaded: " << channelInfo(i,1)
00682 << ": " << channelInfo(i,2));
00683 }
00684
00685 return channels;
00686 }
00687 catch (const dal::DbSqlQueryExecFailure& e) {
00688
00689 LOG_ERROR("(DALStorage::getChannelList) SQL query failure: " << e.what());
00690 }
00691
00692 return channels;
00693 }
00694
00695 void
00696 DALStorage::updateChannels(std::map<short, ChatChannel>& channelList)
00697 {
00698 #if defined (SQLITE_SUPPORT)
00699
00700
00701 close();
00702 #endif
00703 open();
00704
00705 try {
00706
00707 std::stringstream sql;
00708 sql << "delete from "
00709 << CHANNELS_TBL_NAME
00710 << ";";
00711
00712 mDb->execSql(sql.str());
00713
00714 for (std::map<short, ChatChannel>::iterator i = channelList.begin();
00715 i != channelList.end();)
00716 {
00717
00718 if ( i->first < (signed)MAX_PUBLIC_CHANNELS_RANGE )
00719 {
00720 if (i->second.getName() != "")
00721 {
00722 sql.str("");
00723 sql << "insert into "
00724 << CHANNELS_TBL_NAME
00725 << " (id, name, announcement, password, privacy)"
00726 << " values ("
00727 << i->first << ", \""
00728 << i->second.getName() << "\", \""
00729 << i->second.getAnnouncement() << "\", \""
00730 << i->second.getPassword() << "\", \""
00731 << i->second.getPrivacy() << "\");";
00732
00733 LOG_DEBUG("Channel (" << i->first << ") saved: "
00734 << i->second.getName()
00735 << ": " << i->second.getAnnouncement());
00736 }
00737
00738 mDb->execSql(sql.str());
00739 }
00740 ++i;
00741 }
00742
00743 }
00744 catch (const dal::DbSqlQueryExecFailure& e) {
00745
00746 LOG_ERROR("(DALStorage::updateChannels) SQL query failure: " << e.what());
00747 }
00748 }
00749
00750
00754 void
00755 DALStorage::createTable(const std::string& tblName,
00756 const std::string& sql)
00757 {
00758 try {
00759 mDb->execSql(sql);
00760 }
00761 catch (const dal::DbSqlQueryExecFailure& e) {
00762
00763 #if defined (MYSQL_SUPPORT)
00764 std::string alreadyExists("Table '");
00765 alreadyExists += tblName;
00766 alreadyExists += "' already exists";
00767 #elif defined (POSTGRESQL_SUPPORT)
00768 std::string alreadyExists("table ");
00769 alreadyExists += tblName;
00770 alreadyExists += " already exists";
00771 #else // SQLITE_SUPPORT
00772 std::string alreadyExists("table ");
00773 alreadyExists += tblName;
00774 alreadyExists += " already exists";
00775 #endif
00776
00777 const std::string msg(e.what());
00778
00779
00780 if (msg != alreadyExists) {
00781
00782 throw;
00783 }
00784 }
00785 }
00786
00787
00791 void DALStorage::addAccount(AccountPtr const &account)
00792 {
00793 assert(account->getCharacters().size() == 0);
00794
00795 using namespace dal;
00796
00797
00798
00799
00800
00801 std::ostringstream sql1;
00802 sql1 << "insert into " << ACCOUNTS_TBL_NAME
00803 << " (username, password, email, level, banned)"
00804 << " values (\""
00805 << account->getName() << "\", \""
00806 << account->getPassword() << "\", \""
00807 << account->getEmail() << "\", "
00808 << account->getLevel() << ", 0);";
00809 mDb->execSql(sql1.str());
00810
00811
00812 std::ostringstream sql2;
00813 sql2 << "select id from " << ACCOUNTS_TBL_NAME
00814 << " where username = \"" << account->getName() << "\";";
00815 const RecordSet& accountInfo = mDb->execSql(sql2.str());
00816 string_to<unsigned int> toUint;
00817 unsigned id = toUint(accountInfo(0, 0));
00818 account->setID(id);
00819 mAccounts.insert(std::make_pair(id, account));
00820 }
00821
00825 void DALStorage::flushAll()
00826 {
00827 for (Accounts::iterator i = mAccounts.begin(),
00828 i_end = mAccounts.end(); i != i_end; ++i)
00829 flush(i->second);
00830 }
00831
00835 void DALStorage::flush(AccountPtr const &account)
00836 {
00837 assert(account->getID() >= 0);
00838
00839 using namespace dal;
00840
00841
00842
00843
00844
00845 std::ostringstream sqlUpdateAccountTable;
00846 sqlUpdateAccountTable << "update " << ACCOUNTS_TBL_NAME
00847 << " set username = \"" << account->getName() << "\", "
00848 << "password = \"" << account->getPassword() << "\", "
00849 << "email = \"" << account->getEmail() << "\", "
00850 << "level = '" << account->getLevel() << "' "
00851 << "where id = '" << account->getID() << "';";
00852 mDb->execSql(sqlUpdateAccountTable.str());
00853
00854
00855 Characters &characters = account->getCharacters();
00856
00857
00858 for (Characters::const_iterator it = characters.begin(),
00859 it_end = characters.end(); it != it_end; ++it)
00860 {
00861 if ((*it)->getDatabaseID() < 0) {
00862 std::ostringstream sqlInsertCharactersTable;
00863
00864
00865
00866 sqlInsertCharactersTable
00867 << "insert into " << CHARACTERS_TBL_NAME
00868 << " (user_id, name, gender, hair_style, hair_color, level, money,"
00869 << " x, y, map_id, str, agi, dex, vit, int, will, charisma) values ("
00870 << account->getID() << ", \""
00871 << (*it)->getName() << "\", "
00872 << (*it)->getGender() << ", "
00873 << (int)(*it)->getHairStyle() << ", "
00874 << (int)(*it)->getHairColor() << ", "
00875 << (int)(*it)->getLevel() << ", "
00876 << (*it)->getMoney() << ", "
00877 << (*it)->getPosition().x << ", "
00878 << (*it)->getPosition().y << ", "
00879 << (*it)->getMapId() << ", "
00880 << (*it)->getBaseAttribute(BASE_ATTR_STRENGTH) << ", "
00881 << (*it)->getBaseAttribute(BASE_ATTR_AGILITY) << ", "
00882 << (*it)->getBaseAttribute(BASE_ATTR_DEXTERITY) << ", "
00883 << (*it)->getBaseAttribute(BASE_ATTR_VITALITY) << ", "
00884 << (*it)->getBaseAttribute(BASE_ATTR_INTELLIGENCE) << ", "
00885 << (*it)->getBaseAttribute(BASE_ATTR_WILLPOWER) << ", "
00886 << (*it)->getBaseAttribute(BASE_ATTR_CHARISMA) << ");";
00887
00888 mDb->execSql(sqlInsertCharactersTable.str());
00889 } else {
00890 std::ostringstream sqlUpdateCharactersTable;
00891 sqlUpdateCharactersTable
00892 << "update " << CHARACTERS_TBL_NAME
00893 << " set name = \"" << (*it)->getName() << "\", "
00894 << " gender = " << (*it)->getGender() << ", "
00895 << " hair_style = " << (int)(*it)->getHairStyle() << ", "
00896 << " hair_color = " << (int)(*it)->getHairColor() << ", "
00897 << " level = " << (int)(*it)->getLevel() << ", "
00898 << " money = " << (*it)->getMoney() << ", "
00899 << " x = " << (*it)->getPosition().x << ", "
00900 << " y = " << (*it)->getPosition().y << ", "
00901 << " map_id = " << (*it)->getMapId() << ", "
00902 << " str = " << (*it)->getBaseAttribute(BASE_ATTR_STRENGTH) << ", "
00903 << " agi = " << (*it)->getBaseAttribute(BASE_ATTR_AGILITY) << ", "
00904 << " dex = " << (*it)->getBaseAttribute(BASE_ATTR_DEXTERITY) << ", "
00905 << " vit = " << (*it)->getBaseAttribute(BASE_ATTR_VITALITY) << ", "
00906 #if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT)
00907 << " `int` = "
00908 #else
00909 << " int = "
00910 #endif
00911 << (*it)->getBaseAttribute(BASE_ATTR_INTELLIGENCE) << ", "
00912 << " will = " << (*it)->getBaseAttribute(BASE_ATTR_WILLPOWER) << ", "
00913 << " charisma = " << (*it)->getBaseAttribute(BASE_ATTR_CHARISMA)
00914 << " where id = " << (*it)->getDatabaseID() << ";";
00915
00916 mDb->execSql(sqlUpdateCharactersTable.str());
00917 }
00918
00919 if ((*it)->getDatabaseID() < 0)
00920 {
00921
00922 std::ostringstream sqlSelectIdCharactersTable;
00923 sqlSelectIdCharactersTable
00924 << "select id from " << CHARACTERS_TBL_NAME
00925 << " where name = \"" << (*it)->getName() << "\";";
00926 RecordSet const &charInfo =
00927 mDb->execSql(sqlSelectIdCharactersTable.str());
00928
00929 if (!charInfo.isEmpty()) {
00930 string_to<unsigned int> toUint;
00931 (*it)->setDatabaseID(toUint(charInfo(0, 0)));
00932 }
00933 else
00934 {
00935
00936
00937 }
00938 }
00939
00940
00941 }
00942
00943
00944
00945
00946
00947
00948 string_to<unsigned short> toUint;
00949
00950 std::ostringstream sqlSelectNameIdCharactersTable;
00951 sqlSelectNameIdCharactersTable
00952 << "select name, id from " << CHARACTERS_TBL_NAME
00953 << " where user_id = '" << account->getID() << "';";
00954 const RecordSet& charInMemInfo =
00955 mDb->execSql(sqlSelectNameIdCharactersTable.str());
00956
00957
00958
00959 bool charFound;
00960 for (unsigned int i = 0; i < charInMemInfo.rows(); ++i)
00961 {
00962 charFound = false;
00963 for (Characters::const_iterator it = characters.begin(),
00964 it_end = characters.end(); it != it_end; ++it)
00965 {
00966 if (charInMemInfo(i, 0) == (*it)->getName())
00967 {
00968 charFound = true;
00969 break;
00970 }
00971 }
00972 if (!charFound)
00973 {
00974
00975
00976
00977
00978
00979 unsigned int charId = toUint(charInMemInfo(i, 1));
00980
00981
00982 std::ostringstream sqlDeleteInventoryTable;
00983 sqlDeleteInventoryTable
00984 << "delete from "
00985 << INVENTORIES_TBL_NAME
00986 << " where owner_id = '"
00987 << charId
00988 << "';";
00989 mDb->execSql(sqlDeleteInventoryTable.str());
00990
00991
00992 std::ostringstream sqlDeleteCharactersTable;
00993 sqlDeleteCharactersTable
00994 << "delete from "
00995 << CHARACTERS_TBL_NAME
00996 << " where id = '"
00997 << charId
00998 << "';";
00999 mDb->execSql(sqlDeleteCharactersTable.str());
01000 }
01001 }
01002 }
01003
01004
01008 void DALStorage::delAccount(AccountPtr const &account)
01009 {
01010 using namespace dal;
01011
01012 account->setCharacters(Characters());
01013 flush(account);
01014 mAccounts.erase(account->getID());
01015
01016
01017 std::ostringstream sql;
01018 sql << "delete from " << ACCOUNTS_TBL_NAME
01019 << " where id = '" << account->getID() << "';";
01020 mDb->execSql(sql.str());
01021 }
01022
01026 void DALStorage::unloadAccount(AccountPtr const &account)
01027 {
01028 flush(account);
01029 mAccounts.erase(account->getID());
01030 }