diff --git a/changelog.txt b/changelog.txt index 6e1240815..556069f21 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,10 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 08/16/2014 == +KLS: (addmoreice) Trying out some unstable DB changes. Do backup your database before trying them as master will be considered unstable for a few days at least. Uleat (Noudness): Fixed a floating-point comparison error that led to the notorious 'client bounce' (this is not related to the 'mob falling' due to not having maps installed.) This fix also eliminates a sizeable amount of unnecessary out-going packets due to invalid orientation corrections. - Note: This patch is probably of significant enough importance that admins may wish to manually apply this to older server builds. The number of packets reduced per second should be approximately (num_stationary_close_clients * (num_close_clients - 1)). This will likely have the most effect in zones like: Nexus, Bazaar, Guilds (Halls) and RAID INSTANCES - where players don't move around a lot. diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index d902bc98e..0bbbaa3fd 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -175,14 +175,14 @@ void ImportSkillCaps(SharedDatabase *db) { continue; } - std::string sql; + int class_id, skill_id, level, cap; class_id = atoi(split[0].c_str()); skill_id = atoi(split[1].c_str()); level = atoi(split[2].c_str()); cap = atoi(split[3].c_str()); - StringFormat(sql, "INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", + std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", class_id, skill_id, level, cap); db->RunQuery(sql.c_str(), (uint32)sql.length()); @@ -226,7 +226,7 @@ void ImportBaseData(SharedDatabase *db) { mana_fac = atof(split[8].c_str()); end_fac = atof(split[9].c_str()); - StringFormat(sql, "INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " + sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " "mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)", level, class_id, hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac); diff --git a/common/Item.cpp b/common/Item.cpp index 3bdd33866..ff02d1574 100644 --- a/common/Item.cpp +++ b/common/Item.cpp @@ -916,8 +916,7 @@ void Inventory::dumpItemCollection(const std::map &collection) if (!inst || !inst->GetItem()) continue; - std::string slot; - StringFormat(slot, "Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); + std::string slot = StringFormat("Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); std::cout << slot << std::endl; dumpBagContents(inst, &it); @@ -936,8 +935,7 @@ void Inventory::dumpBagContents(ItemInst *inst, iter_inst *it) { if (!baginst || !baginst->GetItem()) continue; - std::string subSlot; - StringFormat(subSlot, " Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), + std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); std::cout << subSlot << std::endl; } diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 56e62ae37..f364bf9b2 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -10,35 +10,24 @@ MySQLRequestResult::MySQLRequestResult() MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer) : m_CurrentRow(result), m_OneBeyondRow() { - if (errorBuffer != nullptr) - m_Success = false; - else if (errorBuffer == nullptr && result == nullptr) - { - m_Success = false; - -#ifdef _EQDEBUG - std::cout << "DB Query Error: No Result" << std::endl; -#endif - m_ErrorNumber = UINT_MAX; - m_ErrorBuffer = new char[MYSQL_ERRMSG_SIZE]; - - strcpy(m_ErrorBuffer, "DBcore::RunQuery: No Result"); - } - else - m_Success = true; - - m_Result = result; - m_ErrorBuffer = errorBuffer; + m_Result = result; m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; - // If we actually need the column length / fields it will be - // requested at that time, no need to pull it in just to cache it. - // Normal usage would have it as nullptr most likely anyways. - m_ColumnLengths = nullptr; - m_Fields = nullptr; m_LastInsertedID = lastInsertedID; - m_ErrorNumber = errorNumber; + + // If we actually need the column length / fields it will be + // requested at that time, no need to pull it in just to cache it. + // Normal usage would have it as nullptr most likely anyways. + m_ColumnLengths = nullptr; + m_Fields = nullptr; + + if (errorBuffer != nullptr) + m_Success = false; + + m_Success = true; + m_ErrorNumber = errorNumber; + m_ErrorBuffer = errorBuffer; } void MySQLRequestResult::FreeInternals() @@ -113,7 +102,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_ColumnLengths = moveItem.m_ColumnLengths; m_Fields = moveItem.m_Fields; - // Keeps deconstructor from double freeing + // Keeps deconstructor from double freeing // pre move instance. moveItem.ZeroOut(); } @@ -140,8 +129,8 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_ColumnLengths = other.m_ColumnLengths; m_Fields = other.m_Fields; - // Keeps deconstructor from double freeing + // Keeps deconstructor from double freeing // pre move instance. other.ZeroOut(); return *this; -} \ No newline at end of file +} diff --git a/common/MySQLRequestRow.cpp b/common/MySQLRequestRow.cpp index 46bdaffd9..f8c2b4c06 100644 --- a/common/MySQLRequestRow.cpp +++ b/common/MySQLRequestRow.cpp @@ -1,6 +1,6 @@ #include "MySQLRequestRow.h" -MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row) +MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row) : m_Result(row.m_Result), m_MySQLRow(row.m_MySQLRow) { } @@ -26,13 +26,17 @@ MySQLRequestRow& MySQLRequestRow::operator=(MySQLRequestRow& moveItem) moveItem.m_Result = nullptr; moveItem.m_MySQLRow = nullptr; - + return *this; } MySQLRequestRow::MySQLRequestRow(MYSQL_RES *result) - : m_Result(result), m_MySQLRow(mysql_fetch_row(m_Result)) + : m_Result(result) { + if (result != nullptr) + m_MySQLRow = mysql_fetch_row(result); + else + m_MySQLRow = nullptr; } MySQLRequestRow& MySQLRequestRow::operator++() @@ -41,19 +45,19 @@ MySQLRequestRow& MySQLRequestRow::operator++() return *this; } -MySQLRequestRow MySQLRequestRow::operator++(int) +MySQLRequestRow MySQLRequestRow::operator++(int) { - MySQLRequestRow tmp(*this); - operator++(); + MySQLRequestRow tmp(*this); + operator++(); return tmp; } -bool MySQLRequestRow::operator==(const MySQLRequestRow& rhs) +bool MySQLRequestRow::operator==(const MySQLRequestRow& rhs) { return m_MySQLRow == rhs.m_MySQLRow; } -bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs) +bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs) { return m_MySQLRow != rhs.m_MySQLRow; } diff --git a/common/StringUtil.cpp b/common/StringUtil.cpp index 71bb961e1..80c92fa88 100644 --- a/common/StringUtil.cpp +++ b/common/StringUtil.cpp @@ -38,8 +38,9 @@ // original source: // https://github.com/facebook/folly/blob/master/folly/String.cpp // -void vStringFormat(std::string& output, const char* format, va_list args) +const std::string vStringFormat(const char* format, va_list args) { + std::string output; va_list tmpargs; va_copy(tmpargs,args); @@ -48,11 +49,8 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // Looks like we have an invalid format string. - // error out. - std::string errorMessage("Invalid format string; snprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // return empty string. + return ""; } else if ((unsigned int)characters_used > output.capacity()) { output.resize(characters_used+1); @@ -62,12 +60,10 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // We shouldn't have a format error by this point, but I can't imagine what error we - // could have by this point. Still, error out and report it. - std::string errorMessage("Invalid format string or unknown vsnprintf error; vsnprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // could have by this point. Still, return empty string; + return ""; } + return std::move(output); } else { output.resize(characters_used + 1); @@ -78,24 +74,23 @@ void vStringFormat(std::string& output, const char* format, va_list args) if (characters_used < 0) { // We shouldn't have a format error by this point, but I can't imagine what error we - // could have by this point. still error out and report it. - std::string errorMessage("Invalid format string or unknown vsnprintf error; vsnprintf returned negative with format string: "); - errorMessage.append(format); - - throw std::runtime_error(errorMessage); + // could have by this point. Still, return empty string; + return ""; } - + return std::move(output); } } -void StringFormat(std::string& output, const char* format, ...) +const std::string StringFormat(const char* format, ...) { va_list args; va_start(args, format); - vStringFormat(output,format,args); + std::string output = vStringFormat(format,args); va_end(args); + return std::move(output); } + // normal strncpy doesnt put a null term on copied strings, this one does // ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp char* strn0cpy(char* dest, const char* source, uint32 size) { @@ -384,3 +379,15 @@ std::string EscapeString(const std::string &s) { return ret; } + +bool isAlphaNumeric(const char *text) +{ + for (unsigned int charIndex=0; charIndex 'z') && + (text[charIndex] < 'A' || text[charIndex] > 'Z') && + (text[charIndex] < '0' || text[charIndex] > '9')) + return false; + } + + return true; +} \ No newline at end of file diff --git a/common/StringUtil.h b/common/StringUtil.h index 46ff43183..fe7e83edf 100644 --- a/common/StringUtil.h +++ b/common/StringUtil.h @@ -19,11 +19,12 @@ #include #include #include +#include #include "types.h" -void vStringFormat(std::string& output, const char* format, va_list args); -void StringFormat(std::string& output, const char* format, ...); +const std::string vStringFormat(const char* format, va_list args); +const std::string StringFormat(const char* format, ...); std::string EscapeString(const std::string &s); const char *MakeLowerString(const char *source); @@ -51,4 +52,6 @@ char *RemoveApostrophes(const char *s); std::vector SplitString(const std::string &s, char delim); +bool isAlphaNumeric(const char *text); + #endif diff --git a/common/database.cpp b/common/database.cpp index 6fdf6b1af..2d5bdbdcc 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -43,15 +43,10 @@ #include "database.h" #include "eq_packet_structs.h" #include "guilds.h" -//#include "MiscFunctions.h" #include "StringUtil.h" #include "extprofile.h" extern Client client; -/* -This is the amount of time in seconds the client has to enter the zone -server after the world server, or inbetween zones when that is finished -*/ /* Establish a connection to a mysql database with the supplied parameters @@ -100,8 +95,6 @@ void Database::DBInitVars() { varcache_lastupdate = 0; } - - void Database::HandleMysqlError(uint32 errnum) { /* switch(errnum) { case 0: @@ -141,276 +134,212 @@ Database::~Database() } } - /* Check if there is an account with name "name" and password "password" Return the account id or zero if no account matches. Zero will also be returned if there is a database error. */ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; if(strlen(name) >= 50 || strlen(password) >= 50) return(0); char tmpUN[100]; char tmpPW[100]; + DoEscapeString(tmpUN, name, strlen(name)); DoEscapeString(tmpPW, password, strlen(password)); - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT id, status FROM account WHERE name='%s' AND password is not null " + std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND password is not null " "and length(password) > 0 and (password='%s' or password=MD5('%s'))", - tmpUN, tmpPW, tmpPW), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 id = atoi(row[0]); - if (oStatus) - *oStatus = atoi(row[1]); - mysql_free_result(result); - return id; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else + tmpUN, tmpPW, tmpPW); + auto results = QueryDatabase(query); + + if (!results.Success()) { - std::cerr << "Error in CheckLogin query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; + std::cerr << "Error in CheckLogin query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return 0; + auto row = results.begin(); + + uint32 id = atoi(row[0]); + + if (oStatus) + *oStatus = atoi(row[1]); + + return id; } - -//Lieka: Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. +//Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table. bool Database::CheckBannedIPs(const char* loginIP) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - //std::cout << "Checking against Banned IPs table."<< std::endl; //Lieka: Debugging - if (RunQuery(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - //std::cout << loginIP << " was present in the banned IPs table" << std::endl; //Lieka: Debugging - mysql_free_result(result); - return true; - } - else - { - //std::cout << loginIP << " was not present in the banned IPs table." << std::endl; //Lieka: Debugging - mysql_free_result(result); - return false; - } - mysql_free_result(result); - } - else + std::string query = StringFormat("SELECT ip_address FROM Banned_IPs WHERE ip_address='%s'", loginIP); + + auto results = QueryDatabase(query); + + if (!results.Success()) { - std::cerr << "Error in CheckBannedIPs query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; return true; } - return true; + + if (results.RowCount() != 0) + return true; + + return false; } bool Database::AddBannedIP(char* bannedIP, const char* notes) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes), errbuf)) { - std::cerr << "Error in ReserveName query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); + return true; } - //End Lieka Edit bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - mysql_free_result(result); - return true; - } else { - mysql_free_result(result); - return false; - } - mysql_free_result(result); + std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); - } else { - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) return false; - } + + if (results.RowCount() == 1) + return true; return false; } bool Database::AddGMIP(char* ip_address, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name), errbuf)) { - safe_delete_array(query); - return false; - } - safe_delete_array(query); - return true; + auto results = QueryDatabase(query); + + return results.Success(); } void Database::LoginIP(uint32 AccountID, const char* LoginIP) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP), errbuf)) { - std::cerr << "Error in Log IP query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) + std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; } int16 Database::CheckStatus(uint32 account_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" + " FROM `account` WHERE `id` = %i", account_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" - " FROM `account` WHERE `id` = %i", account_id), errbuf, &result)) + auto results = QueryDatabase(query); + + if (!results.Success()) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - - int16 status = atoi(row[0]); - - int32 suspendeduntil = 0; - // MariaDB initalizes with NULL if unix_timestamp() is out of range - if (row[1] != NULL) { - suspendeduntil = atoi(row[1]); - } - - int32 current = atoi(row[2]); - - mysql_free_result(result); - - if(suspendeduntil > current) - return -1; - - return status; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in CheckStatus query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; + std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return 0; + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + int16 status = atoi(row[0]); + + int32 suspendeduntil = 0; + + // MariaDB initalizes with NULL if unix_timestamp() is out of range + if (row[1] != nullptr) { + suspendeduntil = atoi(row[1]); + } + + int32 current = atoi(row[2]); + + if(suspendeduntil > current) + return -1; + + return status; } uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 querylen; - uint32 last_insert_id; + std::string query; if (password) - querylen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); + query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id); else - querylen = MakeAnyLenString(&query, "INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); + query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; - if (!RunQuery(query, querylen, errbuf, 0, 0, &last_insert_id)) { - std::cerr << "Error in CreateAccount query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - safe_delete_array(query); - if (last_insert_id == 0) { - std::cerr << "Error in CreateAccount query '" << query << "' " << errbuf << std::endl; + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } - return last_insert_id; + if (results.LastInsertedID() == 0) + { + std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; + } + + return results.LastInsertedID(); } bool Database::DeleteAccount(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); - std::cerr << "Account Attempting to be deleted:" << name << std::endl; - if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM account WHERE name='%s';",name), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - return true; - } - } - else { + std::cout << "Account Attempting to be deleted:" << name << std::endl; - std::cerr << "Error in DeleteAccount query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } + auto results = QueryDatabase(query); - return false; -} - -bool Database::SetLocalPassword(uint32 accid, const char* password) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET password=MD5('%s') where id=%i;", password, accid), errbuf)) { - std::cerr << "Error in SetLocalPassword query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + if (!results.Success()) + { + std::cerr << "Error in DeleteAccount query '" << query << "' " << results.ErrorMessage() << std::endl; + return false; + } + + return results.RowsAffected() == 1; +} + +bool Database::SetLocalPassword(uint32 accid, const char* password) { + std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid); + + auto results = QueryDatabase(query); + + if (!results.Success()) { + std::cerr << "Error in SetLocalPassword query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); return true; } bool Database::SetAccountStatus(const char* name, int16 status) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + std::string query = StringFormat("UPDATE account SET status=%i WHERE name='%s';", status, name); std::cout << "Account being GM Flagged:" << name << ", Level: " << (int16) status << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET status=%i WHERE name='%s';", status, name), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return false; - } - safe_delete_array(query); - if (affected_rows == 0) { + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowsAffected() == 0) + { std::cout << "Account: " << name << " does not exist, therefore it cannot be flagged\n"; return false; } @@ -420,15 +349,16 @@ bool Database::SetAccountStatus(const char* name, int16 status) { bool Database::ReserveName(uint32 account_id, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name), errbuf)) { - std::cerr << "Error in ReserveName query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); + return true; } @@ -438,318 +368,202 @@ returns false on failure, true otherwise */ bool Database::DeleteCharacter(char *name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query=0; - MYSQL_RES *result; - MYSQL_ROW row; - int charid, matches; - uint32 affected_rows; + std::string query=StringFormat("SELECT id from character_ WHERE name='%s'", name); + int charid; if(!name || !strlen(name)) { - printf("DeleteCharacter: request to delete without a name (empty char slot)\n"); + std::cerr << "DeleteCharacter: request to delete without a name (empty char slot)" << std::endl; return false; } // get id from character_ before deleting record so we can clean up inventory and qglobal #if DEBUG >= 5 - printf("DeleteCharacter: Attempting to delete '%s'\n", name); + std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; #endif - RunQuery(query, MakeAnyLenString(&query, "SELECT id from character_ WHERE name='%s'", name), errbuf, &result); - if (query) + + auto results = QueryDatabase(query); + + if(results.RowCount() != 1) { - safe_delete_array(query); - query = nullptr; - } - matches = mysql_num_rows(result); - if(matches == 1) - { - row = mysql_fetch_row(result); - charid = atoi(row[0]); -#if DEBUG >= 5 - printf("DeleteCharacter: found '%s' with char id: %d\n", name, charid); -#endif - } - else - { - printf("DeleteCharacter: error: got %d rows matching '%s'\n", matches, name); - if(result) - { - mysql_free_result(result); - result = nullptr; - } + std::cerr << "DeleteCharacter error: got " << results.RowCount() << " rows matching '" << name << "'" << std::endl; return false; } - if(result) - { - mysql_free_result(result); - result = nullptr; - } - - + auto row = results.begin(); + charid = atoi(row[0]); #if DEBUG >= 5 - printf("DeleteCharacter: deleting '%s' (id %d): ", name, charid); - printf(" quest_globals"); + std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; + std::cout << "DeleteCharacter: deleting << '" << name << "' (id " << charid << "): " << std::endl; + std::cout << " quest_globals"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from quest_globals WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from quest_globals WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" character_tasks"); + std::cout << " character_tasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from character_tasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" character_activities"); + std::cout << " character_activities"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_activities WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from character_activities WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" character_enabledtasks"); + std::cout << " character_enabledtasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_enabledtasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from character_enabledtasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" completed_tasks"); + std::cout << " completed_tasks"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from completed_tasks WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from completed_tasks WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" friends"); + std::cout << " friends"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from friends WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from friends WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" mail"); + std::cout << " mail"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from mail WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat( "DELETE from mail WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" ptimers"); + std::cout << " ptimers"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from timers WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from timers WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" inventory"); + std::cout << " inventory"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from inventory WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE from inventory WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" guild_members"); + std::cout << " guild_members"; #endif + #ifdef BOTS - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid), errbuf, nullptr, &affected_rows); + query = StringFormat("DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid); #else - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guild_members WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); + query = StringFormat("DELETE FROM guild_members WHERE char_id='%d'", charid); #endif - if(query) - { - safe_delete_array(query); - query = nullptr; - } + QueryDatabase(query); #if DEBUG >= 5 - printf(" recipes"); + std::cout << " recipes"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM char_recipe_list WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM char_recipe_list WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" adventure_stats"); + std::cout << " adventure_stats"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM adventure_stats WHERE player_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM adventure_stats WHERE player_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" zone_flags"); + std::cout << " zone_flags"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM zone_flags WHERE charID='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM zone_flags WHERE charID='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" titles"); + std::cout << " titles"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM titles WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM titles WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" titlesets"); + std::cout << " titlesets"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM player_titlesets WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" keyring"); + std::cout << " keyring"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM keyring WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" factions"); + std::cout << " factions"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM faction_values WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" instances"); + std::cout << " instances"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE charid='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM instance_list_player WHERE charid='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf(" _character"); + std::cout << " _character"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE from character_ WHERE id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) + + query = StringFormat("DELETE from character_ WHERE id='%d'", charid); + results = QueryDatabase(query); + + if(results.RowsAffected() != 1) // here we have to have a match or it's an error { - safe_delete_array(query); - query = nullptr; - } - if(affected_rows != 1) // here we have to have a match or it's an error - { - LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", affected_rows); + LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", results.RowsAffected()); return false; } #if DEBUG >= 5 - printf(" alternate currency"); + std::cout << " alternate currency"; #endif - RunQuery(query, MakeAnyLenString(&query, "DELETE FROM character_alt_currency WHERE char_id='%d'", charid), errbuf, nullptr, &affected_rows); - if(query) - { - safe_delete_array(query); - query = nullptr; - } + + query = StringFormat("DELETE FROM character_alt_currency WHERE char_id='%d'", charid); + QueryDatabase(query); #if DEBUG >= 5 - printf("\n"); + std::cout << std::endl; #endif - printf("DeleteCharacter: successfully deleted '%s' (id %d)\n", name, charid); + std::cout << "DeleteCharacter: successfully deleted '" << name << "' (id " << charid << ")" << std::endl; return true; } -// Store new character information into the character_ and inventory tables (this won't store starting augments) + +// Store new character information into the character_ and inventory tables bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext) { - char errbuf[MYSQL_ERRMSG_SIZE]; char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; char* end = query; - uint32 affected_rows = 0; - int i; uint32 charid = 0; - char* charidquery = 0; - char* invquery = 0; - MYSQL_RES *result; - MYSQL_ROW row = 0; char zone[50]; float x, y, z; -// memset(&playeraa, 0, sizeof(playeraa)); - - // get the char id (used in inventory inserts below) - if(!RunQuery - ( - charidquery, - MakeAnyLenString - ( - &charidquery, - "SELECT id FROM character_ where name='%s'", - pp->name - ), - errbuf, - &result - )) { - safe_delete_array(charidquery); - LogFile->write(EQEMuLog::Error, "Error in char store id query: %s: %s", charidquery, errbuf); - return(false); - } - safe_delete_array(charidquery); - - if(mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - if(row[0]) - charid = atoi(row[0]); - } + charid = GetCharacterID(pp->name); if(!charid) { @@ -764,6 +578,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven pp->zone_id = 1; } else strn0cpy(zone, zname, 49); + x=pp->x; y=pp->y; z=pp->z; @@ -779,46 +594,32 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); end += sprintf(end, "\' WHERE account_id=%d AND name='%s'",account_id, pp->name); - RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows); + auto results = QueryDatabase(query, (uint32) (end - query)); + // stack assigned query, no need to delete it. - if(!affected_rows) + if(!results.RowsAffected()) { - LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, errbuf); + LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, results.ErrorMessage().c_str()); return false; } - affected_rows = 0; - - - // Doodman: Is this even used? // now the inventory - - for (i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::BANK_BAGS_END;) + std::string invquery; + for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) { - const ItemInst* newinv = inv->GetItem((int16)i); - if (newinv) + const ItemInst* newinv = inv->GetItem(i); + if (!newinv) { - MakeAnyLenString - ( - &invquery, - "INSERT INTO inventory SET " - "charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u", - charid, i, newinv->GetItem()->ID, - newinv->GetCharges(), newinv->GetColor() - ); + invquery = StringFormat("INSERT INTO inventory SET charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u", + charid, i, newinv->GetItem()->ID,newinv->GetCharges(), newinv->GetColor()); + auto results = QueryDatabase(invquery); - RunQuery(invquery, strlen(invquery), errbuf, 0, &affected_rows); - if(!affected_rows) - { - LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery, errbuf); - } + if (!results.RowsAffected()) + LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery.c_str(), results.ErrorMessage().c_str()); #if EQDEBUG >= 9 else - { - LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s' %s", invquery, errbuf); - } + LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s'", invquery.c_str()); #endif - safe_delete_array(invquery); } if (i == MainCursor) { @@ -854,220 +655,201 @@ the name "name" or zero if no character with that name was found Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", charname); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT account_id, id FROM character_ WHERE name='%s'", charname), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - if (oCharID) - *oCharID = atoi(row[1]); - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return 0; + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 accountId = atoi(row[0]); + + if (oCharID) + *oCharID = atoi(row[1]); + + return accountId; } // Retrieve account_id for a given char_id uint32 Database::GetAccountIDByChar(uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret = 0; + std::string query = StringFormat("SELECT account_id FROM character_ WHERE id=%i", char_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT account_id FROM character_ WHERE id=%i", char_id), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - ret = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query, errbuf); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return 0; } - safe_delete_array(query); - return ret; + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + if (!isAlphaNumeric(accname)) + return 0; + std::string query = StringFormat("SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname); + auto results = QueryDatabase(query); - for (unsigned int i=0; i 'z') && - (accname[i] < 'A' || accname[i] > 'Z') && - (accname[i] < '0' || accname[i] > '9')) - return 0; + if (!results.Success()) + { + std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); // copy to temp var because gotta free the result before exitting this function - if (status) - *status = atoi(row[1]); - if (lsid) { - if (row[2]) - *lsid = atoi(row[2]); - else - *lsid = 0; - } - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 id = atoi(row[0]); + + if (status) + *status = atoi(row[1]); + + if (lsid) + { + if (row[2]) + *lsid = atoi(row[2]); + else + *lsid = 0; } - return 0; + return id; } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); + auto results = QueryDatabase(query); - strcpy(name, row[0]); - if (row[1] && oLSAccountID) { - *oLSAccountID = atoi(row[1]); - } - } - - mysql_free_result(result); + if (!results.Success()) + { + std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; + return; } - else { - safe_delete_array(query); - std::cerr << "Error in GetAccountName query '" << query << "' " << errbuf << std::endl; + + if (results.RowCount() != 1) + return; + + auto row = results.begin(); + + strcpy(name, row[0]); + if (row[1] && oLSAccountID) { + *oLSAccountID = atoi(row[1]); } + } void Database::GetCharName(uint32 char_id, char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT name FROM character_ WHERE id='%i'", char_id); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name FROM character_ WHERE id='%i'", char_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - - strcpy(name, row[0]); - } - - mysql_free_result(result); - } - else { - safe_delete_array(query); - std::cerr << "Error in GetCharName query '" << query << "' " << errbuf << std::endl; + if (!results.Success()) + { + std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl; + return; } + auto row = results.begin(); + strcpy(name, row[0]); } bool Database::LoadVariables() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; + char *query = nullptr; - if (RunQuery(query, LoadVariables_MQ(&query), errbuf, &result)) { + auto results = QueryDatabase(query, LoadVariables_MQ(&query)); + + if (!results.Success()) + { + std::cerr << "Error in LoadVariables query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); - bool ret = LoadVariables_result(result); - mysql_free_result(result); - return ret; + return false; } - else { - std::cerr << "Error in LoadVariables query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return false; + + safe_delete_array(query); + return LoadVariables_result(std::move(results)); } -uint32 Database::LoadVariables_MQ(char** query) { -// the read of this single variable should be atomic... this was causing strange problems -// LockMutex lock(&Mvarcache); +uint32 Database::LoadVariables_MQ(char** query) +{ return MakeAnyLenString(query, "SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache_lastupdate); } -bool Database::LoadVariables_result(MYSQL_RES* result) { - uint32 i; - MYSQL_ROW row; +// always returns true? not sure about this. +bool Database::LoadVariables_result(MySQLRequestResult results) { + uint32 i = 0; LockMutex lock(&Mvarcache); - if (mysql_num_rows(result) > 0) { - if (!varcache_array) { - varcache_max = mysql_num_rows(result); - varcache_array = new VarCache_Struct*[varcache_max]; - for (i=0; ivarname, row[0]) == 0) { - delete varcache_array[i]; - varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strn0cpy(varcache_array[i]->varname, row[0], sizeof(varcache_array[i]->varname)); - strcpy(varcache_array[i]->value, row[1]); - break; - } - } - else { + + if (results.RowCount() == 0) + return true; + + if (!varcache_array) { + varcache_max = results.RowCount(); + varcache_array = new VarCache_Struct*[varcache_max]; + for (i=0; ivarname, row[0]) == 0) { + delete varcache_array[i]; varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strcpy(varcache_array[i]->varname, row[0]); + strn0cpy(varcache_array[i]->varname, row[0], sizeof(varcache_array[i]->varname)); strcpy(varcache_array[i]->value, row[1]); break; } } - } - uint32 max_used = 0; - for (i=0; i max_used) - max_used = i; + else { + varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; + strcpy(varcache_array[i]->varname, row[0]); + strcpy(varcache_array[i]->value, row[1]); + break; } } - max_used++; - varcache_max = max_used; } + + uint32 max_used = 0; + for (i=0; i max_used) + max_used = i; + } + } + + varcache_max = max_used + 1; + return true; } @@ -1094,10 +876,7 @@ bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_ } bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - + char *varname,*varvalue; varname=(char *)malloc(strlen(varname_in)*2+1); @@ -1105,291 +884,244 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { DoEscapeString(varname, varname_in, strlen(varname_in)); DoEscapeString(varvalue, varvalue_in, strlen(varvalue_in)); - if (RunQuery(query, MakeAnyLenString(&query, "Update variables set value='%s' WHERE varname like '%s'", varvalue, varname), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - LoadVariables(); // refresh cache - free(varname); - free(varvalue); - return true; - } - else { - if (RunQuery(query, MakeAnyLenString(&query, "Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - LoadVariables(); // refresh cache - free(varname); - free(varvalue); - return true; - } - } - } + std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", varvalue, varname); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in SetVariable query '" << query << "' " << results.ErrorMessage() << std::endl; + free(varname); + free(varvalue); + return false; } - else { - std::cerr << "Error in SetVariable query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + if (results.RowsAffected() == 1) + { + LoadVariables(); // refresh cache + free(varname); + free(varvalue); + return true; } + + query = StringFormat("Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue); + results = QueryDatabase(query); free(varname); free(varvalue); - return false; + + if (results.RowsAffected() != 1) + return false; + + LoadVariables(); // refresh cache + return true; } uint32 Database::GetMiniLoginAccount(char* ip){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 retid = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM account WHERE minilogin_ip='%s'", ip), errbuf, &result)) { - safe_delete_array(query); - if ((row = mysql_fetch_row(result))) - retid = atoi(row[0]); - mysql_free_result(result); - } - else + + std::string query = StringFormat("SELECT id FROM account WHERE minilogin_ip='%s'", ip); + auto results = QueryDatabase(query); + + if (!results.Success()) { - std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return retid; + + auto row = results.begin(); + + return atoi(row[0]); } -// Pyro: Get zone starting points from DB +// Get zone starting points from DB bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - // int buf_len = 256; - // int chars = -1; - MYSQL_RES *result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT safe_x, safe_y, safe_z, min_status, min_level, flag_needed FROM zone " + " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT safe_x, safe_y, safe_z, min_status, min_level, " - " flag_needed FROM zone " - " WHERE short_name='%s' AND (version=%i OR version=0) ORDER BY version DESC", short_name, version), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - if (safe_x != 0) - *safe_x = atof(row[0]); - if (safe_y != 0) - *safe_y = atof(row[1]); - if (safe_z != 0) - *safe_z = atof(row[2]); - if (minstatus != 0) - *minstatus = atoi(row[3]); - if (minlevel != 0) - *minlevel = atoi(row[4]); - if (flag_needed != nullptr) - strcpy(flag_needed, row[5]); - mysql_free_result(result); - return true; - } - - mysql_free_result(result); - } - else + if (!results.Success()) { - std::cerr << "Error in GetSafePoint query '" << query << "' " << errbuf << std::endl; + std::cerr << "Error in GetSafePoint query '" << query << "' " << results.ErrorMessage() << std::endl; std::cerr << "If it errors, run the following querys:\n"; std::cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; std::cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT NULL DEFAULT '';\n"; - - safe_delete_array(query); - } - return false; -} - - -bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - if (long_name != 0) { - *long_name = strcpy(new char[strlen(row[0])+1], row[0]); - } - if (file_name != 0) { - if (row[1] == 0) - strcpy(file_name, short_name); - else - strcpy(file_name, row[1]); - } - if (safe_x != 0) - *safe_x = atof(row[2]); - if (safe_y != 0) - *safe_y = atof(row[3]); - if (safe_z != 0) - *safe_z = atof(row[4]); - if (graveyard_id != 0) - *graveyard_id = atoi(row[5]); - if (maxclients) - *maxclients = atoi(row[6]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetZoneLongName query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); return false; } - return false; -} -uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 GraveyardID = 0; + if (results.RowCount() == 0) + return false; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version), errbuf, &result)) - { - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - GraveyardID = atoi(row[0]); - } - mysql_free_result(result); - safe_delete_array(query); - return GraveyardID; + auto row = results.begin(); + + if (safe_x != nullptr) + *safe_x = atof(row[0]); + if (safe_y != nullptr) + *safe_y = atof(row[1]); + if (safe_z != nullptr) + *safe_z = atof(row[2]); + if (minstatus != nullptr) + *minstatus = atoi(row[3]); + if (minlevel != nullptr) + *minlevel = atoi(row[4]); + if (flag_needed != nullptr) + strcpy(flag_needed, row[5]); + + return true; +} + +bool Database::GetZoneLongName(const char* short_name, char** long_name, char* file_name, float* safe_x, float* safe_y, float* safe_z, uint32* graveyard_id, uint32* maxclients) { + + std::string query = StringFormat("SELECT long_name, file_name, safe_x, safe_y, safe_z, graveyard_id, maxclients FROM zone WHERE short_name='%s' AND version=0", short_name); + auto results = QueryDatabase(query); + + if (!results.Success()) { + std::cerr << "Error in GetZoneLongName query '" << query << "' " << results.ErrorMessage() << std::endl; + return false; } - else - { - std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << errbuf << std::endl; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + if (long_name != nullptr) + *long_name = strcpy(new char[strlen(row[0])+1], row[0]); + + if (file_name != nullptr) { + if (row[1] == nullptr) + strcpy(file_name, short_name); + else + strcpy(file_name, row[1]); } - safe_delete_array(query); - return GraveyardID; + + if (safe_x != nullptr) + *safe_x = atof(row[2]); + if (safe_y != nullptr) + *safe_y = atof(row[3]); + if (safe_z != nullptr) + *safe_z = atof(row[4]); + if (graveyard_id != nullptr) + *graveyard_id = atoi(row[5]); + if (maxclients != nullptr) + *maxclients = atoi(row[6]); + + return true; +} + +uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { + + std::string query = StringFormat("SELECT graveyard_id FROM zone WHERE zoneidnumber='%u' AND (version=%i OR version=0) ORDER BY version DESC", zone_id, version); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; + } + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if(graveyard_zoneid != 0) - *graveyard_zoneid = atoi(row[0]); - if(graveyard_x != 0) - *graveyard_x = atof(row[1]); - if(graveyard_y != 0) - *graveyard_y = atof(row[2]); - if(graveyard_z != 0) - *graveyard_z = atof(row[3]); - if(graveyard_heading != 0) - *graveyard_heading = atof(row[4]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + if (!results.Success()){ + std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - return false; + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + + if(graveyard_zoneid != nullptr) + *graveyard_zoneid = atoi(row[0]); + if(graveyard_x != nullptr) + *graveyard_x = atof(row[1]); + if(graveyard_y != nullptr) + *graveyard_y = atof(row[2]); + if(graveyard_z != nullptr) + *graveyard_z = atof(row[3]); + if(graveyard_heading != nullptr) + *graveyard_heading = atof(row[4]); + + return true; } bool Database::LoadZoneNames() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query("SELECT zoneidnumber, short_name FROM zone"); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT zoneidnumber, short_name FROM zone"), errbuf, &result)) { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) { - uint32 zoneid = atoi(row[0]); - std::string zonename = row[1]; - zonename_array.insert(std::pair(zoneid,zonename)); - } - } - else { - std::cerr << "Error in LoadZoneNames query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in LoadZoneNames query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - mysql_free_result(result); + + for (auto row= results.begin();row != results.end();++row) + { + uint32 zoneid = atoi(row[0]); + std::string zonename = row[1]; + zonename_array.insert(std::pair(zoneid,zonename)); + } return true; } uint32 Database::GetZoneID(const char* zonename) { - if (zonename == 0) + + if (zonename == nullptr) return 0; - for (auto iter = zonename_array.begin(); iter != zonename_array.end(); ++iter) { - if (strcasecmp(iter->second.c_str(), zonename) == 0) { + + for (auto iter = zonename_array.begin(); iter != zonename_array.end(); ++iter) + if (strcasecmp(iter->second.c_str(), zonename) == 0) return iter->first; - } - } + return 0; } const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { auto iter = zonename_array.find(zoneID); - if (iter != zonename_array.end()) { + if (iter != zonename_array.end()) return iter->second.c_str(); - } - else { - if (ErrorUnknown) - return "UNKNOWN"; - else - return 0; - } + + if (ErrorUnknown) + return "UNKNOWN"; + return 0; } uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int peqzone = 0; + + std::string query = StringFormat("SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version), errbuf, &result)) + if (!results.Success()) { - if (mysql_num_rows(result) > 0) - { - row = mysql_fetch_row(result); - peqzone = atoi(row[0]); - } - safe_delete_array(query); - mysql_free_result(result); - return peqzone; + std::cerr << "Error in GetPEQZone query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - else - { - std::cerr << "Error in GetPEQZone query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); - return peqzone; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } bool Database::CheckNameFilter(const char* name, bool surname) { std::string str_name = name; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; if(surname) { @@ -1440,137 +1172,117 @@ bool Database::CheckNameFilter(const char* name, bool surname) } } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name FROM name_filter"), errbuf, &result)) { - safe_delete_array(query); - while((row = mysql_fetch_row(result))) - { - std::string current_row = row[0]; - for(size_t x = 0; x < current_row.size(); ++x) - { - current_row[x] = tolower(current_row[x]); - } + + std::string query("SELECT name FROM name_filter"); + auto results = QueryDatabase(query); - if(str_name.find(current_row) != std::string::npos) - { - return false; - } - } - - mysql_free_result(result); + if (!results.Success()) + { + std::cerr << "Error in CheckNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; + // false through to true? shouldn't it be falls through to false? return true; } - else + + for (auto row = results.begin();row != results.end();++row) { - std::cerr << "Error in CheckNameFilter query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string current_row = row[0]; + + for(size_t x = 0; x < current_row.size(); ++x) + current_row[x] = tolower(current_row[x]); + + if(str_name.find(current_row) != std::string::npos) + return false; } return true; } bool Database::AddToNameFilter(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + + std::string query = StringFormat("INSERT INTO name_filter (name) values ('%s')", name); + auto results = QueryDatabase(query); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO name_filter (name) values ('%s')", name), errbuf, 0, &affected_rows)) { - std::cerr << "Error in AddToNameFilter query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + if (!results.Success()) + { + std::cerr << "Error in AddToNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - - if (affected_rows == 0) { + if (results.RowsAffected() == 0) return false; - } return true; } uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID), errbuf, &result)) + std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID); + auto results = QueryDatabase(query); + + if (!results.Success()) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 account_id = atoi(row[0]); - if (oAccountName) - strcpy(oAccountName, row[1]); - if (oStatus) - *oStatus = atoi(row[2]); - mysql_free_result(result); - return account_id; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } - return 0; + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 account_id = atoi(row[0]); + + if (oAccountName) + strcpy(oAccountName, row[1]); + if (oStatus) + *oStatus = atoi(row[2]); + + return account_id; } void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT name, status FROM account WHERE id=%i", id); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name, status FROM account WHERE id=%i", id), errbuf, &result)) + if (!results.Success()) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (oAccountName) - strcpy(oAccountName, row[0]); - if (oStatus) - *oStatus = atoi(row[1]); - } - mysql_free_result(result); + std::cerr << "Error in GetAccountFromID query '" << query << "' " << results.ErrorMessage() << std::endl; + return; } - else - std::cerr << "Error in GetAccountFromID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + if (results.RowCount() != 1) + return; + + auto row = results.begin(); + + if (oAccountName) + strcpy(oAccountName, row[0]); + if (oStatus) + *oStatus = atoi(row[1]); } void Database::ClearMerchantTemp(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "delete from merchantlist_temp"), errbuf)) { - std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + std::string query("delete from merchantlist_temp"); + auto results = QueryDatabase(query); + + if (!results.Success()) + std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; } bool Database::UpdateName(const char* oldname, const char* newname) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - + std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return false; - } - safe_delete_array(query); - if (affected_rows == 0) - { + std::string query = StringFormat("UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname); + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowsAffected() == 0) return false; - } return true; } @@ -1578,74 +1290,53 @@ bool Database::UpdateName(const char* oldname, const char* newname) { // If the name is used or an error occurs, it returns false, otherwise it returns true bool Database::CheckUsedName(const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - //if (strlen(name) > 15) - // return false; - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM character_ where name='%s'", name), errbuf, &result)) { - std::cerr << "Error in CheckUsedName query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("SELECT id FROM character_ where name='%s'", name); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - else { // It was a valid Query, so lets do our counts! - safe_delete_array(query); - uint32 tmp = mysql_num_rows(result); - mysql_free_result(result); - if (tmp > 0) // There is a Name! No change (Return False) - return false; - else // Everything is okay, so we go and do this. - return true; - } + + if (results.RowCount() > 0) + return false; + + return true; } uint8 Database::GetServerType() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname='ServerType'"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint8 ServerType = atoi(row[0]); - mysql_free_result(result); - return ServerType; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetServerType query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - return 0; + std::string query("SELECT value FROM variables WHERE varname='ServerType'"); + auto results = QueryDatabase(query); + if (!results.Success()) + { + std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; + } + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if(zonename == nullptr || strlen(zonename) == 0) - return(false); + return false; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname), errbuf, 0,&affected_rows)) { - std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << errbuf << std::endl; + std::string query = StringFormat("UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - if (affected_rows == 0) + if (results.RowsAffected() == 0) return false; return true; @@ -1656,50 +1347,40 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { } bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID), errbuf, 0,&affected_rows)) { - std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << errbuf << std::endl; + + std::string query = StringFormat("UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - if (affected_rows == 0) - return false; - - return true; + return results.RowsAffected() != 0; } uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { - //TODO: Rewrite better function - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + PlayerProfile_Struct* pp; ExtendedProfile_Struct* ext; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname), errbuf, &result)) { - safe_delete_array(query); + std::string query = StringFormat("SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname); + auto results = QueryDatabase(query); - row = mysql_fetch_row(result); - - pp = (PlayerProfile_Struct*)row[0]; - strcpy(pp->name, newname); - - ext = (ExtendedProfile_Struct*)row[1]; - - mysql_free_result(result); - } - - else { - std::cerr << "Error in CopyCharacter read query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + if (!results.Success()) + { + std::cerr << "Error in CopyCharacter read query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } - uint32 affected_rows = 0; + auto row = results.begin(); + + pp = (PlayerProfile_Struct*)row[0]; + strcpy(pp->name, newname); + + ext = (ExtendedProfile_Struct*)row[1]; + char query2[276 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 1]; char* end=query2; @@ -1709,105 +1390,86 @@ uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 a end += DoEscapeString(end, (char*) ext, sizeof(ExtendedProfile_Struct)); end += sprintf(end, "\', account_id=%d, name='%s'", acctid, newname); - if (!RunQuery(query2, (uint32) (end - query2), errbuf, 0, &affected_rows)) { - std::cerr << "Error in CopyCharacter query '" << query << "' " << errbuf << std::endl; + results = QueryDatabase(query2, (uint32) (end - query2)); + + if (!results.Success()) + { + std::cerr << "Error in CopyCharacter query '" << query2 << "' " << results.ErrorMessage() << std::endl; return 0; } - if (affected_rows == 0) { + if (results.RowsAffected() == 0) return 0; - } return 1; } bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked), errbuf, 0,&affected_rows)) { - std::cerr << "Error in SetHackerFlag query '" << query << "' " << errbuf << std::endl; - return false; - } - safe_delete_array(query); + + std::string query = StringFormat("INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked); + auto results = QueryDatabase(query); - if (affected_rows == 0) + if (!results.Success()) { + std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - return true; + return results.RowsAffected() != 0; } -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. +bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { + + //Utilize the "hacker" table, but also give zone information. + std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone); + auto results = QueryDatabase(query); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone), errbuf, 0,&affected_rows)) { - std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << errbuf << std::endl; - return false; - } - - safe_delete_array(query); - - if (affected_rows == 0) + if (!results.Success()) { + std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - return true; + return results.RowsAffected() != 0; } uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) { uint16 race_cap = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - MYSQL_RES *result; - MYSQL_ROW row; - + //Check for a racial cap! - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race), errbuf, &result, &affected_rows)) - { - if (affected_rows != 0) - { - row = mysql_fetch_row(result); - race_cap = atoi(row[0]); - } - delete[] query; - mysql_free_result(result); - } + std::string query = StringFormat("SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race); + auto results = QueryDatabase(query); - return race_cap; + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level) { uint8 skill_level = 0, skill_formula = 0; uint16 base_cap = 0, skill_cap = 0, skill_cap2 = 0, skill_cap3 = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + //Fetch the data from DB. - if (RunQuery(query, MakeAnyLenString(&query, "SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class), errbuf, &result, &affected_rows)) + std::string query = StringFormat("SELECT level, formula, pre50cap, post50cap, post60cap from skillcaps where skill = %i && class = %i", skillid, in_class); + auto results = QueryDatabase(query); + + if (results.Success() && results.RowsAffected() != 0) { - if (affected_rows != 0) - { - row = mysql_fetch_row(result); - skill_level = atoi(row[0]); - skill_formula = atoi(row[1]); - skill_cap = atoi(row[2]); - if (atoi(row[3]) > skill_cap) - skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. - skill_cap3 = atoi(row[4]); - } - delete[] query; - mysql_free_result(result); + auto row = results.begin(); + skill_level = atoi(row[0]); + skill_formula = atoi(row[1]); + skill_cap = atoi(row[2]); + if (atoi(row[3]) > skill_cap) + skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. + skill_cap3 = atoi(row[4]); } int race_skill = GetRaceSkill(skillid,in_race); @@ -1826,685 +1488,619 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 base_cap = in_level*skill_formula+skill_formula; if (base_cap > skill_cap || skill_formula == 0) base_cap = skill_cap; + //If post 50, add post 50 cap to base cap. if (in_level > 50 && skill_cap2 > 0) base_cap += skill_cap2*(in_level-50); + //No cap should ever go above its post50cap if (skill_cap3 > 0 && base_cap > skill_cap3) base_cap = skill_cap3; + //Base cap is now the max value at the person's level, return it! return base_cap; } uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 charid = atoi(row[0]); - if (oAccID) - *oAccID = atoi(row[1]); - if (oZoneID) - *oZoneID = GetZoneID(row[2]); - if(oInstanceID) - *oInstanceID = atoi(row[3]); - if (oX) - *oX = atof(row[4]); - if (oY) - *oY = atof(row[5]); - if (oZ) - *oZ = atof(row[6]); - mysql_free_result(result); - return charid; - } - mysql_free_result(result); + if (!results.Success()) + { + std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - else { - std::cerr << "Error in GetCharacterInfo query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return 0; + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + uint32 charid = atoi(row[0]); + if (oAccID) + *oAccID = atoi(row[1]); + if (oZoneID) + *oZoneID = GetZoneID(row[2]); + if(oInstanceID) + *oInstanceID = atoi(row[3]); + if (oX) + *oX = atof(row[4]); + if (oY) + *oY = atof(row[5]); + if (oZ) + *oZ = atof(row[6]); + + return charid; } bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id), errbuf)) { - std::cerr << "Error in UpdateLiveChar query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in UpdateLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); return true; } bool Database::GetLiveChar(uint32 account_id, char* cname) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charname FROM account WHERE id=%i", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - strcpy(cname,row[0]); - mysql_free_result(result); - return true; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetLiveChar query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + std::string query = StringFormat("SELECT charname FROM account WHERE id=%i", account_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in GetLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; + return false; } - return false; + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + strcpy(cname,row[0]); + + return true; } void Database::SetLFP(uint32 CharID, bool LFP) { - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfp=%i where id=%i",LFP, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); + std::string query = StringFormat("update character_ set lfp=%i where id=%i",LFP, CharID); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { + + std::string query = StringFormat("update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID); + auto results = QueryDatabase(query); - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); - + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetLFG(uint32 CharID, bool LFG) { - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set lfg=%i where id=%i",LFG, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); + std::string query = StringFormat("update character_ set lfg=%i where id=%i",LFG, CharID); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { + + std::string query = StringFormat( "update character_ set firstlogon=%i where id=%i",firstlogon, CharID); + auto results = QueryDatabase(query); - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!RunQuery(Query, MakeAnyLenString(&Query, "update character_ set firstlogon=%i where id=%i",firstlogon, CharID), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, ErrBuf); - - safe_delete_array(Query); - + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); } void Database::AddReport(std::string who, std::string against, std::string lines) { - char ErrBuf[MYSQL_ERRMSG_SIZE]; - char *Query = 0; + char *escape_str = new char[lines.size()*2+1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); - if (!RunQuery(Query, MakeAnyLenString(&Query, "INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str), ErrBuf)) - LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), ErrBuf); - - safe_delete_array(Query); + std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str); + auto results = QueryDatabase(query); safe_delete_array(escape_str); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } -void Database::SetGroupID(const char* name,uint32 id, uint32 charid, uint32 ismerc){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(id == 0){ //removing you from table - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc), errbuf)) - LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", errbuf); +void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc){ + + std::string query; + if (id == 0) + { + // removing from group + query = StringFormat("delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc); + auto results = QueryDatabase(query); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str()); + + return; } - else{ - if (!RunQuery(query, MakeAnyLenString(&query, "replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc), errbuf)) - LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", errbuf); - } - safe_delete_array(query); + + // adding to group + query = StringFormat("replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc); + auto results = QueryDatabase(query); + + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", results.ErrorMessage().c_str()); +} + +void Database::ClearAllGroups(void) +{ + std::string query("delete from group_id"); + auto results = QueryDatabase(query); + + if (!results.Success()) + std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; + + return; } void Database::ClearGroup(uint32 gid) { ClearGroupLeader(gid); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(gid == 0) { //clear all groups - //if (!RunQuery(query, MakeAnyLenString(&query, "update group_id set groupid=0 where groupid!=0"), errbuf)) - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id"), errbuf)) - printf("Unable to clear groups: %s\n",errbuf); - } else { //clear a specific group - //if (!RunQuery(query, MakeAnyLenString(&query, "update group_id set groupid=0 where groupid = %lu", gid), errbuf)) - if (!RunQuery(query, MakeAnyLenString(&query, "delete from group_id where groupid = %lu", (unsigned long)gid), errbuf)) - printf("Unable to clear groups: %s\n",errbuf); + + if(gid == 0) + { + //clear all groups + ClearAllGroups(); + return; } - safe_delete_array(query); + + //clear a specific group + std::string query = StringFormat("delete from group_id where groupid = %lu", (unsigned long)gid); + auto results = QueryDatabase(query); + + if (!results.Success()) + std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; } uint32 Database::GetGroupID(const char* name){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 groupid=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT groupid from group_id where name='%s'", name), errbuf, &result)) { - if((row = mysql_fetch_row(result))) - { - if(row[0]) - groupid=atoi(row[0]); - } - else - LogFile->write(EQEMuLog::Debug, "Character not in a group: %s", name); - mysql_free_result(result); + + std::string query = StringFormat("SELECT groupid from group_id where name='%s'", name); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error getting group id: %s", results.ErrorMessage().c_str()); + return 0; } - else - LogFile->write(EQEMuLog::Error, "Error getting group id: %s", errbuf); - safe_delete_array(query); - return groupid; + + if (results.RowCount() == 0) + { + LogFile->write(EQEMuLog::Debug, "Character not in a group: %s", name); + return 0; + } + + auto row = results.begin(); + + return atoi(row[0]); } char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + PlayerProfile_Struct pp; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile from character_ where name='%s'", name), errbuf, &result)) { - row = mysql_fetch_row(result); - unsigned long* lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); - strcpy(leaderbuf,pp.groupMembers[0]); - } - mysql_free_result(result); + + std::string query = StringFormat("SELECT profile from character_ where name='%s'", name); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cout << "Unable to get leader name: " << results.ErrorMessage() << std::endl; + return leaderbuf; } - else{ - printf("Unable to get leader name: %s\n",errbuf); - } - safe_delete_array(query); + + if (results.LengthOfColumn(0) != sizeof(PlayerProfile_Struct)) + return leaderbuf; + + auto row = results.begin(); + + memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); + strcpy(leaderbuf,pp.groupMembers[0]); + return leaderbuf; } void Database::SetGroupLeaderName(uint32 gid, const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name), errbuf)) - printf("Unable to set group leader: %s\n",errbuf); + std::string query = StringFormat("Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name); + auto results = QueryDatabase(query); - safe_delete_array(query); + if (!results.Success()) + std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; } char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; + + std::string query = StringFormat("SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid), - errbuf, &result)) { + if (!results.Success() || results.RowCount() == 0) + { + if(leaderbuf) + strcpy(leaderbuf, "UNKNOWN"); - safe_delete_array(query); + if(maintank) + maintank[0] = '\0'; - row = mysql_fetch_row(result); - unsigned long* Lengths = mysql_fetch_lengths(result); + if(assist) + assist[0] = '\0'; - if(row != nullptr){ + if(puller) + puller[0] = '\0'; - if(leaderbuf) - strcpy(leaderbuf, row[0]); + if(marknpc) + marknpc[0] = '\0'; - if(maintank) - strcpy(maintank, row[1]); - - if(assist) - strcpy(assist, row[2]); - - if(puller) - strcpy(puller, row[3]); - - if(marknpc) - strcpy(marknpc, row[4]); - - if(GLAA && (Lengths[5] == sizeof(GroupLeadershipAA_Struct))) - memcpy(GLAA, row[5], sizeof(GroupLeadershipAA_Struct)); - - mysql_free_result(result); - return leaderbuf; - } + return leaderbuf; } - else - safe_delete_array(query); + + auto row = results.begin(); if(leaderbuf) - strcpy(leaderbuf, "UNKNOWN"); + strcpy(leaderbuf, row[0]); if(maintank) - maintank[0] = 0; + strcpy(maintank, row[1]); if(assist) - assist[0] = 0; + strcpy(assist, row[2]); if(puller) - puller[0] = 0; + strcpy(puller, row[3]); if(marknpc) - marknpc[0] = 0; + strcpy(marknpc, row[4]); + + if(GLAA && results.LengthOfColumn(5) == sizeof(GroupLeadershipAA_Struct)) + memcpy(GLAA, row[5], sizeof(GroupLeadershipAA_Struct)); return leaderbuf; } -void Database::ClearGroupLeader(uint32 gid){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(gid == 0) { //clear all group leaders - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE from group_leaders"), errbuf)) - printf("Unable to clear group leaders: %s\n",errbuf); - } else { //clear a specific group leader - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE from group_leaders where gid = %lu", (unsigned long)gid), errbuf)) - printf("Unable to clear group leader: %s\n",errbuf); - } - safe_delete_array(query); +// Clearing all group leaders +void Database::ClearAllGroupLeaders(void) +{ + std::string query("DELETE from group_leaders"); + auto results = QueryDatabase(query); + + if (!results.Success()) + std::cout << "Unable to clear group leaders: " << results.ErrorMessage() << std::endl; + + return; } -bool FetchRowMap(MYSQL_RES *result, std::map &rowmap) -{ -MYSQL_FIELD *fields; -MYSQL_ROW row; -unsigned long num_fields,i; -bool retval=false; - rowmap.clear(); - if (result && (num_fields=mysql_num_fields(result)) && (row = mysql_fetch_row(result))!=nullptr && (fields = mysql_fetch_fields(result))!=nullptr) { - retval=true; - for(i=0;i %u", count,count), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) { - row = mysql_fetch_row(result); - if(atoi(row[0]) <= max) { - count = atoi(row[0]); - mysql_free_result(result); - } else { - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where id > %u ORDER BY id", count), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) { - count++; - while((row = mysql_fetch_row(result))) { - if(count < atoi(row[0])) { - instance_id = count; - mysql_free_result(result); - return true; - } else if(count > max) { - instance_id = 0; - mysql_free_result(result); - return false; - } else { - count++; - } - } - } else { - instance_id = 0; - mysql_free_result(result); - return false; - } - } else { - safe_delete_array(query); - instance_id = 0; - return false; - } - } - } else { - instance_id = 0; - mysql_free_result(result); - return false; - } - } else { - safe_delete_array(query); + + std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count); + auto results = QueryDatabase(query); + + if (!results.Success()) + { instance_id = 0; return false; } + + if (results.RowCount() == 0) + { + instance_id = 0; + return false; + } + + auto row = results.begin(); + + if (atoi(row[0]) <= max) + { + instance_id = atoi(row[0]); + return true; + } + + query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count); + results = QueryDatabase(query); + + if (!results.Success()) + { + instance_id = 0; + return false; + } + + if (results.RowCount() == 0) + { + instance_id = 0; + return false; + } + + count++; + for (auto row = results.begin();row != results.end();++row) + { + if(count < atoi(row[0])) + { + instance_id = count; + return true; + } + + if(count > max) + { + instance_id = 0; + return false; + } + + count++; + } + instance_id = count; return true; } @@ -2574,214 +2175,114 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) //perhaps purge any expireds too bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO instance_list (id, zone, version, start_time, duration)" - " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)" + " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", + (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration); + auto results = QueryDatabase(query); + + return results.Success(); } void Database::PurgeExpiredInstances() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint16 id = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM instance_list where " - "(start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) - { - row = mysql_fetch_row(result); - while(row != nullptr) - { - id = atoi(row[0]); - DeleteInstance(id); - row = mysql_fetch_row(result); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); - } + std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + if (results.RowCount() == 0) + return; + + for (auto row = results.begin();row != results.end();++row) + DeleteInstance(atoi(row[0])); } bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT INTO instance_list_player(id, charid) values(%lu, %lu)", + (unsigned long)instance_id, (unsigned long)char_id); + auto results = QueryDatabase(query); - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO instance_list_player(id, charid) " - "values(%lu, %lu)", (unsigned long)instance_id, (unsigned long)char_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + return results.Success(); } bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", + (unsigned long)instance_id, (unsigned long)char_id); + auto results = QueryDatabase(query); - if(RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", - (unsigned long)instance_id, (unsigned long)char_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + return results.Success(); } bool Database::RemoveClientsFromInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id); + auto results = QueryDatabase(query); - if(RunQuery(query, MakeAnyLenString(&query, "DELETE FROM instance_list_player WHERE id=%lu", - (unsigned long)instance_id), errbuf)) - { - safe_delete_array(query); - return true; - } - else - { - safe_delete_array(query); - return false; - } + return results.Success(); } bool Database::CheckInstanceExists(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - mysql_free_result(result); - return true; - } - mysql_free_result(result); + std::string query = StringFormat("SELECT * FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) return false; - } - else - { - safe_delete_array(query); + + if (results.RowCount() == 0) return false; - } - return false; + + return true; } void Database::BuryCorpsesInInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", - instance_id), errbuf, &result)) - { - mysql_free_result(result); - } - safe_delete_array(query); + std::string query = StringFormat("UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id); + auto results = QueryDatabase(query); } uint16 Database::GetInstanceVersion(uint16 instance_id) { - if(instance_id < 1) + if(instance_id == 0) return 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret; + std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT version FROM instance_list where id=%u", instance_id), - errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint16 Database::GetInstanceID(const char* zone, uint32 charid, int16 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint16 ret; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " + std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid); + auto results = QueryDatabase(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) @@ -2789,113 +2290,74 @@ uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) if(!zone) return 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint16 ret; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT instance_list.id FROM instance_list, instance_list_player " + std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", zone, version, charid), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) != 0) - { - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - safe_delete_array(query); + "instance_list_player.charid=%u LIMIT 1;", zone, version, charid); + auto results = QueryDatabase(query); + + if (!results.Success()) return 0; - } - return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM instance_list_player WHERE id=%u", instance_id), errbuf, &result)) { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) - { - charid_list.push_back(atoi(row[0])); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT charid FROM instance_list_player WHERE id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return; } + + for(auto row=results.begin();row != results.end();++row) + charid_list.push_back(atoi(row[0])); } void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM group_id WHERE groupid=%u", gid), - errbuf, &result)) + std::string query = StringFormat("SELECT charid FROM group_id WHERE groupid=%u", gid); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + for (auto row=results.begin();row != results.end();++row) { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - { - AddClientToInstance(instance_id, charid); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); + uint32 charid = atoi(row[0]); + if(GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); } } void Database::AssignRaidToInstance(uint32 rid, uint32 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + uint32 zone_id = ZoneIDFromInstanceID(instance_id); uint16 version = VersionFromInstanceID(instance_id); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT charid FROM raid_members WHERE raidid=%u", rid), - errbuf, &result)) + std::string query = StringFormat("SELECT charid FROM raid_members WHERE raidid=%u", rid); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + for (auto row=results.begin();row!=results.end();++row) { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - { - AddClientToInstance(instance_id, charid); - } - } - mysql_free_result(result); - } - else - { - safe_delete_array(query); + uint32 charid = atoi(row[0]); + if(GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); } } @@ -2934,208 +2396,127 @@ void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 chari void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " - "duration=%u WHERE id=%u", new_duration, instance_id), errbuf)) - { - safe_delete_array(query); - } - else - { - //error - safe_delete_array(query); - } + std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " + "duration=%u WHERE id=%u", new_duration, instance_id); + auto results = QueryDatabase(query); } bool Database::GlobalInstance(uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - bool ret; + + std::string query = StringFormat("SELECT is_global from instance_list where id=%u LIMIT 1", instance_id); + auto results = QueryDatabase(query); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT is_global from instance_list where id=%u LIMIT 1", instance_id), errbuf, &result)) - { - safe_delete_array(query); - row = mysql_fetch_row(result); - if(row) - { - ret = (atoi(row[0]) == 1) ? true : false; - } - else - { - mysql_free_result(result); - return false; - } - } - else - { - safe_delete_array(query); + if (!results.Success()) return false; - } - return ret; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + return (atoi(row[0]) == 1) ? true : false; } void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected = 0; - + std::string field; - if(win) + switch(theme) { - switch(theme) + case 1: { - case 1: - { - field = "guk_wins"; - break; - } - case 2: - { - field = "mir_wins"; - break; - } - case 3: - { - field = "mmc_wins"; - break; - } - case 4: - { - field = "ruj_wins"; - break; - } - case 5: - { - field = "tak_wins"; - break; - } - default: - { - return; - } + field = "guk_"; + break; } - } - else - { - switch(theme) + case 2: { - case 1: - { - field = "guk_losses"; - break; - } - case 2: - { - field = "mir_losses"; - break; - } - case 3: - { - field = "mmc_losses"; - break; - } - case 4: - { - field = "ruj_losses"; - break; - } - case 5: - { - field = "tak_losses"; - break; - } - default: - { - return; - } + field = "mir_"; + break; + } + case 3: + { + field = "mmc_"; + break; + } + case 4: + { + field = "ruj_"; + break; + } + case 5: + { + field = "tak_"; + break; + } + default: + { + return; } } - if(RunQuery(query, MakeAnyLenString(&query, "UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u", - field.c_str(), field.c_str(), char_id), errbuf, nullptr, &affected)) - { - safe_delete_array(query); - } + if (win) + field += "wins"; else - { - //error - safe_delete_array(query); - } + field += "losses"; - if(affected == 0) - { - if(RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `adventure_stats` SET %s=1, player_id=%u", - field.c_str(), char_id), errbuf)) - { - safe_delete_array(query); - } - else - { - //error - safe_delete_array(query); - } - } + std::string query = StringFormat("UPDATE `adventure_stats` SET %s=%s+1 WHERE player_id=%u",field.c_str(), field.c_str(), char_id); + auto results = QueryDatabase(query); + + if (results.RowsAffected() != 0) + return; + + query = StringFormat("INSERT INTO `adventure_stats` SET %s=1, player_id=%u", field.c_str(), char_id); + QueryDatabase(query); } bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, uint32 &tak_w, uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, " - "`guk_losses`, `mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", - char_id), errbuf, &result)) - { - safe_delete_array(query); - while((row = mysql_fetch_row(result)) != nullptr) - { - guk_w = atoi(row[0]); - mir_w = atoi(row[1]); - mmc_w = atoi(row[2]); - ruj_w = atoi(row[3]); - tak_w = atoi(row[4]); - guk_l = atoi(row[5]); - mir_l = atoi(row[6]); - mmc_l = atoi(row[7]); - ruj_l = atoi(row[8]); - tak_l = atoi(row[9]); - } - mysql_free_result(result); - return true; - } - else - { - safe_delete_array(query); + std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, " + "`mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", char_id); + auto results = QueryDatabase(query); + + if (!results.Success()) return false; - } + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + guk_w = atoi(row[0]); + mir_w = atoi(row[1]); + mmc_w = atoi(row[2]); + ruj_w = atoi(row[3]); + tak_w = atoi(row[4]); + guk_l = atoi(row[5]); + mir_l = atoi(row[6]); + mmc_l = atoi(row[7]); + ruj_l = atoi(row[8]); + tak_l = atoi(row[9]); + + return true; } -uint32 Database::GetGuildDBIDByCharID(uint32 char_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - int retVal = 0; +uint32 Database::GetGuildIDByCharID(uint32 char_id) +{ - if (RunQuery(query, MakeAnyLenString(&query, "SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - MYSQL_ROW row = mysql_fetch_row(result); - retVal = atoi(row[0]); - } - mysql_free_result(result); + std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + std::cerr << "Error in GetGuildIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - else { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); - return retVal; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } diff --git a/common/database.h b/common/database.h index 300fc9875..9be05f0cd 100644 --- a/common/database.h +++ b/common/database.h @@ -130,7 +130,7 @@ public: uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); - uint32 GetGuildDBIDByCharID(uint32 char_id); + uint32 GetGuildIDByCharID(uint32 char_id); void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0,float* oX = 0, float* oY = 0, float* oZ = 0); @@ -207,6 +207,7 @@ public: char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); void ClearGroupLeader(uint32 gid = 0); + /* * Raids @@ -223,7 +224,7 @@ public: bool SetVariable(const char* varname, const char* varvalue); bool LoadVariables(); uint32 LoadVariables_MQ(char** query); - bool LoadVariables_result(MYSQL_RES* result); + bool LoadVariables_result(MySQLRequestResult results); /* * General Queries @@ -262,7 +263,20 @@ private: uint32 varcache_max; VarCache_Struct** varcache_array; uint32 varcache_lastupdate; + + + /* + * Groups, utility methods. + */ + void ClearAllGroupLeaders(); + void ClearAllGroups(); + + + /* + * Raid, utility methods. + */ + void ClearAllRaids(); + void ClearAllRaidDetails(); }; -bool FetchRowMap(MYSQL_RES *result, std::map &rowmap); #endif diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 9b6236e5a..3d25236c7 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -80,10 +80,10 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo pStatus = Error; // error appears to be a disconnect error, may need to try again. - if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) + if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) { - if (retryOnFailureOnce) + if (retryOnFailureOnce) { std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl; MySQLRequestResult requestResult = QueryDatabase(query, querylen, false); @@ -95,18 +95,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo } } - + pStatus = Error; - + char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); - + std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer); - } - + } + char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); @@ -114,21 +114,26 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; #endif return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer); - + } // successful query. get results. MYSQL_RES* res = mysql_store_result(&mysql); - MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), (uint32)mysql_num_rows(res), (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); + uint32 rowCount = 0; + + if (res != nullptr) + rowCount = (uint32)mysql_num_rows(res); + + MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); #if DEBUG_MYSQL_QUERIES >= 1 - if (requestResult.Success()) + if (requestResult.Success()) { std::cout << "query successful"; if (requestResult.Result()) std::cout << ", " << (int) mysql_num_rows(requestResult.Result()) << " rows returned"; - + std::cout << ", " << requestResult.RowCount() << " rows affected"; std::cout<< std::endl; } diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp index a1fa5e3e1..4c772689d 100644 --- a/common/eq_dictionary.cpp +++ b/common/eq_dictionary.cpp @@ -237,7 +237,7 @@ std::string EmuConstants::InventorySubName(int16 sub) { return "Unknown Sub"; std::string ret_str; - StringFormat(ret_str, "Container %i", (sub + 1)); // zero-based index..but, count starts at one + ret_str = StringFormat("Container %i", (sub + 1)); // zero-based index..but, count starts at one return ret_str; } @@ -250,7 +250,7 @@ std::string EmuConstants::InventoryAugName(int16 aug) { return "Unknown Aug"; std::string ret_str; - StringFormat(ret_str, "Augment %i", (aug + 1)); // zero-based index..but, count starts at one + ret_str = StringFormat("Augment %i", (aug + 1)); // zero-based index..but, count starts at one return ret_str; } @@ -929,7 +929,7 @@ uint64 EQLimits::PossessionsBitmask(uint32 version) { /*Underfoot*/ 0x000000027FFFFFFF, /*RoF*/ 0x00000003FFFFFFFF, /*RoF2*/ 0, - + /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, @@ -950,7 +950,7 @@ uint64 EQLimits::EquipmentBitmask(uint32 version) { /*Underfoot*/ 0x00000000007FFFFF, /*RoF*/ 0x00000000007FFFFF, /*RoF2*/ 0, - + /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, @@ -971,7 +971,7 @@ uint64 EQLimits::GeneralBitmask(uint32 version) { /*Underfoot*/ 0x000000007F800000, /*RoF*/ 0x00000001FF800000, /*RoF2*/ 0, - + /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, @@ -992,7 +992,7 @@ uint64 EQLimits::CursorBitmask(uint32 version) { /*Underfoot*/ 0x0000000200000000, /*RoF*/ 0x0000000200000000, /*RoF2*/ 0, - + /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, @@ -1013,13 +1013,13 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) { /*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*RoF2*/ false, - + /*NPC*/ false, /*Merc*/ false, /*Bot*/ false, /*Pet*/ false }; - + return false; // not implemented //return local[ValidateMobVersion(version)]; } @@ -1035,7 +1035,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) { /*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, /*RoF*/ EmuConstants::ITEM_COMMON_SIZE, /*RoF2*/ 0, - + /*NPC*/ EmuConstants::ITEM_COMMON_SIZE, /*Merc*/ EmuConstants::ITEM_COMMON_SIZE, /*Bot*/ EmuConstants::ITEM_COMMON_SIZE, @@ -1055,7 +1055,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) { /*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, /*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, /*RoF2*/ 0, - + /*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Bot*/ EmuConstants::ITEM_CONTAINER_SIZE, @@ -1075,7 +1075,7 @@ bool EQLimits::CoinHasWeight(uint32 version) { /*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT, /*RoF*/ RoF::limits::COIN_HAS_WEIGHT, /*RoF2*/ true, - + /*NPC*/ true, /*Merc*/ true, /*Bot*/ true, @@ -1095,7 +1095,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) { /*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, /*RoF*/ EmuConstants::BANDOLIERS_COUNT, /*RoF2*/ 0, - + /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, @@ -1115,7 +1115,7 @@ uint32 EQLimits::BandolierSize(uint32 version) { /*Underfoot*/ EmuConstants::BANDOLIER_SIZE, /*RoF*/ EmuConstants::BANDOLIER_SIZE, /*RoF2*/ 0, - + /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, @@ -1135,7 +1135,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) { /*Underfoot*/ EmuConstants::POTION_BELT_SIZE, /*RoF*/ EmuConstants::POTION_BELT_SIZE, /*RoF2*/ 0, - + /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, diff --git a/common/logsys_eqemu.cpp b/common/logsys_eqemu.cpp index 5086114f5..e1e75996c 100644 --- a/common/logsys_eqemu.cpp +++ b/common/logsys_eqemu.cpp @@ -33,9 +33,7 @@ void log_message(LogType type, const char *fmt, ...) { } void log_messageVA(LogType type, const char *fmt, va_list args) { - std::string prefix_buffer; - - StringFormat(prefix_buffer, "[%s] ", log_type_info[type].name); + std::string prefix_buffer = StringFormat("[%s] ", log_type_info[type].name); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } diff --git a/utils/sql/git/required/2014_06_25_AA_Updates..sql b/utils/sql/git/required/2014_06_25_AA_Updates..sql new file mode 100644 index 000000000..3d7a048b6 --- /dev/null +++ b/utils/sql/git/required/2014_06_25_AA_Updates..sql @@ -0,0 +1,34 @@ +-- AA MGB update +UPDATE altadv_vars SET spellid = 5228 WHERE skill_id = 128; +UPDATE aa_actions SET spell_id = 5228, nonspell_action = 0 WHERE aaid = 128; + +-- AA Project Illusion update +UPDATE altadv_vars SET spellid = 5227 WHERE skill_id = 643; +UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643; + +-- AA Improved Reclaim Energy +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('180', '1', '241', '95', '0'); + +-- AA Headshot +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0'); + +-- AA Anatomy (Rogue Assassinate) +INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1604', 'Anatomy', '5', '3', '4294967295', '4294967295', '1604', '1604', '1', '4294967295', '0', '0', '0', '0', '512', '0', '60', '1', '10', '4294967295', '3', '0', '3', '1604', '1', '0', '0', '0', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '2', '345', '48', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0'); + +-- AA Finishing Blow Fix +DELETE FROM aa_effects WHERE aaid = 199 AND slot = 2; +DELETE FROM aa_effects WHERE aaid = 200 AND slot = 2; +DELETE FROM aa_effects WHERE aaid = 201 AND slot = 2; +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '2', '440', '50', '200'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '2', '440', '52', '200'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '1', '278', '500', '32000'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '2', '440', '54', '200'); \ No newline at end of file diff --git a/world/world_logsys.cpp b/world/world_logsys.cpp index f60186a86..d7f798b6c 100644 --- a/world/world_logsys.cpp +++ b/world/world_logsys.cpp @@ -12,8 +12,7 @@ void log_message_clientVA(LogType type, Client *who, const char *fmt, va_list args) { - std::string prefix_buffer; - StringFormat(prefix_buffer,"[%s] %s: ", log_type_info[type].name, who->GetAccountName()); + std::string prefix_buffer = StringFormat("[%s] %s: ", log_type_info[type].name, who->GetAccountName()); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } @@ -31,11 +30,11 @@ void log_message_zoneVA(LogType type, ZoneServer *who, const char *fmt, va_list const char *zone_name=who->GetZoneName(); if (zone_name == nullptr) - StringFormat(zone_tag,"[%d]", who->GetID()); + zone_tag = StringFormat("[%d]", who->GetID()); else - StringFormat(zone_tag,"[%d] [%s]",who->GetID(),zone_name); + zone_tag = StringFormat("[%d] [%s]",who->GetID(),zone_name); - StringFormat(prefix_buffer, "[%s] %s ", log_type_info[type].name, zone_tag.c_str()); + prefix_buffer = StringFormat("[%s] %s ", log_type_info[type].name, zone_tag.c_str()); LogFile->writePVA(EQEMuLog::Debug, prefix_buffer.c_str(), fmt, args); } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index f748ddc68..bd6708a88 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -2015,7 +2015,7 @@ float Mob::GetSpecialProcChances(uint16 hand) ProcBonus += static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25); ProcChance += ProcChance * ProcBonus / 100.0f; } else { - /*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.” + /*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.” Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/ ProcChance = (static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25))/100.0f;