Guest User

Untitled

a guest
Jan 27th, 2019
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.75 KB | None | 0 0
  1. /**
  2. * Tibia GIMUD Server - a free and open-source MMORPG server emulator
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18.  
  19. #include "otpch.h"
  20.  
  21. #include "iologindata.h"
  22. #include "configmanager.h"
  23. #include "game.h"
  24.  
  25. extern ConfigManager g_config;
  26. extern Game g_game;
  27.  
  28. Account IOLoginData::loadAccount(uint32_t accno)
  29. {
  30. Account account;
  31.  
  32. std::ostringstream query;
  33. query << "SELECT `id`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `id` = " << accno;
  34. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  35. if (!result) {
  36. return account;
  37. }
  38.  
  39. account.id = result->getNumber<uint32_t>("id");
  40. account.accountType = static_cast<AccountType_t>(result->getNumber<int32_t>("type"));
  41. account.premiumDays = result->getNumber<uint16_t>("premdays");
  42. account.lastDay = result->getNumber<time_t>("lastday");
  43. return account;
  44. }
  45.  
  46. bool IOLoginData::saveAccount(const Account& acc)
  47. {
  48. std::ostringstream query;
  49. query << "UPDATE `accounts` SET `premdays` = " << acc.premiumDays << ", `lastday` = " << acc.lastDay << " WHERE `id` = " << acc.id;
  50. return Database::getInstance()->executeQuery(query.str());
  51. }
  52.  
  53. bool IOLoginData::loginserverAuthentication(uint32_t accountNumber, const std::string& password, Account& account)
  54. {
  55. Database* db = Database::getInstance();
  56.  
  57. std::ostringstream query;
  58. query << "SELECT `id`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `id` = " << accountNumber;
  59. result = db->storeQuery(query.str());
  60. if (!result) {
  61. return false;
  62. }
  63.  
  64. if (transformToSHA1(password) != result->getString("password")) {
  65. return false;
  66. }
  67.  
  68. account.id = result->getNumber<uint32_t>("id");
  69. account.accountType = static_cast<AccountType_t>(result->getNumber<int32_t>("type"));
  70. account.premiumDays = result->getNumber<uint16_t>("premdays");
  71. account.lastDay = result->getNumber<time_t>("lastday");
  72.  
  73. query.str(std::string());
  74. query << "SELECT `name`, `deletion` FROM `players` WHERE `account_id` = " << account.id;
  75. result = db->storeQuery(query.str());
  76. if (result) {
  77. do {
  78. if (result->getNumber<uint64_t>("deletion") == 0) {
  79. account.characters.insert(result->getString("name"));
  80. account.casts.erase(result->getString("name"));
  81. }
  82. } while (result->next());
  83. }
  84. return true;
  85. }
  86.  
  87. uint32_t IOLoginData::gameworldAuthentication(uint32_t accountNumber, const std::string& password, std::string& characterName, bool& cast)
  88. {
  89. Database* db = Database::getInstance();
  90. cast = false;
  91. if(accountNumber == 0)
  92. cast = true;
  93.  
  94. std::ostringstream query;
  95. query << "SELECT `id`, `password` FROM `accounts` WHERE `id` = " << accountNumber;
  96. DBResult_ptr result = db->storeQuery(query.str());
  97. if (!result) {
  98. return 0;
  99. }
  100.  
  101. if (transformToSHA1(password) != result->getString("password")) {
  102. return 0;
  103. }
  104.  
  105. uint32_t accountId = result->getNumber<uint32_t>("id");
  106.  
  107. query.str(std::string());
  108. query << "SELECT `account_id`, `name`, `deletion` FROM `players` WHERE `name` = " << db->escapeString(characterName);
  109. result = db->storeQuery(query.str());
  110. if (!result) {
  111. return 0;
  112. }
  113.  
  114. if(result->getNumber<uint32_t>("account_id") != accountId)
  115. cast = true;
  116.  
  117. if (result->getNumber<uint32_t>("account_id") != accountId || result->getNumber<uint64_t>("deletion") != 0) {
  118. return 0;
  119. }
  120. characterName = result->getString("name");
  121. return accountId;
  122. }
  123.  
  124. AccountType_t IOLoginData::getAccountType(uint32_t accountId)
  125. {
  126. std::ostringstream query;
  127. query << "SELECT `type` FROM `accounts` WHERE `id` = " << accountId;
  128. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  129. if (!result) {
  130. return ACCOUNT_TYPE_NORMAL;
  131. }
  132. return static_cast<AccountType_t>(result->getNumber<uint16_t>("type"));
  133. }
  134.  
  135. void IOLoginData::setAccountType(uint32_t accountId, AccountType_t accountType)
  136. {
  137. std::ostringstream query;
  138. query << "UPDATE `accounts` SET `type` = " << static_cast<uint16_t>(accountType) << " WHERE `id` = " << accountId;
  139. Database::getInstance()->executeQuery(query.str());
  140. }
  141.  
  142. void IOLoginData::updateOnlineStatus(uint32_t guid, bool login, bool broadcasting, const std::string& cast_password,
  143. const std::string& cast_description, uint32_t spectators)
  144. {
  145. if (g_config.getBoolean(ConfigManager::ALLOW_CLONES)) {
  146. return;
  147. }
  148.  
  149. Database* db = Database::getInstance();
  150. std::ostringstream query;
  151. if (login) {
  152. query << "INSERT INTO `players_online` (`player_id`, `broadcasting`, `password`, `description`, `spectators`) VALUES "
  153. "(" << guid << ", " << broadcasting << ", " << db->escapeString(cast_password) << ", " << db->escapeString(cast_description) << ", " << spectators << ")";
  154. } else {
  155. query << "UPDATE `players_online` SET "
  156. "`broadcasting` = " << broadcasting << ", "
  157. "`password` = " << db->escapeString(cast_password) << ", "
  158. "`description` = " << db->escapeString(cast_description) << ", "
  159. "`spectators` = " << spectators << " "
  160. " WHERE `player_id` = " << guid;
  161. }
  162. db->executeQuery(query.str());
  163. }
  164.  
  165. void IOLoginData::removeOnlineStatus(uint32_t guid)
  166. {
  167. if (g_config.getBoolean(ConfigManager::ALLOW_CLONES)) {
  168. return;
  169. }
  170.  
  171. std::ostringstream query;
  172. query << "DELETE FROM `players_online` WHERE `player_id` = " << guid;
  173. Database::getInstance()->executeQuery(query.str());
  174. }
  175.  
  176. bool IOLoginData::preloadPlayer(Player* player, const std::string& name)
  177. {
  178. Database* db = Database::getInstance();
  179.  
  180. std::ostringstream query;
  181. query << "SELECT `id`, `account_id`, `group_id`, `deletion`, (SELECT `type` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `account_type`";
  182. if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  183. query << ", (SELECT `premdays` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `premium_days`";
  184. }
  185. query << " FROM `players` WHERE `name` = " << db->escapeString(name);
  186. DBResult_ptr result = db->storeQuery(query.str());
  187. if (!result) {
  188. return false;
  189. }
  190.  
  191. if (result->getNumber<uint64_t>("deletion") != 0) {
  192. return false;
  193. }
  194.  
  195. player->setGUID(result->getNumber<uint32_t>("id"));
  196. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  197. if (!group) {
  198. std::cout << "[Error - IOLoginData::preloadPlayer] " << player->name << " has Group ID " << result->getNumber<uint16_t>("group_id") << " which doesn't exist." << std::endl;
  199. return false;
  200. }
  201. player->setGroup(group);
  202. player->accountNumber = result->getNumber<uint32_t>("account_id");
  203. player->accountType = static_cast<AccountType_t>(result->getNumber<uint16_t>("account_type"));
  204. if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  205. player->premiumDays = result->getNumber<uint16_t>("premium_days");
  206. } else {
  207. player->premiumDays = std::numeric_limits<uint16_t>::max();
  208. }
  209. return true;
  210. }
  211.  
  212. bool IOLoginData::loadPlayerById(Player* player, uint32_t id)
  213. {
  214. std::ostringstream query;
  215. query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `id` = " << id;
  216. return loadPlayer(player, Database::getInstance()->storeQuery(query.str()));
  217. }
  218.  
  219. bool IOLoginData::loadPlayerByName(Player* player, const std::string& name)
  220. {
  221. Database* db = Database::getInstance();
  222. std::ostringstream query;
  223. query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `name` = " << db->escapeString(name);
  224. return loadPlayer(player, db->storeQuery(query.str()));
  225. }
  226.  
  227. bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
  228. {
  229. if (!result) {
  230. return false;
  231. }
  232.  
  233. Database* db = Database::getInstance();
  234.  
  235. uint32_t accno = result->getNumber<uint32_t>("account_id");
  236. Account acc = loadAccount(accno);
  237.  
  238. player->setGUID(result->getNumber<uint32_t>("id"));
  239. player->name = result->getString("name");
  240. player->accountNumber = accno;
  241.  
  242. player->accountType = acc.accountType;
  243.  
  244. if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  245. player->premiumDays = std::numeric_limits<uint16_t>::max();
  246. } else {
  247. player->premiumDays = acc.premiumDays;
  248. }
  249.  
  250. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  251. if (!group) {
  252. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Group ID " << result->getNumber<uint16_t>("group_id") << " which doesn't exist" << std::endl;
  253. return false;
  254. }
  255. player->setGroup(group);
  256.  
  257. player->bankBalance = result->getNumber<uint64_t>("balance");
  258.  
  259. player->setSex(static_cast<PlayerSex_t>(result->getNumber<uint16_t>("sex")));
  260. player->level = std::max<uint32_t>(1, result->getNumber<uint32_t>("level"));
  261.  
  262. uint64_t experience = result->getNumber<uint64_t>("experience");
  263.  
  264. uint64_t currExpCount = Player::getExpForLevel(player->level);
  265. uint64_t nextExpCount = Player::getExpForLevel(player->level + 1);
  266. if (experience < currExpCount || experience > nextExpCount) {
  267. experience = currExpCount;
  268. }
  269.  
  270. player->experience = experience;
  271.  
  272. if (currExpCount < nextExpCount) {
  273. player->levelPercent = Player::getPercentLevel(player->experience - currExpCount, nextExpCount - currExpCount);
  274. } else {
  275. player->levelPercent = 0;
  276. }
  277.  
  278. player->soul = result->getNumber<uint16_t>("soul");
  279. player->capacity = std::max<uint32_t>(400, result->getNumber<uint32_t>("cap")) * 100;
  280. player->blessings = result->getNumber<uint16_t>("blessings");
  281.  
  282. unsigned long conditionsSize;
  283. const char* conditions = result->getStream("conditions", conditionsSize);
  284. PropStream propStream;
  285. propStream.init(conditions, conditionsSize);
  286.  
  287. Condition* condition = Condition::createCondition(propStream);
  288. while (condition) {
  289. if (condition->unserialize(propStream)) {
  290. player->storedConditionList.push_front(condition);
  291. } else {
  292. delete condition;
  293. }
  294. condition = Condition::createCondition(propStream);
  295. }
  296.  
  297. if (!player->setVocation(result->getNumber<uint16_t>("vocation"))) {
  298. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Vocation ID " << result->getNumber<uint16_t>("vocation") << " which doesn't exist" << std::endl;
  299. return false;
  300. }
  301.  
  302. player->mana = result->getNumber<uint32_t>("mana");
  303. player->manaMax = result->getNumber<uint32_t>("manamax");
  304. player->magLevel = result->getNumber<uint32_t>("maglevel");
  305.  
  306. uint64_t nextManaCount = player->vocation->getReqMana(player->magLevel + 1);
  307. uint64_t manaSpent = result->getNumber<uint64_t>("manaspent");
  308. if (manaSpent > nextManaCount) {
  309. manaSpent = 0;
  310. }
  311.  
  312. player->manaSpent = manaSpent;
  313. player->magLevelPercent = Player::getPercentLevel(player->manaSpent, nextManaCount);
  314.  
  315. player->health = result->getNumber<int32_t>("health");
  316. player->healthMax = result->getNumber<int32_t>("healthmax");
  317.  
  318. player->defaultOutfit.lookType = result->getNumber<uint16_t>("looktype");
  319. player->defaultOutfit.lookHead = result->getNumber<uint16_t>("lookhead");
  320. player->defaultOutfit.lookBody = result->getNumber<uint16_t>("lookbody");
  321. player->defaultOutfit.lookLegs = result->getNumber<uint16_t>("looklegs");
  322. player->defaultOutfit.lookFeet = result->getNumber<uint16_t>("lookfeet");
  323. player->currentOutfit = player->defaultOutfit;
  324.  
  325. if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
  326. player->playerKillerEnd = result->getNumber<time_t>("skulltime");
  327.  
  328. uint16_t skull = result->getNumber<uint16_t>("skull");
  329. if (skull == SKULL_RED) {
  330. player->skull = SKULL_RED;
  331. }
  332.  
  333. if (player->playerKillerEnd == 0) {
  334. player->skull = SKULL_NONE;
  335. }
  336. }
  337.  
  338. player->loginPosition.x = result->getNumber<uint16_t>("posx");
  339. player->loginPosition.y = result->getNumber<uint16_t>("posy");
  340. player->loginPosition.z = result->getNumber<uint16_t>("posz");
  341.  
  342. player->lastLoginSaved = result->getNumber<time_t>("lastlogin");
  343. player->lastLogout = result->getNumber<time_t>("lastlogout");
  344.  
  345. Town* town = g_game.map.towns.getTown(result->getNumber<uint32_t>("town_id"));
  346. if (!town) {
  347. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Town ID " << result->getNumber<uint32_t>("town_id") << " which doesn't exist" << std::endl;
  348. return false;
  349. }
  350.  
  351. player->town = town;
  352.  
  353. const Position& loginPos = player->loginPosition;
  354. if (loginPos.x == 0 && loginPos.y == 0 && loginPos.z == 0) {
  355. player->loginPosition = player->getTemplePosition();
  356. }
  357.  
  358. static const std::string skillNames[] = {"skill_fist", "skill_club", "skill_sword", "skill_axe", "skill_dist", "skill_shielding", "skill_fishing"};
  359. static const std::string skillNameTries[] = {"skill_fist_tries", "skill_club_tries", "skill_sword_tries", "skill_axe_tries", "skill_dist_tries", "skill_shielding_tries", "skill_fishing_tries"};
  360. static constexpr size_t size = sizeof(skillNames) / sizeof(std::string);
  361. for (uint8_t i = 0; i < size; ++i) {
  362. uint16_t skillLevel = result->getNumber<uint16_t>(skillNames[i]);
  363. uint64_t skillTries = result->getNumber<uint64_t>(skillNameTries[i]);
  364. uint64_t nextSkillTries = player->vocation->getReqSkillTries(i, skillLevel + 1);
  365. if (skillTries > nextSkillTries) {
  366. skillTries = 0;
  367. }
  368.  
  369. player->skills[i].level = skillLevel;
  370. player->skills[i].tries = skillTries;
  371. player->skills[i].percent = Player::getPercentLevel(skillTries, nextSkillTries);
  372. }
  373.  
  374. std::ostringstream query;
  375.  
  376. query << "SELECT `date` FROM `player_murders` WHERE `player_id` = " << player->getGUID() << " ORDER BY `date` ASC";
  377. if ((result = db->storeQuery(query.str()))) {
  378. do {
  379. player->murderTimeStamps.push_back(result->getNumber<time_t>("date"));
  380. } while (result->next());
  381. }
  382.  
  383. query.str(std::string());
  384. query << "SELECT `guild_id`, `rank_id`, `nick` FROM `guild_membership` WHERE `player_id` = " << player->getGUID();
  385. if ((result = db->storeQuery(query.str()))) {
  386. uint32_t guildId = result->getNumber<uint32_t>("guild_id");
  387. uint32_t playerRankId = result->getNumber<uint32_t>("rank_id");
  388. player->guildNick = result->getString("nick");
  389.  
  390. Guild* guild = g_game.getGuild(guildId);
  391. if (!guild) {
  392. query.str(std::string());
  393. query << "SELECT `name` FROM `guilds` WHERE `id` = " << guildId;
  394. if ((result = db->storeQuery(query.str()))) {
  395. guild = new Guild(guildId, result->getString("name"));
  396. g_game.addGuild(guild);
  397.  
  398. query.str(std::string());
  399. query << "SELECT `id`, `name`, `level` FROM `guild_ranks` WHERE `guild_id` = " << guildId;
  400.  
  401. if ((result = db->storeQuery(query.str()))) {
  402. do {
  403. guild->addRank(result->getNumber<uint32_t>("id"), result->getString("name"), result->getNumber<uint16_t>("level"));
  404. } while (result->next());
  405. }
  406. }
  407. }
  408.  
  409. if (guild) {
  410. player->guild = guild;
  411. const GuildRank* rank = guild->getRankById(playerRankId);
  412. if (!rank) {
  413. query.str(std::string());
  414. query << "SELECT `id`, `name`, `level` FROM `guild_ranks` WHERE `id` = " << playerRankId;
  415.  
  416. if ((result = db->storeQuery(query.str()))) {
  417. guild->addRank(result->getNumber<uint32_t>("id"), result->getString("name"), result->getNumber<uint16_t>("level"));
  418. }
  419.  
  420. rank = guild->getRankById(playerRankId);
  421. if (!rank) {
  422. player->guild = nullptr;
  423. }
  424. }
  425.  
  426. player->guildRank = rank;
  427.  
  428. IOGuild::getWarList(guildId, player->guildWarList);
  429.  
  430. query.str(std::string());
  431. query << "SELECT COUNT(*) AS `members` FROM `guild_membership` WHERE `guild_id` = " << guildId;
  432. if ((result = db->storeQuery(query.str()))) {
  433. guild->setMemberCount(result->getNumber<uint32_t>("members"));
  434. }
  435. }
  436. }
  437.  
  438. query.str(std::string());
  439. query << "SELECT `player_id`, `name` FROM `player_spells` WHERE `player_id` = " << player->getGUID();
  440. if ((result = db->storeQuery(query.str()))) {
  441. do {
  442. player->learnedInstantSpellList.emplace_front(result->getString("name"));
  443. } while (result->next());
  444. }
  445.  
  446. //load inventory items
  447. ItemMap itemMap;
  448.  
  449. query.str(std::string());
  450. query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_items` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";
  451. if ((result = db->storeQuery(query.str()))) {
  452. loadItems(itemMap, result);
  453.  
  454. for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
  455. const std::pair<Item*, int32_t>& pair = it->second;
  456. Item* item = pair.first;
  457. int32_t pid = pair.second;
  458. if (pid >= 1 && pid <= 10) {
  459. player->internalAddThing(pid, item);
  460. } else {
  461. ItemMap::const_iterator it2 = itemMap.find(pid);
  462. if (it2 == itemMap.end()) {
  463. continue;
  464. }
  465.  
  466. Container* container = it2->second.first->getContainer();
  467. if (container) {
  468. container->internalAddThing(item);
  469. }
  470. }
  471. }
  472. }
  473.  
  474. //load depot items
  475. itemMap.clear();
  476.  
  477. query.str(std::string());
  478. query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_depotitems` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";
  479. if ((result = db->storeQuery(query.str()))) {
  480. loadItems(itemMap, result);
  481.  
  482. for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
  483. const std::pair<Item*, int32_t>& pair = it->second;
  484. Item* item = pair.first;
  485.  
  486. int32_t pid = pair.second;
  487. if (pid >= 0 && pid < 100) {
  488. Container* itemContainer = item->getContainer();
  489. if (itemContainer) {
  490. DepotLocker* locker = itemContainer->getDepotLocker();
  491. if (locker) {
  492. DepotLocker* existingLocker = player->getDepotLocker(pid, false);
  493. if (!existingLocker) {
  494. player->depotLockerMap[pid] = locker;
  495. }
  496. }
  497. }
  498. } else {
  499. ItemMap::const_iterator it2 = itemMap.find(pid);
  500. if (it2 == itemMap.end()) {
  501. continue;
  502. }
  503.  
  504. Container* container = it2->second.first->getContainer();
  505. if (container) {
  506. container->internalAddThing(item);
  507. }
  508. }
  509. }
  510. }
  511.  
  512. //load storage map
  513. query.str(std::string());
  514. query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID();
  515. if ((result = db->storeQuery(query.str()))) {
  516. do {
  517. player->addStorageValue(result->getNumber<uint32_t>("key"), result->getNumber<int32_t>("value"));
  518. } while (result->next());
  519. }
  520.  
  521. //load vip
  522. query.str(std::string());
  523. query << "SELECT `player_id` FROM `account_viplist` WHERE `account_id` = " << player->getAccount();
  524. if ((result = db->storeQuery(query.str()))) {
  525. do {
  526. player->addVIPInternal(result->getNumber<uint32_t>("player_id"));
  527. } while (result->next());
  528. }
  529.  
  530. player->updateBaseSpeed();
  531. player->updateInventoryWeight();
  532. player->updateItemsLight(true);
  533. return true;
  534. }
  535.  
  536. bool IOLoginData::saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream)
  537. {
  538. std::ostringstream ss;
  539.  
  540. typedef std::pair<Container*, int32_t> containerBlock;
  541. std::list<containerBlock> queue;
  542.  
  543. int32_t runningId = 100;
  544.  
  545. Database* db = Database::getInstance();
  546. for (const auto& it : itemList) {
  547. int32_t pid = it.first;
  548. Item* item = it.second;
  549. ++runningId;
  550.  
  551. propWriteStream.clear();
  552. item->serializeAttr(propWriteStream);
  553.  
  554. size_t attributesSize;
  555. const char* attributes = propWriteStream.getStream(attributesSize);
  556.  
  557. ss << player->getGUID() << ',' << pid << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize);
  558. if (!query_insert.addRow(ss)) {
  559. return false;
  560. }
  561.  
  562. if (Container* container = item->getContainer()) {
  563. queue.emplace_back(container, runningId);
  564. }
  565. }
  566.  
  567. while (!queue.empty()) {
  568. const containerBlock& cb = queue.front();
  569. Container* container = cb.first;
  570. int32_t parentId = cb.second;
  571. queue.pop_front();
  572.  
  573. for (Item* item : container->getItemList()) {
  574. ++runningId;
  575.  
  576. Container* subContainer = item->getContainer();
  577. if (subContainer) {
  578. queue.emplace_back(subContainer, runningId);
  579. }
  580.  
  581. propWriteStream.clear();
  582. item->serializeAttr(propWriteStream);
  583.  
  584. size_t attributesSize;
  585. const char* attributes = propWriteStream.getStream(attributesSize);
  586.  
  587. ss << player->getGUID() << ',' << parentId << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize);
  588. if (!query_insert.addRow(ss)) {
  589. return false;
  590. }
  591. }
  592. }
  593. return query_insert.execute();
  594. }
  595.  
  596. bool IOLoginData::savePlayer(Player* player)
  597. {
  598. if (player->getHealth() <= 0) {
  599. player->changeHealth(1);
  600. }
  601.  
  602. Database* db = Database::getInstance();
  603.  
  604. std::ostringstream query;
  605. query << "SELECT `save` FROM `players` WHERE `id` = " << player->getGUID();
  606. DBResult_ptr result = db->storeQuery(query.str());
  607. if (!result) {
  608. return false;
  609. }
  610.  
  611. if (result->getNumber<uint16_t>("save") == 0) {
  612. query.str(std::string());
  613. query << "UPDATE `players` SET `lastlogin` = " << player->lastLoginSaved << ", `lastip` = " << player->lastIP << " WHERE `id` = " << player->getGUID();
  614. return db->executeQuery(query.str());
  615. }
  616.  
  617. //serialize conditions
  618. PropWriteStream propWriteStream;
  619. for (Condition* condition : player->conditions) {
  620. if (condition->isPersistent()) {
  621. condition->serialize(propWriteStream);
  622. propWriteStream.write<uint8_t>(CONDITIONATTR_END);
  623. }
  624. }
  625.  
  626. size_t conditionsSize;
  627. const char* conditions = propWriteStream.getStream(conditionsSize);
  628.  
  629. //First, an UPDATE query to write the player itself
  630. query.str(std::string());
  631. query << "UPDATE `players` SET ";
  632. query << "`level` = " << player->level << ',';
  633. query << "`group_id` = " << player->group->id << ',';
  634. query << "`vocation` = " << player->getVocationId() << ',';
  635. query << "`health` = " << player->health << ',';
  636. query << "`healthmax` = " << player->healthMax << ',';
  637. query << "`experience` = " << player->experience << ',';
  638. query << "`lookbody` = " << static_cast<uint32_t>(player->defaultOutfit.lookBody) << ',';
  639. query << "`lookfeet` = " << static_cast<uint32_t>(player->defaultOutfit.lookFeet) << ',';
  640. query << "`lookhead` = " << static_cast<uint32_t>(player->defaultOutfit.lookHead) << ',';
  641. query << "`looklegs` = " << static_cast<uint32_t>(player->defaultOutfit.lookLegs) << ',';
  642. query << "`looktype` = " << player->defaultOutfit.lookType << ',';
  643. query << "`maglevel` = " << player->magLevel << ',';
  644. query << "`mana` = " << player->mana << ',';
  645. query << "`manamax` = " << player->manaMax << ',';
  646. query << "`manaspent` = " << player->manaSpent << ',';
  647. query << "`soul` = " << static_cast<uint16_t>(player->soul) << ',';
  648. query << "`town_id` = " << player->town->getID() << ',';
  649.  
  650. const Position& loginPosition = player->getLoginPosition();
  651. query << "`posx` = " << loginPosition.getX() << ',';
  652. query << "`posy` = " << loginPosition.getY() << ',';
  653. query << "`posz` = " << loginPosition.getZ() << ',';
  654.  
  655. query << "`cap` = " << (player->capacity / 100) << ',';
  656. query << "`sex` = " << player->sex << ',';
  657.  
  658. if (player->lastLoginSaved != 0) {
  659. query << "`lastlogin` = " << player->lastLoginSaved << ',';
  660. }
  661.  
  662. if (player->lastIP != 0) {
  663. query << "`lastip` = " << player->lastIP << ',';
  664. }
  665.  
  666. query << "`conditions` = " << db->escapeBlob(conditions, conditionsSize) << ',';
  667.  
  668. if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
  669. query << "`skulltime` = " << player->getPlayerKillerEnd() << ',';
  670.  
  671. Skulls_t skull = SKULL_NONE;
  672. if (player->skull == SKULL_RED) {
  673. skull = SKULL_RED;
  674. }
  675.  
  676. query << "`skull` = " << static_cast<uint32_t>(skull) << ',';
  677. }
  678.  
  679. query << "`lastlogout` = " << player->getLastLogout() << ',';
  680. query << "`balance` = " << player->bankBalance << ',';
  681.  
  682. query << "`skill_fist` = " << player->skills[SKILL_FIST].level << ',';
  683. query << "`skill_fist_tries` = " << player->skills[SKILL_FIST].tries << ',';
  684. query << "`skill_club` = " << player->skills[SKILL_CLUB].level << ',';
  685. query << "`skill_club_tries` = " << player->skills[SKILL_CLUB].tries << ',';
  686. query << "`skill_sword` = " << player->skills[SKILL_SWORD].level << ',';
  687. query << "`skill_sword_tries` = " << player->skills[SKILL_SWORD].tries << ',';
  688. query << "`skill_axe` = " << player->skills[SKILL_AXE].level << ',';
  689. query << "`skill_axe_tries` = " << player->skills[SKILL_AXE].tries << ',';
  690. query << "`skill_dist` = " << player->skills[SKILL_DISTANCE].level << ',';
  691. query << "`skill_dist_tries` = " << player->skills[SKILL_DISTANCE].tries << ',';
  692. query << "`skill_shielding` = " << player->skills[SKILL_SHIELD].level << ',';
  693. query << "`skill_shielding_tries` = " << player->skills[SKILL_SHIELD].tries << ',';
  694. query << "`skill_fishing` = " << player->skills[SKILL_FISHING].level << ',';
  695. query << "`skill_fishing_tries` = " << player->skills[SKILL_FISHING].tries << ',';
  696.  
  697. if (!player->isOffline()) {
  698. query << "`onlinetime` = `onlinetime` + " << (time(nullptr) - player->lastLoginSaved) << ',';
  699. }
  700. query << "`blessings` = " << static_cast<uint32_t>(player->blessings);
  701. query << " WHERE `id` = " << player->getGUID();
  702.  
  703. DBTransaction transaction;
  704. if (!transaction.begin()) {
  705. return false;
  706. }
  707.  
  708. if (!db->executeQuery(query.str())) {
  709. return false;
  710. }
  711.  
  712. // learned spells
  713. query.str(std::string());
  714. query << "DELETE FROM `player_spells` WHERE `player_id` = " << player->getGUID();
  715. if (!db->executeQuery(query.str())) {
  716. return false;
  717. }
  718.  
  719. query.str(std::string());
  720.  
  721. DBInsert spellsQuery("INSERT INTO `player_spells` (`player_id`, `name` ) VALUES ");
  722. for (const std::string& spellName : player->learnedInstantSpellList) {
  723. query << player->getGUID() << ',' << db->escapeString(spellName);
  724. if (!spellsQuery.addRow(query)) {
  725. return false;
  726. }
  727. }
  728.  
  729. if (!spellsQuery.execute()) {
  730. return false;
  731. }
  732.  
  733. query.str(std::string());
  734. query << "DELETE FROM `player_murders` WHERE `player_id` = " << player->getGUID();
  735.  
  736. if (!db->executeQuery(query.str())) {
  737. return false;
  738. }
  739.  
  740. query.str(std::string());
  741.  
  742. DBInsert murdersQuery("INSERT INTO `player_murders`(`id`, `player_id`, `date`) VALUES ");
  743. for (time_t timestamp : player->murderTimeStamps) {
  744. query << "NULL," << player->getGUID() << ',' << timestamp;
  745. if (!murdersQuery.addRow(query)) {
  746. return false;
  747. }
  748. }
  749.  
  750. if (!murdersQuery.execute()) {
  751. return false;
  752. }
  753.  
  754. //item saving
  755. query.str(std::string());
  756. query << "DELETE FROM `player_items` WHERE `player_id` = " << player->getGUID();
  757. if (!db->executeQuery(query.str())) {
  758. return false;
  759. }
  760.  
  761. DBInsert itemsQuery("INSERT INTO `player_items` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
  762.  
  763. ItemBlockList itemList;
  764. for (int32_t slotId = 1; slotId <= 10; ++slotId) {
  765. Item* item = player->inventory[slotId];
  766. if (item) {
  767. itemList.emplace_back(slotId, item);
  768. }
  769. }
  770.  
  771. if (!saveItems(player, itemList, itemsQuery, propWriteStream)) {
  772. return false;
  773. }
  774.  
  775. //save depot items
  776. query.str(std::string());
  777. query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
  778.  
  779. if (!db->executeQuery(query.str())) {
  780. return false;
  781. }
  782.  
  783. DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
  784. itemList.clear();
  785.  
  786. for (const auto& it : player->depotLockerMap) {
  787. itemList.emplace_back(it.first, it.second);
  788. }
  789.  
  790. if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
  791. return false;
  792. }
  793.  
  794. query.str(std::string());
  795. query << "DELETE FROM `player_storage` WHERE `player_id` = " << player->getGUID();
  796. if (!db->executeQuery(query.str())) {
  797. return false;
  798. }
  799.  
  800. query.str(std::string());
  801.  
  802. DBInsert storageQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES ");
  803.  
  804. for (const auto& it : player->storageMap) {
  805. query << player->getGUID() << ',' << it.first << ',' << it.second;
  806. if (!storageQuery.addRow(query)) {
  807. return false;
  808. }
  809. }
  810.  
  811. if (!storageQuery.execute()) {
  812. return false;
  813. }
  814.  
  815. //End the transaction
  816. return transaction.commit();
  817. }
  818.  
  819. std::string IOLoginData::getNameByGuid(uint32_t guid)
  820. {
  821. std::ostringstream query;
  822. query << "SELECT `name` FROM `players` WHERE `id` = " << guid;
  823. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  824. if (!result) {
  825. return std::string();
  826. }
  827. return result->getString("name");
  828. }
  829.  
  830. uint32_t IOLoginData::getGuidByName(const std::string& name)
  831. {
  832. Database* db = Database::getInstance();
  833.  
  834. std::ostringstream query;
  835. query << "SELECT `id` FROM `players` WHERE `name` = " << db->escapeString(name);
  836. DBResult_ptr result = db->storeQuery(query.str());
  837. if (!result) {
  838. return 0;
  839. }
  840. return result->getNumber<uint32_t>("id");
  841. }
  842.  
  843. bool IOLoginData::getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name)
  844. {
  845. Database* db = Database::getInstance();
  846.  
  847. std::ostringstream query;
  848. query << "SELECT `name`, `id`, `group_id`, `account_id` FROM `players` WHERE `name` = " << db->escapeString(name);
  849. DBResult_ptr result = db->storeQuery(query.str());
  850. if (!result) {
  851. return false;
  852. }
  853.  
  854. name = result->getString("name");
  855. guid = result->getNumber<uint32_t>("id");
  856. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  857.  
  858. uint64_t flags;
  859. if (group) {
  860. flags = group->flags;
  861. } else {
  862. flags = 0;
  863. }
  864.  
  865. specialVip = (flags & PlayerFlag_SpecialVIP) != 0;
  866. return true;
  867. }
  868.  
  869. bool IOLoginData::formatPlayerName(std::string& name)
  870. {
  871. Database* db = Database::getInstance();
  872.  
  873. std::ostringstream query;
  874. query << "SELECT `name` FROM `players` WHERE `name` = " << db->escapeString(name);
  875.  
  876. DBResult_ptr result = db->storeQuery(query.str());
  877. if (!result) {
  878. return false;
  879. }
  880.  
  881. name = result->getString("name");
  882. return true;
  883. }
  884.  
  885. void IOLoginData::loadItems(ItemMap& itemMap, DBResult_ptr result)
  886. {
  887. do {
  888. uint32_t sid = result->getNumber<uint32_t>("sid");
  889. uint32_t pid = result->getNumber<uint32_t>("pid");
  890. uint16_t type = result->getNumber<uint16_t>("itemtype");
  891. uint16_t count = result->getNumber<uint16_t>("count");
  892.  
  893. unsigned long attrSize;
  894. const char* attr = result->getStream("attributes", attrSize);
  895.  
  896. PropStream propStream;
  897. propStream.init(attr, attrSize);
  898.  
  899. Item* item = Item::CreateItem(type, count);
  900. if (item) {
  901. if (!item->unserializeAttr(propStream)) {
  902. std::cout << "WARNING: Serialize error in IOLoginData::loadItems" << std::endl;
  903. }
  904.  
  905. std::pair<Item*, uint32_t> pair(item, pid);
  906. itemMap[sid] = pair;
  907. }
  908. } while (result->next());
  909. }
  910.  
  911. void IOLoginData::increaseBankBalance(uint32_t guid, uint64_t bankBalance)
  912. {
  913. std::ostringstream query;
  914. query << "UPDATE `players` SET `balance` = `balance` + " << bankBalance << " WHERE `id` = " << guid;
  915. Database::getInstance()->executeQuery(query.str());
  916. }
  917.  
  918. bool IOLoginData::hasBiddedOnHouse(uint32_t guid)
  919. {
  920. Database* db = Database::getInstance();
  921.  
  922. std::ostringstream query;
  923. query << "SELECT `id` FROM `houses` WHERE `highest_bidder` = " << guid << " LIMIT 1";
  924. return db->storeQuery(query.str()).get() != nullptr;
  925. }
  926.  
  927. std::forward_list<VIPEntry> IOLoginData::getVIPEntries(uint32_t accountId)
  928. {
  929. std::forward_list<VIPEntry> entries;
  930.  
  931. std::ostringstream query;
  932. query << "SELECT `player_id`, (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `name` FROM `account_viplist` WHERE `account_id` = " << accountId;
  933.  
  934. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  935. if (result) {
  936. do {
  937. entries.emplace_front(
  938. result->getNumber<uint32_t>("player_id"),
  939. result->getString("name")
  940. );
  941. } while (result->next());
  942. }
  943. return entries;
  944. }
  945.  
  946. void IOLoginData::addVIPEntry(uint32_t accountId, uint32_t guid)
  947. {
  948. Database* db = Database::getInstance();
  949.  
  950. std::ostringstream query;
  951. query << "INSERT INTO `account_viplist` (`account_id`, `player_id`) VALUES (" << accountId << ',' << guid << ')';
  952. db->executeQuery(query.str());
  953. }
  954.  
  955. void IOLoginData::removeVIPEntry(uint32_t accountId, uint32_t guid)
  956. {
  957. std::ostringstream query;
  958. query << "DELETE FROM `account_viplist` WHERE `account_id` = " << accountId << " AND `player_id` = " << guid;
  959. Database::getInstance()->executeQuery(query.str());
  960. }
  961.  
  962. void IOLoginData::addPremiumDays(uint32_t accountId, int32_t addDays)
  963. {
  964. std::ostringstream query;
  965. query << "UPDATE `accounts` SET `premdays` = `premdays` + " << addDays << " WHERE `id` = " << accountId;
  966. Database::getInstance()->executeQuery(query.str());
  967. }
  968.  
  969. void IOLoginData::removePremiumDays(uint32_t accountId, int32_t removeDays)
  970. {
  971. std::ostringstream query;
  972. query << "UPDATE `accounts` SET `premdays` = `premdays` - " << removeDays << " WHERE `id` = " << accountId;
  973. Database::getInstance()->executeQuery(query.str());
  974. }
Advertisement
Add Comment
Please, Sign In to add comment