Advertisement
Guest User

Untitled

a guest
May 2nd, 2022
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 48.00 KB | None | 0 0
  1. /**
  2. * The Forgotten Server - a free and open-source MMORPG server emulator
  3. * Copyright (C) 2016 Mark Samman <mark.samman@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19.  
  20. #include "otpch.h"
  21.  
  22. #include "iologindata.h"
  23. #include "configmanager.h"
  24. #include "game.h"
  25.  
  26. #include "vocation.h"
  27. // --
  28.  
  29. extern ConfigManager g_config;
  30. extern Game g_game;
  31.  
  32. extern Vocation g_vocations;
  33. // --
  34.  
  35. Account IOLoginData::loadAccount(uint32_t accno)
  36. {
  37. Account account;
  38.  
  39. std::ostringstream query;
  40. query << "SELECT `id`, `name`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `id` = " << accno;
  41. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  42. if (!result) {
  43. return account;
  44. }
  45.  
  46. account.id = result->getNumber<uint32_t>("id");
  47. account.name = result->getNumber<uint32_t>("name");
  48. account.accountType = static_cast<AccountType_t>(result->getNumber<int32_t>("type"));
  49. account.premiumDays = result->getNumber<uint16_t>("premdays");
  50. account.lastDay = result->getNumber<time_t>("lastday");
  51. return account;
  52. }
  53.  
  54. bool IOLoginData::saveAccount(const Account& acc)
  55. {
  56. std::ostringstream query;
  57. query << "UPDATE `accounts` SET `premdays` = " << acc.premiumDays << ", `lastday` = " << acc.lastDay << " WHERE `id` = " << acc.id;
  58. return Database::getInstance()->executeQuery(query.str());
  59. }
  60.  
  61. bool IOLoginData::loginserverAuthentication(uint32_t accountName, const std::string& password, Account& account)
  62. {
  63. Database* db = Database::getInstance();
  64.  
  65. std::ostringstream query;
  66. query << "SELECT `id`, `name`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `name` = " << accountName;
  67. DBResult_ptr result = db->storeQuery(query.str());
  68. if (!result) {
  69. return false;
  70. }
  71.  
  72. if (transformToSHA1(password) != result->getString("password")) {
  73. return false;
  74. }
  75.  
  76. account.id = result->getNumber<uint32_t>("id");
  77. account.name = result->getNumber<uint32_t>("name");
  78. account.accountType = static_cast<AccountType_t>(result->getNumber<int32_t>("type"));
  79. account.premiumDays = result->getNumber<uint16_t>("premdays");
  80. account.lastDay = result->getNumber<time_t>("lastday");
  81.  
  82. query.str(std::string());
  83. query << "SELECT `name`, `deletion` FROM `players` WHERE `account_id` = " << account.id;
  84. result = db->storeQuery(query.str());
  85.  
  86. if(!result){
  87. // give the account the account manager to use if they have no account
  88. account.characters.push_back("Account Manager");
  89. return true;
  90. }
  91. // --
  92. if (result) {
  93. // allow them to access the account manager if there are players on the account
  94. if (account.id != 1){
  95. account.characters.push_back("Account Manager");
  96. }
  97. do {
  98. if (result->getNumber<uint64_t>("deletion") == 0) {
  99. account.characters.push_back(result->getString("name"));
  100. }
  101. } while (result->next());
  102. std::sort(account.characters.begin(), account.characters.end());
  103. }
  104. return true;
  105. }
  106.  
  107.  
  108.  
  109. bool IOLoginData::getAccountId(const uint32_t name, uint32_t& number)
  110. {
  111. if(!name)
  112. return false;
  113.  
  114. Database* db = Database::getInstance();
  115. std::ostringstream query;
  116. query << "SELECT `id` FROM `accounts` WHERE `name` LIKE " << name << " LIMIT 1;";
  117.  
  118. DBResult_ptr result;
  119. if(!(result = db->storeQuery(query.str())))
  120. return false;
  121.  
  122. number = result->getNumber<uint32_t>("id");
  123. return true;
  124. }
  125. // --
  126.  
  127. uint32_t IOLoginData::gameworldAuthentication(uint32_t accountName, const std::string& password, std::string& characterName)
  128. {
  129. Database* db = Database::getInstance();
  130.  
  131. std::ostringstream query;
  132. query << "SELECT `id`, `password` FROM `accounts` WHERE `name` = " << accountName;
  133. DBResult_ptr result = db->storeQuery(query.str());
  134. if (!result) {
  135. return 0;
  136. }
  137.  
  138. if (transformToSHA1(password) != result->getString("password")) {
  139. return 0;
  140. }
  141.  
  142. uint32_t accountId = result->getNumber<uint32_t>("id");
  143.  
  144. query.str(std::string());
  145. query << "SELECT `account_id`, `name`, `deletion` FROM `players` WHERE `name` = " << db->escapeString(characterName);
  146. result = db->storeQuery(query.str());
  147. if (!result) {
  148. return 0;
  149. }
  150.  
  151. if (result->getNumber<uint32_t>("account_id") != accountId || result->getNumber<uint64_t>("deletion") != 0) {
  152. return 0;
  153. }
  154. characterName = result->getString("name");
  155. return accountId;
  156. }
  157.  
  158. AccountType_t IOLoginData::getAccountType(uint32_t accountId)
  159. {
  160. std::ostringstream query;
  161. query << "SELECT `type` FROM `accounts` WHERE `id` = " << accountId;
  162. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  163. if (!result) {
  164. return ACCOUNT_TYPE_NORMAL;
  165. }
  166. return static_cast<AccountType_t>(result->getNumber<uint16_t>("type"));
  167. }
  168.  
  169. void IOLoginData::setAccountType(uint32_t accountId, AccountType_t accountType)
  170. {
  171. std::ostringstream query;
  172. query << "UPDATE `accounts` SET `type` = " << static_cast<uint16_t>(accountType) << " WHERE `id` = " << accountId;
  173. Database::getInstance()->executeQuery(query.str());
  174. }
  175.  
  176. void IOLoginData::updateOnlineStatus(uint32_t guid, bool login)
  177. {
  178.  
  179.  
  180.  
  181. if(g_config.getBoolean(ConfigManager::ACCOUNT_MANAGER)){
  182. return;
  183. }
  184. // --
  185.  
  186. if (g_config.getBoolean(ConfigManager::ALLOW_CLONES)) {
  187. return;
  188. }
  189.  
  190. std::ostringstream query;
  191. if (login) {
  192. query << "INSERT INTO `players_online` VALUES (" << guid << ')';
  193. } else {
  194. query << "DELETE FROM `players_online` WHERE `player_id` = " << guid;
  195. }
  196. Database::getInstance()->executeQuery(query.str());
  197. }
  198.  
  199.  
  200. bool IOLoginData::getNameByGuid(uint32_t guid, std::string& name)
  201. {
  202. std::ostringstream query;
  203. query << "SELECT `name` FROM `players` WHERE `id` = " << guid << " AND `deleted` = 0 LIMIT 1;";
  204. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  205. if (!result) {
  206. return false;
  207. }
  208. name = result->getString("name");
  209. nameCacheMap[guid] = name;
  210. return true;
  211. }
  212. // --
  213.  
  214. bool IOLoginData::preloadPlayer(Player* player, const std::string& name)
  215. {
  216. Database* db = Database::getInstance();
  217.  
  218. std::ostringstream query;
  219. query << "SELECT `id`, `account_id`, `group_id`, `deletion`, (SELECT `type` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `account_type`";
  220. if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  221. query << ", (SELECT `premdays` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `premium_days`";
  222. }
  223. query << " FROM `players` WHERE `name` = " << db->escapeString(name);
  224. DBResult_ptr result = db->storeQuery(query.str());
  225. if (!result) {
  226. return false;
  227. }
  228.  
  229. if (result->getNumber<uint64_t>("deletion") != 0) {
  230. return false;
  231. }
  232.  
  233. player->setGUID(result->getNumber<uint32_t>("id"));
  234. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  235. if (!group) {
  236. std::cout << "[Error - IOLoginData::preloadPlayer] " << player->name << " has Group ID " << result->getNumber<uint16_t>("group_id") << " which doesn't exist." << std::endl;
  237. return false;
  238. }
  239. player->setGroup(group);
  240. player->accountNumber = result->getNumber<uint32_t>("account_id");
  241. player->accountType = static_cast<AccountType_t>(result->getNumber<uint16_t>("account_type"));
  242. if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  243. player->premiumDays = result->getNumber<uint16_t>("premium_days");
  244. } else {
  245. player->premiumDays = std::numeric_limits<uint16_t>::max();
  246. }
  247. return true;
  248. }
  249.  
  250. bool IOLoginData::loadPlayerById(Player* player, uint32_t id)
  251. {
  252. std::ostringstream query;
  253. 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`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `offlinetraining_time`, `offlinetraining_skill`, `stamina`, `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`, `direction` FROM `players` WHERE `id` = " << id;
  254. return loadPlayer(player, Database::getInstance()->storeQuery(query.str()));
  255. }
  256.  
  257. bool IOLoginData::loadPlayerByName(Player* player, const std::string& name)
  258. {
  259. Database* db = Database::getInstance();
  260. std::ostringstream query;
  261. 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`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `offlinetraining_time`, `offlinetraining_skill`, `stamina`, `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`, `direction` FROM `players` WHERE `name` = " << db->escapeString(name);
  262. return loadPlayer(player, db->storeQuery(query.str()));
  263. }
  264.  
  265. bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
  266. {
  267. if (!result) {
  268. return false;
  269. }
  270.  
  271. Database* db = Database::getInstance();
  272.  
  273. uint32_t accno = result->getNumber<uint32_t>("account_id");
  274. Account acc = loadAccount(accno);
  275.  
  276. player->setGUID(result->getNumber<uint32_t>("id"));
  277. player->name = result->getString("name");
  278. player->accountNumber = accno;
  279.  
  280. player->accountType = acc.accountType;
  281.  
  282. if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
  283. player->premiumDays = std::numeric_limits<uint16_t>::max();
  284. } else {
  285. player->premiumDays = acc.premiumDays;
  286. }
  287.  
  288. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  289. if (!group) {
  290. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Group ID " << result->getNumber<uint16_t>("group_id") << " which doesn't exist" << std::endl;
  291. return false;
  292. }
  293. player->setGroup(group);
  294.  
  295. player->bankBalance = result->getNumber<uint64_t>("balance");
  296.  
  297. player->setSex(static_cast<PlayerSex_t>(result->getNumber<uint16_t>("sex")));
  298. player->level = std::max<uint32_t>(1, result->getNumber<uint32_t>("level"));
  299.  
  300. uint64_t experience = result->getNumber<uint64_t>("experience");
  301.  
  302. uint64_t currExpCount = Player::getExpForLevel(player->level);
  303. uint64_t nextExpCount = Player::getExpForLevel(player->level + 1);
  304. if (experience < currExpCount || experience > nextExpCount) {
  305. experience = currExpCount;
  306. }
  307.  
  308. player->experience = experience;
  309.  
  310. if (currExpCount < nextExpCount) {
  311. player->levelPercent = Player::getPercentLevel(player->experience - currExpCount, nextExpCount - currExpCount);
  312. } else {
  313. player->levelPercent = 0;
  314. }
  315.  
  316. player->soul = result->getNumber<uint16_t>("soul");
  317. player->capacity = result->getNumber<uint32_t>("cap") * 100;
  318. player->blessings = result->getNumber<uint16_t>("blessings");
  319.  
  320. unsigned long conditionsSize;
  321. const char* conditions = result->getStream("conditions", conditionsSize);
  322. PropStream propStream;
  323. propStream.init(conditions, conditionsSize);
  324.  
  325. Condition* condition = Condition::createCondition(propStream);
  326. while (condition) {
  327. if (condition->unserialize(propStream)) {
  328. player->storedConditionList.push_front(condition);
  329. } else {
  330. delete condition;
  331. }
  332. condition = Condition::createCondition(propStream);
  333. }
  334.  
  335. if (!player->setVocation(result->getNumber<uint16_t>("vocation"))) {
  336. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Vocation ID " << result->getNumber<uint16_t>("vocation") << " which doesn't exist" << std::endl;
  337. return false;
  338. }
  339.  
  340. player->mana = result->getNumber<uint32_t>("mana");
  341. player->manaMax = result->getNumber<uint32_t>("manamax");
  342. player->magLevel = result->getNumber<uint32_t>("maglevel");
  343.  
  344. uint64_t nextManaCount = player->vocation->getReqMana(player->magLevel + 1);
  345. uint64_t manaSpent = result->getNumber<uint64_t>("manaspent");
  346. if (manaSpent > nextManaCount) {
  347. manaSpent = 0;
  348. }
  349.  
  350. player->manaSpent = manaSpent;
  351. player->magLevelPercent = Player::getPercentLevel(player->manaSpent, nextManaCount);
  352.  
  353. player->health = result->getNumber<int32_t>("health");
  354. player->healthMax = result->getNumber<int32_t>("healthmax");
  355.  
  356. player->defaultOutfit.lookType = result->getNumber<uint16_t>("looktype");
  357. player->defaultOutfit.lookHead = result->getNumber<uint16_t>("lookhead");
  358. player->defaultOutfit.lookBody = result->getNumber<uint16_t>("lookbody");
  359. player->defaultOutfit.lookLegs = result->getNumber<uint16_t>("looklegs");
  360. player->defaultOutfit.lookFeet = result->getNumber<uint16_t>("lookfeet");
  361. player->defaultOutfit.lookAddons = result->getNumber<uint16_t>("lookaddons");
  362. player->currentOutfit = player->defaultOutfit;
  363. player->direction = static_cast<Direction> (result->getNumber<uint16_t>("direction"));
  364.  
  365. if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
  366. const time_t skullSeconds = result->getNumber<time_t>("skulltime") - time(nullptr);
  367. if (skullSeconds > 0) {
  368. //ensure that we round up the number of ticks
  369. player->skullTicks = (skullSeconds + 2) * 1000;
  370.  
  371. uint16_t skull = result->getNumber<uint16_t>("skull");
  372. if (skull == SKULL_RED) {
  373. player->skull = SKULL_RED;
  374. }
  375. }
  376. }
  377.  
  378. player->loginPosition.x = result->getNumber<uint16_t>("posx");
  379. player->loginPosition.y = result->getNumber<uint16_t>("posy");
  380. player->loginPosition.z = result->getNumber<uint16_t>("posz");
  381.  
  382. player->lastLoginSaved = result->getNumber<time_t>("lastlogin");
  383. player->lastLogout = result->getNumber<time_t>("lastlogout");
  384.  
  385. player->offlineTrainingTime = result->getNumber<int32_t>("offlinetraining_time") * 1000;
  386. player->offlineTrainingSkill = result->getNumber<int32_t>("offlinetraining_skill");
  387.  
  388. Town* town = g_game.map.towns.getTown(result->getNumber<uint32_t>("town_id"));
  389. if (!town) {
  390. std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Town ID " << result->getNumber<uint32_t>("town_id") << " which doesn't exist" << std::endl;
  391. return false;
  392. }
  393.  
  394. player->town = town;
  395.  
  396. const Position& loginPos = player->loginPosition;
  397. if (loginPos.x == 0 && loginPos.y == 0 && loginPos.z == 0) {
  398. player->loginPosition = player->getTemplePosition();
  399. }
  400.  
  401. player->staminaMinutes = result->getNumber<uint16_t>("stamina");
  402.  
  403. static const std::string skillNames[] = {"skill_fist", "skill_club", "skill_sword", "skill_axe", "skill_dist", "skill_shielding", "skill_fishing"};
  404. 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"};
  405. static const size_t size = sizeof(skillNames) / sizeof(std::string);
  406. for (uint8_t i = 0; i < size; ++i) {
  407. uint16_t skillLevel = result->getNumber<uint16_t>(skillNames[i]);
  408. uint64_t skillTries = result->getNumber<uint64_t>(skillNameTries[i]);
  409. uint64_t nextSkillTries = player->vocation->getReqSkillTries(i, skillLevel + 1);
  410. if (skillTries > nextSkillTries) {
  411. skillTries = 0;
  412. }
  413.  
  414. player->skills[i].level = skillLevel;
  415. player->skills[i].tries = skillTries;
  416. player->skills[i].percent = Player::getPercentLevel(skillTries, nextSkillTries);
  417. }
  418.  
  419. std::ostringstream query;
  420. query << "SELECT `guild_id`, `rank_id`, `nick` FROM `guild_membership` WHERE `player_id` = " << player->getGUID();
  421. if ((result = db->storeQuery(query.str()))) {
  422. uint32_t guildId = result->getNumber<uint32_t>("guild_id");
  423. uint32_t playerRankId = result->getNumber<uint32_t>("rank_id");
  424. player->guildNick = result->getString("nick");
  425.  
  426. Guild* guild = g_game.getGuild(guildId);
  427. if (!guild) {
  428. query.str(std::string());
  429. query << "SELECT `name` FROM `guilds` WHERE `id` = " << guildId;
  430. if ((result = db->storeQuery(query.str()))) {
  431. guild = new Guild(guildId, result->getString("name"));
  432. g_game.addGuild(guild);
  433.  
  434. query.str(std::string());
  435. query << "SELECT `id`, `name`, `level` FROM `guild_ranks` WHERE `guild_id` = " << guildId << " LIMIT 3";
  436.  
  437. if ((result = db->storeQuery(query.str()))) {
  438. do {
  439. guild->addRank(result->getNumber<uint32_t>("id"), result->getString("name"), result->getNumber<uint16_t>("level"));
  440. } while (result->next());
  441. }
  442. }
  443. }
  444.  
  445. if (guild) {
  446. player->guild = guild;
  447. GuildRank* rank = guild->getRankById(playerRankId);
  448. if (rank) {
  449. player->guildLevel = rank->level;
  450. } else {
  451. player->guildLevel = 1;
  452. }
  453.  
  454. IOGuild::getWarList(guildId, player->guildWarList);
  455.  
  456. query.str(std::string());
  457. query << "SELECT COUNT(*) AS `members` FROM `guild_membership` WHERE `guild_id` = " << guildId;
  458. if ((result = db->storeQuery(query.str()))) {
  459. guild->setMemberCount(result->getNumber<uint32_t>("members"));
  460. }
  461. }
  462. }
  463.  
  464. query.str(std::string());
  465. query << "SELECT `player_id`, `name` FROM `player_spells` WHERE `player_id` = " << player->getGUID();
  466. if ((result = db->storeQuery(query.str()))) {
  467. do {
  468. player->learnedInstantSpellList.emplace_front(result->getString("name"));
  469. } while (result->next());
  470. }
  471.  
  472. //load inventory items
  473. ItemMap itemMap;
  474.  
  475. query.str(std::string());
  476. query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_items` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";
  477. if ((result = db->storeQuery(query.str()))) {
  478. loadItems(itemMap, result);
  479.  
  480. for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
  481. const std::pair<Item*, int32_t>& pair = it->second;
  482. Item* item = pair.first;
  483. int32_t pid = pair.second;
  484. if (pid >= 1 && pid <= 10) {
  485. player->internalAddThing(pid, item);
  486. } else {
  487. ItemMap::const_iterator it2 = itemMap.find(pid);
  488. if (it2 == itemMap.end()) {
  489. continue;
  490. }
  491.  
  492. Container* container = it2->second.first->getContainer();
  493. if (container) {
  494. container->internalAddThing(item);
  495. }
  496. }
  497. }
  498. }
  499.  
  500. //load depot items
  501. itemMap.clear();
  502.  
  503. query.str(std::string());
  504. query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_depotitems` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";
  505. if ((result = db->storeQuery(query.str()))) {
  506. loadItems(itemMap, result);
  507.  
  508. for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
  509. const std::pair<Item*, int32_t>& pair = it->second;
  510. Item* item = pair.first;
  511.  
  512. int32_t pid = pair.second;
  513. if (pid >= 0 && pid < 100) {
  514. DepotChest* depotChest = player->getDepotChest(pid, true);
  515. if (depotChest) {
  516. depotChest->internalAddThing(item);
  517. }
  518. } else {
  519. ItemMap::const_iterator it2 = itemMap.find(pid);
  520. if (it2 == itemMap.end()) {
  521. continue;
  522. }
  523.  
  524. Container* container = it2->second.first->getContainer();
  525. if (container) {
  526. container->internalAddThing(item);
  527. }
  528. }
  529. }
  530. }
  531.  
  532. //load inbox items
  533. itemMap.clear();
  534.  
  535. query.str(std::string());
  536. query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_inboxitems` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";
  537. if ((result = db->storeQuery(query.str()))) {
  538. loadItems(itemMap, result);
  539.  
  540. for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
  541. const std::pair<Item*, int32_t>& pair = it->second;
  542. Item* item = pair.first;
  543.  
  544. int32_t pid = pair.second;
  545. if (pid >= 0 && pid < 100) {
  546. DepotLocker* depotLocker = player->getDepotLocker(pid);
  547. if (depotLocker) {
  548. depotLocker->internalAddThing(item);
  549. }
  550. } else {
  551. ItemMap::const_iterator it2 = itemMap.find(pid);
  552. if (it2 == itemMap.end()) {
  553. continue;
  554. }
  555.  
  556. Container* container = it2->second.first->getContainer();
  557. if (container) {
  558. container->internalAddThing(item);
  559. }
  560. }
  561. }
  562. }
  563.  
  564. //load storage map
  565. query.str(std::string());
  566. query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID();
  567. if ((result = db->storeQuery(query.str()))) {
  568. do {
  569. player->addStorageValue(result->getNumber<uint32_t>("key"), result->getNumber<int32_t>("value"), true);
  570. } while (result->next());
  571. }
  572.  
  573. //load vip
  574. query.str(std::string());
  575. query << "SELECT `player_id` FROM `account_viplist` WHERE `account_id` = " << player->getAccount();
  576. if ((result = db->storeQuery(query.str()))) {
  577. do {
  578. player->addVIPInternal(result->getNumber<uint32_t>("player_id"));
  579. } while (result->next());
  580. }
  581.  
  582. player->updateBaseSpeed();
  583. player->updateInventoryWeight();
  584. player->updateItemsLight(true);
  585. return true;
  586. }
  587.  
  588. bool IOLoginData::saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream)
  589. {
  590. std::ostringstream ss;
  591.  
  592. typedef std::pair<Container*, int32_t> containerBlock;
  593. std::list<containerBlock> queue;
  594.  
  595. int32_t runningId = 100;
  596.  
  597. Database* db = Database::getInstance();
  598. for (const auto& it : itemList) {
  599. int32_t pid = it.first;
  600. Item* item = it.second;
  601. ++runningId;
  602.  
  603. propWriteStream.clear();
  604. item->serializeAttr(propWriteStream);
  605.  
  606. size_t attributesSize;
  607. const char* attributes = propWriteStream.getStream(attributesSize);
  608.  
  609. ss << player->getGUID() << ',' << pid << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize);
  610. if (!query_insert.addRow(ss)) {
  611. return false;
  612. }
  613.  
  614. if (Container* container = item->getContainer()) {
  615. queue.emplace_back(container, runningId);
  616. }
  617. }
  618.  
  619. while (!queue.empty()) {
  620. const containerBlock& cb = queue.front();
  621. Container* container = cb.first;
  622. int32_t parentId = cb.second;
  623. queue.pop_front();
  624.  
  625. for (Item* item : container->getItemList()) {
  626. ++runningId;
  627.  
  628. Container* subContainer = item->getContainer();
  629. if (subContainer) {
  630. queue.emplace_back(subContainer, runningId);
  631. }
  632.  
  633. propWriteStream.clear();
  634. item->serializeAttr(propWriteStream);
  635.  
  636. size_t attributesSize;
  637. const char* attributes = propWriteStream.getStream(attributesSize);
  638.  
  639. ss << player->getGUID() << ',' << parentId << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize);
  640. if (!query_insert.addRow(ss)) {
  641. return false;
  642. }
  643. }
  644. }
  645. return query_insert.execute();
  646. }
  647.  
  648. bool IOLoginData::savePlayer(Player* player)
  649. {
  650. if (player->getHealth() <= 0) {
  651. player->changeHealth(1);
  652. }
  653.  
  654. Database* db = Database::getInstance();
  655.  
  656. std::ostringstream query;
  657. query << "SELECT `save` FROM `players` WHERE `id` = " << player->getGUID();
  658. DBResult_ptr result = db->storeQuery(query.str());
  659. if (!result) {
  660. return false;
  661. }
  662.  
  663. if (result->getNumber<uint16_t>("save") == 0) {
  664. query.str(std::string());
  665. query << "UPDATE `players` SET `lastlogin` = " << player->lastLoginSaved << ", `lastip` = " << player->lastIP << " WHERE `id` = " << player->getGUID();
  666. return db->executeQuery(query.str());
  667. }
  668.  
  669. //serialize conditions
  670. PropWriteStream propWriteStream;
  671. for (Condition* condition : player->conditions) {
  672. if (condition->isPersistent()) {
  673. condition->serialize(propWriteStream);
  674. propWriteStream.write<uint8_t>(CONDITIONATTR_END);
  675. }
  676. }
  677.  
  678. size_t conditionsSize;
  679. const char* conditions = propWriteStream.getStream(conditionsSize);
  680.  
  681. //First, an UPDATE query to write the player itself
  682. query.str(std::string());
  683. query << "UPDATE `players` SET ";
  684. query << "`level` = " << player->level << ',';
  685. query << "`group_id` = " << player->group->id << ',';
  686. query << "`vocation` = " << player->getVocationId() << ',';
  687. query << "`health` = " << player->health << ',';
  688. query << "`healthmax` = " << player->healthMax << ',';
  689. query << "`experience` = " << player->experience << ',';
  690. query << "`lookbody` = " << static_cast<uint32_t>(player->defaultOutfit.lookBody) << ',';
  691. query << "`lookfeet` = " << static_cast<uint32_t>(player->defaultOutfit.lookFeet) << ',';
  692. query << "`lookhead` = " << static_cast<uint32_t>(player->defaultOutfit.lookHead) << ',';
  693. query << "`looklegs` = " << static_cast<uint32_t>(player->defaultOutfit.lookLegs) << ',';
  694. query << "`looktype` = " << player->defaultOutfit.lookType << ',';
  695. query << "`lookaddons` = " << static_cast<uint32_t>(player->defaultOutfit.lookAddons) << ',';
  696. query << "`maglevel` = " << player->magLevel << ',';
  697. query << "`mana` = " << player->mana << ',';
  698. query << "`manamax` = " << player->manaMax << ',';
  699. query << "`manaspent` = " << player->manaSpent << ',';
  700. query << "`soul` = " << static_cast<uint16_t>(player->soul) << ',';
  701. query << "`town_id` = " << player->town->getID() << ',';
  702.  
  703. const Position& loginPosition = player->getLoginPosition();
  704. query << "`posx` = " << loginPosition.getX() << ',';
  705. query << "`posy` = " << loginPosition.getY() << ',';
  706. query << "`posz` = " << loginPosition.getZ() << ',';
  707.  
  708. query << "`cap` = " << (player->capacity / 100) << ',';
  709. query << "`sex` = " << (int)(player->sex) << ',';
  710.  
  711. if (player->lastLoginSaved != 0) {
  712. query << "`lastlogin` = " << player->lastLoginSaved << ',';
  713. }
  714.  
  715. if (player->lastIP != 0) {
  716. query << "`lastip` = " << player->lastIP << ',';
  717. }
  718.  
  719. query << "`conditions` = " << db->escapeBlob(conditions, conditionsSize) << ',';
  720.  
  721. if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
  722. int32_t skullTime = 0;
  723.  
  724. if (player->skullTicks > 0) {
  725. skullTime = time(nullptr) + player->skullTicks / 1000;
  726. }
  727.  
  728. query << "`skulltime` = " << skullTime << ',';
  729.  
  730. Skulls_t skull = SKULL_NONE;
  731. if (player->skull == SKULL_RED) {
  732. skull = SKULL_RED;
  733. }
  734. query << "`skull` = " << static_cast<uint32_t>(skull) << ',';
  735. }
  736.  
  737. query << "`lastlogout` = " << player->getLastLogout() << ',';
  738. query << "`balance` = " << player->bankBalance << ',';
  739. query << "`offlinetraining_time` = " << player->getOfflineTrainingTime() / 1000 << ',';
  740. query << "`offlinetraining_skill` = " << player->getOfflineTrainingSkill() << ',';
  741. query << "`stamina` = " << player->getStaminaMinutes() << ',';
  742.  
  743. query << "`skill_fist` = " << player->skills[SKILL_FIST].level << ',';
  744. query << "`skill_fist_tries` = " << player->skills[SKILL_FIST].tries << ',';
  745. query << "`skill_club` = " << player->skills[SKILL_CLUB].level << ',';
  746. query << "`skill_club_tries` = " << player->skills[SKILL_CLUB].tries << ',';
  747. query << "`skill_sword` = " << player->skills[SKILL_SWORD].level << ',';
  748. query << "`skill_sword_tries` = " << player->skills[SKILL_SWORD].tries << ',';
  749. query << "`skill_axe` = " << player->skills[SKILL_AXE].level << ',';
  750. query << "`skill_axe_tries` = " << player->skills[SKILL_AXE].tries << ',';
  751. query << "`skill_dist` = " << player->skills[SKILL_DISTANCE].level << ',';
  752. query << "`skill_dist_tries` = " << player->skills[SKILL_DISTANCE].tries << ',';
  753. query << "`skill_shielding` = " << player->skills[SKILL_SHIELD].level << ',';
  754. query << "`skill_shielding_tries` = " << player->skills[SKILL_SHIELD].tries << ',';
  755. query << "`skill_fishing` = " << player->skills[SKILL_FISHING].level << ',';
  756. query << "`skill_fishing_tries` = " << player->skills[SKILL_FISHING].tries << ',';
  757. query << "`direction` = " << static_cast<uint16_t> (player->getDirection()) << ',';
  758.  
  759. if (!player->isOffline()) {
  760. query << "`onlinetime` = `onlinetime` + " << (time(nullptr) - player->lastLoginSaved) << ',';
  761. }
  762. query << "`blessings` = " << static_cast<uint32_t>(player->blessings);
  763. query << " WHERE `id` = " << player->getGUID();
  764.  
  765. DBTransaction transaction;
  766. if (!transaction.begin()) {
  767. return false;
  768. }
  769.  
  770. if (!db->executeQuery(query.str())) {
  771. return false;
  772. }
  773.  
  774. // learned spells
  775. query.str(std::string());
  776. query << "DELETE FROM `player_spells` WHERE `player_id` = " << player->getGUID();
  777. if (!db->executeQuery(query.str())) {
  778. return false;
  779. }
  780.  
  781. query.str(std::string());
  782.  
  783. DBInsert spellsQuery("INSERT INTO `player_spells` (`player_id`, `name` ) VALUES ");
  784. for (const std::string& spellName : player->learnedInstantSpellList) {
  785. query << player->getGUID() << ',' << db->escapeString(spellName);
  786. if (!spellsQuery.addRow(query)) {
  787. return false;
  788. }
  789. }
  790.  
  791. if (!spellsQuery.execute()) {
  792. return false;
  793. }
  794.  
  795. //item saving
  796. query << "DELETE FROM `player_items` WHERE `player_id` = " << player->getGUID();
  797. if (!db->executeQuery(query.str())) {
  798. return false;
  799. }
  800.  
  801. DBInsert itemsQuery("INSERT INTO `player_items` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
  802.  
  803. ItemBlockList itemList;
  804. for (int32_t slotId = 1; slotId <= 10; ++slotId) {
  805. Item* item = player->inventory[slotId];
  806. if (item) {
  807. itemList.emplace_back(slotId, item);
  808. }
  809. }
  810.  
  811. if (!saveItems(player, itemList, itemsQuery, propWriteStream)) {
  812. return false;
  813. }
  814.  
  815. if (player->lastDepotId != -1) {
  816. //save depot items
  817. query.str(std::string());
  818. query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
  819.  
  820. if (!db->executeQuery(query.str())) {
  821. return false;
  822. }
  823.  
  824. DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
  825. itemList.clear();
  826.  
  827. for (const auto& it : player->depotChests) {
  828. DepotChest* depotChest = it.second;
  829. for (Item* item : depotChest->getItemList()) {
  830. itemList.emplace_back(it.first, item);
  831. }
  832. }
  833.  
  834. if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
  835. return false;
  836. }
  837.  
  838. // save inbox items
  839. query.str(std::string());
  840. query << "DELETE FROM `player_inboxitems` WHERE `player_id` = " << player->getGUID();
  841.  
  842. if (!db->executeQuery(query.str())) {
  843. return false;
  844. }
  845.  
  846. DBInsert inboxQuery("INSERT INTO `player_inboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
  847. itemList.clear();
  848.  
  849. for (const auto& it : player->depotLockerMap) {
  850. DepotLocker* depotLocker = it.second;
  851. for (Item* item : depotLocker->getItemList()) {
  852. if (item->getID() != ITEM_DEPOT) {
  853. itemList.emplace_back(it.first, item);
  854. }
  855. }
  856. }
  857.  
  858. if (!saveItems(player, itemList, inboxQuery, propWriteStream)) {
  859. return false;
  860. }
  861. }
  862.  
  863. query.str(std::string());
  864. query << "DELETE FROM `player_storage` WHERE `player_id` = " << player->getGUID();
  865. if (!db->executeQuery(query.str())) {
  866. return false;
  867. }
  868.  
  869. query.str(std::string());
  870.  
  871. DBInsert storageQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES ");
  872. player->genReservedStorageRange();
  873.  
  874. for (const auto& it : player->storageMap) {
  875. query << player->getGUID() << ',' << it.first << ',' << it.second;
  876. if (!storageQuery.addRow(query)) {
  877. return false;
  878. }
  879. }
  880.  
  881. if (!storageQuery.execute()) {
  882. return false;
  883. }
  884.  
  885. //End the transaction
  886. return transaction.commit();
  887. }
  888.  
  889. std::string IOLoginData::getNameByGuid(uint32_t guid)
  890. {
  891. std::ostringstream query;
  892. query << "SELECT `name` FROM `players` WHERE `id` = " << guid;
  893. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  894. if (!result) {
  895. return std::string();
  896. }
  897. return result->getString("name");
  898. }
  899.  
  900. uint32_t IOLoginData::getGuidByName(const std::string& name)
  901. {
  902. Database* db = Database::getInstance();
  903.  
  904. std::ostringstream query;
  905. query << "SELECT `id` FROM `players` WHERE `name` = " << db->escapeString(name);
  906. DBResult_ptr result = db->storeQuery(query.str());
  907. if (!result) {
  908. return 0;
  909. }
  910. return result->getNumber<uint32_t>("id");
  911. }
  912.  
  913. bool IOLoginData::getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name)
  914. {
  915. Database* db = Database::getInstance();
  916.  
  917. std::ostringstream query;
  918. query << "SELECT `name`, `id`, `group_id`, `account_id` FROM `players` WHERE `name` = " << db->escapeString(name);
  919. DBResult_ptr result = db->storeQuery(query.str());
  920. if (!result) {
  921. return false;
  922. }
  923.  
  924. name = result->getString("name");
  925. guid = result->getNumber<uint32_t>("id");
  926. Group* group = g_game.groups.getGroup(result->getNumber<uint16_t>("group_id"));
  927.  
  928. uint64_t flags;
  929. if (group) {
  930. flags = group->flags;
  931. } else {
  932. flags = 0;
  933. }
  934.  
  935. specialVip = (flags & PlayerFlag_SpecialVIP) != 0;
  936. return true;
  937. }
  938.  
  939. bool IOLoginData::formatPlayerName(std::string& name)
  940. {
  941. Database* db = Database::getInstance();
  942.  
  943. std::ostringstream query;
  944. query << "SELECT `name` FROM `players` WHERE `name` = " << db->escapeString(name);
  945.  
  946. DBResult_ptr result = db->storeQuery(query.str());
  947. if (!result) {
  948. return false;
  949. }
  950.  
  951. name = result->getString("name");
  952. return true;
  953. }
  954.  
  955. void IOLoginData::loadItems(ItemMap& itemMap, DBResult_ptr result)
  956. {
  957. do {
  958. uint32_t sid = result->getNumber<uint32_t>("sid");
  959. uint32_t pid = result->getNumber<uint32_t>("pid");
  960. uint16_t type = result->getNumber<uint16_t>("itemtype");
  961. uint16_t count = result->getNumber<uint16_t>("count");
  962.  
  963. unsigned long attrSize;
  964. const char* attr = result->getStream("attributes", attrSize);
  965.  
  966. PropStream propStream;
  967. propStream.init(attr, attrSize);
  968.  
  969. Item* item = Item::CreateItem(type, count);
  970. if (item) {
  971. if (!item->unserializeAttr(propStream)) {
  972. std::cout << "WARNING: Serialize error in IOLoginData::loadItems" << std::endl;
  973. }
  974.  
  975. std::pair<Item*, uint32_t> pair(item, pid);
  976. itemMap[sid] = pair;
  977. }
  978. } while (result->next());
  979. }
  980.  
  981. void IOLoginData::increaseBankBalance(uint32_t guid, uint64_t bankBalance)
  982. {
  983. std::ostringstream query;
  984. query << "UPDATE `players` SET `balance` = `balance` + " << bankBalance << " WHERE `id` = " << guid;
  985. Database::getInstance()->executeQuery(query.str());
  986. }
  987.  
  988. bool IOLoginData::hasBiddedOnHouse(uint32_t guid)
  989. {
  990. Database* db = Database::getInstance();
  991.  
  992. std::ostringstream query;
  993. query << "SELECT `id` FROM `houses` WHERE `highest_bidder` = " << guid << " LIMIT 1";
  994. return db->storeQuery(query.str()).get() != nullptr;
  995. }
  996.  
  997. std::forward_list<VIPEntry> IOLoginData::getVIPEntries(uint32_t accountId)
  998. {
  999. std::forward_list<VIPEntry> entries;
  1000.  
  1001. std::ostringstream query;
  1002. query << "SELECT `player_id`, (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `name`, `description`, `icon`, `notify` FROM `account_viplist` WHERE `account_id` = " << accountId;
  1003.  
  1004. DBResult_ptr result = Database::getInstance()->storeQuery(query.str());
  1005. if (result) {
  1006. do {
  1007. entries.emplace_front(
  1008. result->getNumber<uint32_t>("player_id"),
  1009. result->getString("name")
  1010. );
  1011. } while (result->next());
  1012. }
  1013. return entries;
  1014. }
  1015.  
  1016. void IOLoginData::addVIPEntry(uint32_t accountId, uint32_t guid)
  1017. {
  1018. Database* db = Database::getInstance();
  1019.  
  1020. std::ostringstream query;
  1021. query << "INSERT INTO `account_viplist` (`account_id`, `player_id`) VALUES (" << accountId << ',' << guid << ')';
  1022. db->executeQuery(query.str());
  1023. }
  1024.  
  1025. void IOLoginData::removeVIPEntry(uint32_t accountId, uint32_t guid)
  1026. {
  1027. std::ostringstream query;
  1028. query << "DELETE FROM `account_viplist` WHERE `account_id` = " << accountId << " AND `player_id` = " << guid;
  1029. Database::getInstance()->executeQuery(query.str());
  1030. }
  1031.  
  1032. void IOLoginData::addPremiumDays(uint32_t accountId, int32_t addDays)
  1033. {
  1034. std::ostringstream query;
  1035. query << "UPDATE `accounts` SET `premdays` = `premdays` + " << addDays << " WHERE `id` = " << accountId;
  1036. Database::getInstance()->executeQuery(query.str());
  1037. }
  1038.  
  1039. void IOLoginData::removePremiumDays(uint32_t accountId, int32_t removeDays)
  1040. {
  1041. std::ostringstream query;
  1042. query << "UPDATE `accounts` SET `premdays` = `premdays` - " << removeDays << " WHERE `id` = " << accountId;
  1043. Database::getInstance()->executeQuery(query.str());
  1044. }
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051. bool IOLoginData::accountIdExists(uint32_t accountId)
  1052. {
  1053. Database* db = Database::getInstance();
  1054. std::ostringstream query;
  1055. query << "SELECT `id` FROM `accounts` WHERE `id` = " << accountId << " LIMIT 1";
  1056.  
  1057. DBResult_ptr result = db->storeQuery(query.str());
  1058. if(!result)
  1059. return false;
  1060.  
  1061. return true;
  1062. }
  1063.  
  1064. bool IOLoginData::accountNameExists(const std::string& name)
  1065. {
  1066. Database* db = Database::getInstance();
  1067. std::ostringstream query;
  1068. query << "SELECT `id` FROM `accounts` WHERE `name` LIKE " << db->escapeString(name) << " LIMIT 1";
  1069.  
  1070. DBResult_ptr result = db->storeQuery(query.str());
  1071. if(!result)
  1072. return false;
  1073.  
  1074. return true;
  1075. }
  1076.  
  1077. bool IOLoginData::getPassword(uint32_t accountId, std::string& password, std::string name/* = ""*/)
  1078. {
  1079. Database* db = Database::getInstance();
  1080. std::ostringstream query;
  1081. query << "SELECT `password` FROM `accounts` WHERE `id` = " << accountId << " LIMIT 1";
  1082.  
  1083. DBResult_ptr result = db->storeQuery(query.str());
  1084. if(!result)
  1085. return false;
  1086.  
  1087. if(name.empty() || name == "Account Manager")
  1088. {
  1089. password = result->getString("password");
  1090. return true;
  1091. }
  1092.  
  1093. std::string tmpPassword = result->getString("password");
  1094. query.str("");
  1095.  
  1096. query << "SELECT `name` FROM `players` WHERE `account_id` = " << accountId;
  1097. result = db->storeQuery(query.str());
  1098. if(!result)
  1099. return false;
  1100.  
  1101. do
  1102. {
  1103. if(result->getString("name") != name)
  1104. continue;
  1105.  
  1106. password = tmpPassword;
  1107. return true;
  1108. }
  1109. while(result->next());
  1110. return false;
  1111. }
  1112.  
  1113. // accountId should be id because the server references the index and not the actual account data
  1114. bool IOLoginData::setPassword(uint32_t accountId, std::string newPassword)
  1115. {
  1116. std::string ePassword = transformToSHA1(newPassword);
  1117. Database* db = Database::getInstance();
  1118.  
  1119. std::ostringstream query;
  1120. query << "UPDATE `accounts` SET `password` = " << db->escapeString(ePassword) << " WHERE `id` = " << accountId << ";";
  1121. return db->executeQuery(query.str());
  1122. }
  1123.  
  1124. // not using recovery key atm but still good to have
  1125. bool IOLoginData::validRecoveryKey(uint32_t accountId, std::string recoveryKey)
  1126. {
  1127. std::string nRecoveryKey = transformToSHA1(recoveryKey);
  1128. Database* db = Database::getInstance();
  1129.  
  1130. std::ostringstream query;
  1131. query << "SELECT `id` FROM `accounts` WHERE `id` = " << accountId << " AND `recoverykey` ";
  1132. query << "LIKE " << db->escapeString(nRecoveryKey) << " LIMIT 1";
  1133.  
  1134. DBResult_ptr result = db->storeQuery(query.str());
  1135. if(!result)
  1136. return false;
  1137.  
  1138. return true;
  1139. }
  1140.  
  1141. bool IOLoginData::setRecoveryKey(uint32_t accountId, std::string newRecoveryKey)
  1142. {
  1143. std::string nRecoveryKey = transformToSHA1(newRecoveryKey);
  1144. Database* db = Database::getInstance();
  1145.  
  1146. std::ostringstream query;
  1147. std::cout << "account id " << accountId << std::endl;
  1148. query << "UPDATE `accounts` SET `recoverykey` = " << db->escapeString(nRecoveryKey) << " WHERE `name` = " << accountId << ";";
  1149. return db->executeQuery(query.str());
  1150. }
  1151.  
  1152. uint64_t IOLoginData::createAccount(std::string name, std::string password)
  1153. {
  1154. std::string ePassword = transformToSHA1(password);
  1155. Database* db = Database::getInstance();
  1156.  
  1157. std::ostringstream query;
  1158. query << "INSERT INTO `accounts` (`id`, `name`, `password`) VALUES ("<< db->escapeString(name) <<", " << db->escapeString(name) << ", " << db->escapeString(ePassword) << ")";
  1159. if(!db->executeQuery(query.str()))
  1160. return 0;
  1161.  
  1162. return db->getLastInsertId();
  1163. }
  1164.  
  1165. // not tested yet
  1166. bool IOLoginData::changeName(uint32_t guid, std::string newName, std::string oldName)
  1167. {
  1168. Database* db = Database::getInstance();
  1169.  
  1170. std::ostringstream query;
  1171. query << "INSERT INTO `player_namelocks` (`player_id`, `name`, `new_name`, `date`) VALUES ("<< guid << ", "
  1172. << db->escapeString(oldName) << ", " << db->escapeString(newName) << ", " << time(NULL) << ")";
  1173. DBResult_ptr result = db->storeQuery(query.str());
  1174. if (!result) {
  1175. return false;
  1176. }
  1177.  
  1178. query.str("");
  1179. query << "UPDATE `players` SET `name` = " << db->escapeString(newName) << " WHERE `id` = " << guid << " LIMIT 1";
  1180. result = db->storeQuery(query.str());
  1181. if (!result) {
  1182. return false;
  1183. }
  1184.  
  1185. // GuidCacheMap::iterator it = guidCacheMap.find(oldName);
  1186. // if(it != guidCacheMap.end())
  1187. // {
  1188. // guidCacheMap.erase(it);
  1189. // guidCacheMap[newName] = guid;
  1190. // }
  1191.  
  1192. nameCacheMap[guid] = newName;
  1193. return true;
  1194. }
  1195.  
  1196. bool IOLoginData::createCharacter(uint32_t accountId, std::string characterName, uint32_t vocationId /*int32_t vocationId */, uint16_t sex)
  1197. {
  1198. if(playerExists(characterName)){
  1199. return false;
  1200. }
  1201. // a little bulky but whatever lol
  1202. uint32_t healthMax = g_config.getNumber(ConfigManager::AM_MAX_HP);
  1203. uint32_t manaMax = g_config.getNumber(ConfigManager::AM_MAX_MP);
  1204. uint32_t capMax = g_config.getNumber(ConfigManager::AM_MAX_CAP);
  1205. uint16_t lookType = (sex % 2) ? g_config.getNumber(ConfigManager::AM_MALE) : g_config.getNumber(ConfigManager::AM_FEMALE);
  1206. uint16_t lookAddons = g_config.getNumber(ConfigManager::AM_LOOK_ADDONS);
  1207.  
  1208. uint16_t magLevel = g_config.getNumber(ConfigManager::AM_MAGLEVEL);
  1209. uint16_t townId = g_config.getNumber(ConfigManager::AM_TOWN_ID);
  1210.  
  1211. uint16_t spawnX = g_config.getNumber(ConfigManager::AM_SPAWNPOS_X);
  1212. uint16_t spawnY = g_config.getNumber(ConfigManager::AM_SPAWNPOS_Y);
  1213. uint16_t spawnZ = g_config.getNumber(ConfigManager::AM_SPAWNPOS_Z);
  1214.  
  1215. uint32_t level = g_config.getNumber(ConfigManager::AM_LEVEL);
  1216. uint64_t exp = g_config.getNumber(ConfigManager::AM_EXPERIENCE);
  1217.  
  1218. uint32_t fist = g_config.getNumber(ConfigManager::AM_FIST);
  1219. uint32_t club = g_config.getNumber(ConfigManager::AM_CLUB);
  1220. uint32_t sword = g_config.getNumber(ConfigManager::AM_SWORD);
  1221. uint32_t axe = g_config.getNumber(ConfigManager::AM_AXE);
  1222. uint32_t shield = g_config.getNumber(ConfigManager::AM_SHIELD);
  1223. uint32_t dist = g_config.getNumber(ConfigManager::AM_DIST);
  1224. uint32_t fish = g_config.getNumber(ConfigManager::AM_FISH);
  1225.  
  1226. uint32_t soul = g_config.getNumber(ConfigManager::AM_SOUL);
  1227.  
  1228. uint64_t balance = g_config.getNumber(ConfigManager::AM_BALANCE);
  1229. int32_t offlineTrainingTime = g_config.getNumber(ConfigManager::AM_OFFLINE_TRAIN);
  1230. uint16_t stamina = g_config.getNumber(ConfigManager::AM_STAMINA);
  1231.  
  1232. if(level > 1){
  1233. exp += Player::getExpForLevel(level);
  1234. healthMax *= level;
  1235. manaMax *= level;
  1236. capMax *= level;
  1237. }
  1238. Database* db = Database::getInstance();
  1239. std::string name = db->escapeString(characterName);
  1240. std::ostringstream query, initialQuery, lastQuery, selectChar;
  1241.  
  1242. // since character creation wants to use the account name when it setups up the player as the account id
  1243. // we'll ask the database to get the id of the account since that is how the players are listed in the character list
  1244. selectChar << "SELECT `id` FROM `accounts` WHERE `name` = " << accountId << ";";
  1245. DBResult_ptr result = db->storeQuery(selectChar.str());
  1246. if (!result){
  1247. return false;
  1248. }
  1249.  
  1250. accountId = result->getNumber<uint32_t>("id");
  1251.  
  1252. // this is to counteract the foreign key issue
  1253. initialQuery << "SET FOREIGN_KEY_CHECKS=0;";
  1254. lastQuery << "SET FOREIGN_KEY_CHECKS=1;";
  1255. db->executeQuery(initialQuery.str());
  1256.  
  1257. query << "INSERT INTO `players` (`name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `skull`, `skulltime`, `lastlogout`, `blessings`, `onlinetime`, `deletion`, `balance`, `offlinetraining_time`, `offlinetraining_skill`, `stamina`, `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`) VALUES (" << name << ", 1, " << accountId << ", 8, " << vocationId << ", " << healthMax << ", " << healthMax << ", 4500, 0, 0, 0, 0, " << lookType << ", " << lookAddons << ", " << magLevel << ", " << manaMax << ", " << manaMax << ", 0, " << soul << ", " << townId << ", " << spawnX << ", " << spawnY << ", " << spawnZ << ", 0x0, " << capMax << ", " << sex << ", 0, 0, 1, 0, 0, 0, 0, 0, 0, " << balance << ", " << offlineTrainingTime << ", -1, " << stamina << ", " << fist << ", 0, " << club << ", 0, " << sword << ", 0, " << axe << ", 0, " << dist << ", 0, " << shield << ", 0, " << fish << ", 0);";
  1258. if(db->executeQuery(query.str())){
  1259. db->executeQuery(lastQuery.str());
  1260. return true;
  1261. }
  1262. db->executeQuery(lastQuery.str());
  1263. return false;
  1264. }
  1265.  
  1266. // not tested
  1267. DeleteCharacter_t IOLoginData::deleteCharacter(uint32_t accountId, const std::string characterName)
  1268. {
  1269. if(g_game.getPlayerByName(characterName))
  1270. return DELETE_ONLINE;
  1271.  
  1272. Database* db = Database::getInstance();
  1273. std::ostringstream query;
  1274. query << "SELECT `id` FROM `players` WHERE `name` LIKE " << db->escapeString(characterName) << " AND `account_id` = " << accountId << " AND `deleted` = 0 LIMIT 1";
  1275.  
  1276. DBResult_ptr result = db->storeQuery(query.str());
  1277. if(!result)
  1278. return DELETE_INTERNAL;
  1279.  
  1280. uint32_t id = result->getNumber<uint32_t>("id");
  1281.  
  1282. House* house = g_game.map.houses.getHouseByPlayerId(id);
  1283. if(house)
  1284. return DELETE_HOUSE;
  1285.  
  1286. /*
  1287. if(IOGuild::getInstance()->getGuildLevel(id) == 3)
  1288. return DELETE_LEADER;
  1289. */
  1290. query.str("");
  1291. query << "UPDATE `players` SET `deleted` = 1 WHERE `id` = " << id << ";";
  1292. if(!db->executeQuery(query.str()))
  1293. return DELETE_INTERNAL;
  1294.  
  1295. query.str("");
  1296. query << "DELETE FROM `guild_invites` WHERE `player_id` = " << id;
  1297. db->executeQuery(query.str());
  1298.  
  1299. query.str("");
  1300. query << "DELETE FROM `player_viplist` WHERE `vip_id` = " << id;
  1301. db->executeQuery(query.str());
  1302.  
  1303. /*
  1304. for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it)
  1305. {
  1306. VIPListSet::iterator it_ = it->second->VIPList.find(id);
  1307. if(it_ != it->second->VIPList.end())
  1308. it->second->VIPList.erase(it_);
  1309. }
  1310. */
  1311. return DELETE_SUCCESS;
  1312. }
  1313.  
  1314. bool IOLoginData::playerExists(uint32_t guid /*= false*/, bool checkCache /*= true*/)
  1315. {
  1316. if(checkCache)
  1317. {
  1318. NameCacheMap::iterator it = nameCacheMap.find(guid);
  1319. if(it != nameCacheMap.end())
  1320. return true;
  1321. }
  1322.  
  1323. Database* db = Database::getInstance();
  1324. std::ostringstream query;
  1325.  
  1326. query << "SELECT `name` FROM `players` WHERE `id` = " << guid << " AND `deleted` = 0";
  1327.  
  1328. query << " LIMIT 1";
  1329. DBResult_ptr result = db->storeQuery(query.str());
  1330. if(!result)
  1331. return false;
  1332.  
  1333. const std::string name = result->getString("name");
  1334. nameCacheMap[guid] = name;
  1335. return true;
  1336. }
  1337.  
  1338. bool IOLoginData::playerExists(std::string& name /*= false*/, bool checkCache /*= true*/)
  1339. {
  1340. if(checkCache)
  1341. {
  1342. GuidCacheMap::iterator it = guidCacheMap.find(name);
  1343. if(it != guidCacheMap.end())
  1344. {
  1345. name = it->first;
  1346. return true;
  1347. }
  1348. }
  1349.  
  1350. Database* db = Database::getInstance();
  1351. std::ostringstream query;
  1352.  
  1353. query << "SELECT `id`, `name` FROM `players` WHERE `name` LIKE " << db->escapeString(name); /*<< " AND `deleted` = 0"; */
  1354.  
  1355. query << " LIMIT 1";
  1356. DBResult_ptr result = db->storeQuery(query.str());
  1357. if(!result)
  1358. return false;
  1359.  
  1360. name = result->getString("name");
  1361. guidCacheMap[name] = result->getNumber<int32_t>("id");
  1362.  
  1363. return true;
  1364. }
  1365. // --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement