Advertisement
Guest User

iologindata.cpp

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