From 523ba30d811f0ed8545934a242b4248d83bf4955 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 23 Mar 2024 20:30:56 -0400 Subject: [PATCH] [Repositories] Convert database.cpp to Repositories (#4054) * [Repositories] Convert database.cpp to Repositories - Convert all database.cpp methods to repositories where possible. * Final push. * Cleanup * Cleanup * Update database.h * Fix crash * Update database.cpp --- common/database.cpp | 2053 ++++++++--------- common/database.h | 280 +-- common/database_instances.cpp | 2 +- common/repositories/account_repository.h | 44 + .../repositories/adventure_stats_repository.h | 58 + .../base/base_account_ip_repository.h | 20 +- .../base/base_variables_repository.h | 20 +- common/repositories/group_id_repository.h | 10 +- .../repositories/group_leaders_repository.h | 10 +- .../repositories/guild_members_repository.h | 1 + .../inventory_snapshots_repository.h | 23 + common/repositories/raid_details_repository.h | 10 + common/repositories/raid_leaders_repository.h | 297 --- common/repositories/raid_members_repository.h | 12 +- common/shareddb.cpp | 3 +- .../generators/repository-generator.pl | 10 +- world/client.cpp | 38 +- world/cliententry.cpp | 2 +- world/console.cpp | 3 +- zone/api_service.cpp | 4 +- zone/embparser_api.cpp | 4 +- zone/gm_commands/movechar.cpp | 2 +- zone/zone.cpp | 12 +- 23 files changed, 1287 insertions(+), 1631 deletions(-) delete mode 100644 common/repositories/raid_leaders_repository.h diff --git a/common/database.cpp b/common/database.cpp index 7bdbcc1cc..aad665464 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -30,13 +30,25 @@ #include #include "../common/repositories/account_repository.h" +#include "../common/repositories/adventure_stats_repository.h" #include "../common/repositories/character_bind_repository.h" #include "../common/repositories/character_data_repository.h" #include "../common/repositories/character_languages_repository.h" #include "../common/repositories/character_leadership_abilities_repository.h" #include "../common/repositories/character_skills_repository.h" +#include "../common/repositories/data_buckets_repository.h" #include "../common/repositories/group_id_repository.h" #include "../common/repositories/group_leaders_repository.h" +#include "../common/repositories/guild_members_repository.h" +#include "../common/repositories/instance_list_repository.h" +#include "../common/repositories/inventory_snapshots_repository.h" +#include "../common/repositories/ip_exemptions_repository.h" +#include "../common/repositories/name_filter_repository.h" +#include "../common/repositories/npc_types_repository.h" +#include "../common/repositories/raid_details_repository.h" +#include "../common/repositories/raid_members_repository.h" +#include "../common/repositories/reports_repository.h" +#include "../common/repositories/variables_repository.h" // Disgrace: for windows compile #ifdef _WINDOWS @@ -65,360 +77,272 @@ extern Client client; -Database::Database () { -} +Database::Database() { } -/* -Establish a connection to a mysql database with the supplied parameters -*/ +Database::~Database() { } -Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +Database::Database( + const std::string& host, + const std::string& user, + const std::string& password, + const std::string& database, + uint32 port +) { - Connect(host, user, passwd, database, port); + Connect(host, user, password, database, port); } -bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port, std::string connection_label) { - uint32 errnum= 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { - LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, errbuf); +bool Database::Connect( + const std::string& host, + const std::string& user, + const std::string& password, + const std::string& database, + uint32 port, + std::string connection_label +) +{ + uint32 error_number = 0; + char error_buffer[MYSQL_ERRMSG_SIZE]; + + if (!Open(host.c_str(), user.c_str(), password.c_str(), database.c_str(), port, &error_number, error_buffer)) { + LogError("Connection [{}] Failed to connect to database Error [{}]", connection_label, error_buffer); return false; - } - else { - LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host,port); + } else { + LogInfo("Connected to database [{}] [{}] @ [{}:{}]", connection_label, database, host, port); return true; } } -/* - Close the connection to the database -*/ - -Database::~Database() +uint32 Database::CheckLogin( + const std::string& name, + const std::string& password, + const std::string& loginserver, + int16* status +) { -} - -/* - 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, const char *loginserver, int16* oStatus) { - - if (strlen(name) >= 50 || strlen(password) >= 50) - return(0); - - char temporary_username[100]; - char temporary_password[100]; - - DoEscapeString(temporary_username, name, strlen(name)); - DoEscapeString(temporary_password, password, strlen(password)); - - std::string query = fmt::format( - "SELECT id, status FROM account WHERE `name` = '{}' AND ls_id = '{}' AND password is NOT NULL " - "AND length(password) > 0 AND (password = '{}' OR password = MD5('{}'))", - temporary_username, - Strings::Escape(loginserver), - temporary_password, - temporary_password - ); - - auto results = QueryDatabase(query); - - if (!results.Success() || !results.RowCount()) { + if (name.length() >= 50 || password.length() >= 50) { return 0; } - auto row = results.begin(); + const auto& l = AccountRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}' AND `ls_id` = '{}' AND `password` IS NOT NULL AND LENGTH(`password`) > 0 AND (`password` = '{}' OR `password` = MD5('{}'))", + Strings::Escape(name), + Strings::Escape(loginserver), + Strings::Escape(password), + Strings::Escape(password) + ) + ); - auto id = Strings::ToUnsignedInt(row[0]); - - if (oStatus) { - *oStatus = Strings::ToInt(row[1]); + if (l.empty()) { + return 0; } - return id; + auto e = l.front(); + + if (status) { + *status = e.status; + } + + return e.id; } -//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(std::string login_ip) +bool Database::CheckBannedIPs(const std::string& login_ip) { - auto query = fmt::format( - "SELECT ip_address FROM banned_ips WHERE ip_address = '{}'", - login_ip + const std::string& query = fmt::format( + "SELECT `ip_address` FROM `banned_ips` WHERE `ip_address` = '{}'", + Strings::Escape(login_ip) ); - auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() != 0) { + auto results = QueryDatabase(query); + if (!results.Success() || results.RowCount()) { return true; } return false; } -bool Database::AddBannedIP(std::string banned_ip, std::string notes) { +bool Database::AddBannedIP(const std::string& banned_ip, const std::string& notes) +{ auto query = fmt::format( - "INSERT into banned_ips SET ip_address = '{}', notes = '{}'", + "INSERT INTO banned_ips SET `ip_address` = '{}', `notes` = '{}'", Strings::Escape(banned_ip), Strings::Escape(notes) ); + auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - return true; + return results.Success(); } - bool Database::CheckGMIPs(std::string login_ip, uint32 account_id) { +bool Database::CheckGMIPs(const std::string& login_ip, uint32 account_id) +{ auto query = fmt::format( - "SELECT * FROM `gm_ips` WHERE `ip_address` = '{}' AND `account_id` = {}", - login_ip, + "SELECT `name`, `account_id`, `ip_address` FROM `gm_ips` WHERE `ip_address` = '{}' AND `account_id` = {}", + Strings::Escape(login_ip), account_id ); - auto results = QueryDatabase(query); + auto results = QueryDatabase(query); if (!results.Success()) { return false; } - if (results.RowCount() == 1) { - return true; - } - - return false; + return results.RowCount(); } -void Database::LoginIP(uint32 account_id, std::string login_ip) { +void Database::LoginIP(uint32 account_id, const std::string& login_ip) +{ auto query = fmt::format( - "INSERT INTO account_ip SET accid = {}, ip = '{}' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", + "INSERT INTO account_ip SET `accid` = {}, `ip` = '{}' ON DUPLICATE KEY UPDATE count = (count + 1), lastused = NOW()", account_id, - login_ip + Strings::Escape(login_ip) ); + QueryDatabase(query); } int16 Database::CheckStatus(uint32 account_id) { - auto query = fmt::format( - "SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = {}", - account_id - ); - auto results = QueryDatabase(query); - - if (!results.Success() || results.RowCount() != 1) { - return 0; - } - - auto row = results.begin(); - int16 status = Strings::ToInt(row[0]); - int32 date_diff = 0; - - if (row[1]) { - date_diff = Strings::ToInt(row[1]); - } - - if (date_diff > 0) { - return -1; - } - - return status; + return AccountRepository::GetAccountStatus(*this, account_id); } -/** - * @param name - * @param password - * @param status - * @param loginserver - * @param lsaccount_id - * @return - */ uint32 Database::CreateAccount( - const char *name, - const char *password, + const std::string& name, + const std::string& password, int16 status, - const char *loginserver, + const std::string& loginserver, uint32 lsaccount_id ) { - std::string query; + auto e = AccountRepository::NewEntity(); - if (password) { - query = StringFormat( - "INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();", - name, - password, - status, - loginserver, - lsaccount_id - ); - } - else { - query = StringFormat( - "INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();", - name, - status, - loginserver, - lsaccount_id - ); + e.name = name; + e.status = status; + e.ls_id = loginserver; + e.lsaccount_id = lsaccount_id; + e.time_creation = std::time(nullptr); + + if (!password.empty()) { + e.password = password; } - LogInfo("Account Attempting to be created: [{0}:{1}] status: {2}", loginserver, name, status); - auto results = QueryDatabase(query); + LogInfo("Account Attempting to be created: [{}:{}] status: {}", loginserver, name, status); - if (!results.Success()) { + e = AccountRepository::InsertOne(*this, e); + + if (!e.id) { return 0; } - if (results.LastInsertedID() == 0) { - return 0; - } - - return results.LastInsertedID(); + return e.id; } -bool Database::DeleteAccount(const char* name, const char *loginserver) { - std::string query = StringFormat("DELETE FROM account WHERE `name`='%s' AND ls_id='%s'", name, loginserver); - LogInfo("Account Attempting to be deleted:'[{}]:[{}]'", loginserver, name); - - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - return results.RowsAffected() == 1; +bool Database::SetLocalPassword(uint32 account_id, const std::string& password) +{ + return AccountRepository::UpdatePassword(*this, account_id, password); } -bool Database::SetLocalPassword(uint32 accid, const char* password) { - std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", Strings::Escape(password).c_str(), accid); - - auto results = QueryDatabase(query); - - if (!results.Success()) { - return false; - } - - return true; -} - -bool Database::SetAccountStatus(const char* name, int16 status) { - 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; - - 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; - } - - return true; -} - -/** - * @param account_name - * @param status - * @return - */ bool Database::SetAccountStatus(const std::string& account_name, int16 status) { LogInfo("Account [{}] is attempting to be set to status [{}]", account_name, status); - std::string query = fmt::format( - "UPDATE account SET status = {} WHERE name = '{}'", - status, - account_name + auto l = AccountRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(account_name) + ) ); - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (l.empty()) { return false; } - if (results.RowsAffected() == 0) { - LogWarning("Account [{}] does not exist!", account_name); - return false; - } + auto e = l.front(); - return true; + e.status = status; + + return AccountRepository::UpdateOne(*this, e); } -/* This initially creates the character during character create */ -bool Database::ReserveName(uint32 account_id, char* name) { - std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name); - auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { - if (row[0] && Strings::ToInt(row[0]) > 0){ - LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name); - return false; - } - } - - query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); - results = QueryDatabase(query); - if (!results.Success() || !results.ErrorMessage().empty()){ return false; } - - // Put character into the default guild if rule is being used. - int guild_id = RuleI(Character, DefaultGuild); - - if (guild_id != 0) { - int character_id=results.LastInsertedID(); - if (character_id > -1) { - query = StringFormat("INSERT INTO `guild_members` SET `char_id` = %i, `guild_id` = '%i'", character_id, guild_id); - results = QueryDatabase(query); - if (!results.Success() || !results.ErrorMessage().empty()){ - LogInfo("Could not put character [{}] into default Guild", name); - } - } - } - - return true; -} - -/** - * @param character_name - * @return - */ -bool Database::DeleteCharacter(char *character_name) +bool Database::ReserveName(uint32 account_id, const std::string& name) { - uint32 character_id = 0; - if (!character_name || !strlen(character_name)) { - LogInfo("DeleteCharacter: request to delete without a name (empty char slot)"); + const auto& l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) + ); + + if (!l.empty()) { + LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name); return false; } - std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name); - auto results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { - character_id = Strings::ToUnsignedInt(row[0]); + auto e = CharacterDataRepository::NewEntity(); + + e.account_id = account_id; + e.name = name; + + e = CharacterDataRepository::InsertOne(*this, e); + + if (!e.id) { + return false; } - if (character_id <= 0) { - LogError("Invalid Character ID [{}]", character_name); + const int guild_id = RuleI(Character, DefaultGuild); + if (guild_id != 0) { + if (e.id) { + auto g = GuildMembersRepository::NewEntity(); + + g.char_id = e.id; + g.guild_id = guild_id; + + GuildMembersRepository::InsertOne(*this, g); + } + } + + return true; +} + +bool Database::DeleteCharacter(const std::string& name) +{ + if (name.empty()) { + LogInfo("Request to delete without a name."); + return false; + } + + const auto& l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) + ); + + if (l.empty()) { + return false; + } + + auto e = l.front(); + + if (!e.id) { return false; } std::string delete_type = "hard-deleted"; if (RuleB(Character, SoftDeletes)) { delete_type = "soft-deleted"; - query = fmt::format( + + std::string query = fmt::format( SQL( - UPDATE - character_data - SET - name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64), - deleted_at = NOW() - WHERE - id = '{}' + UPDATE character_data SET name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64), deleted_at = NOW() + WHERE id = {} ), - character_id + e.id ); QueryDatabase(query); @@ -426,20 +350,17 @@ bool Database::DeleteCharacter(char *character_name) if (RuleB(Bots, Enabled)) { query = fmt::format( SQL( - UPDATE - bot_data - SET - name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64) - WHERE - owner_id = '{}' + UPDATE bot_data SET name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64) WHERE owner_id = {} ), - character_id + e.id ); + QueryDatabase(query); + LogInfo( "[DeleteCharacter] character_name [{}] ({}) bots are being [{}]", - character_name, - character_id, + e.name, + e.id, delete_type ); } @@ -447,14 +368,21 @@ bool Database::DeleteCharacter(char *character_name) return true; } - for (const auto &iter: DatabaseSchema::GetCharacterTables()) { - std::string table_name = iter.first; - std::string character_id_column_name = iter.second; + for (const auto &t : DatabaseSchema::GetCharacterTables()) { + const std::string& table_name = t.first; + const std::string& character_id_column_name = t.second; - QueryDatabase(fmt::format("DELETE FROM {} WHERE {} = {}", table_name, character_id_column_name, character_id)); + QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + table_name, + character_id_column_name, + e.id + ) + ); } - LogInfo("character_name [{}] ({}) is being [{}]", character_name, character_id, delete_type); + LogInfo("character_name [{}] ({}) is being [{}]", e.name, e.id, delete_type); return true; } @@ -642,290 +570,235 @@ uint32 Database::GetCharacterID(const std::string& name) return e.id; } -/* - This function returns the account_id that owns the character with - 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) { - std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", Strings::Escape(charname).c_str()); +uint32 Database::GetAccountIDByChar(const std::string& name, uint32* character_id) +{ + const auto& l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) + ); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + if (l.empty()) { return 0; } - if (results.RowCount() != 1) - return 0; + auto e = l.front(); - auto row = results.begin(); - - uint32 accountId = Strings::ToUnsignedInt(row[0]); - - if (oCharID) - *oCharID = Strings::ToUnsignedInt(row[1]); - - return accountId; -} - -// Retrieve account_id for a given char_id -uint32 Database::GetAccountIDByChar(uint32 char_id) { - std::string query = StringFormat("SELECT `account_id` FROM `character_data` WHERE `id` = %i LIMIT 1", char_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; + if (character_id) { + *character_id = e.id; } - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + return e.account_id; } -uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) { +uint32 Database::GetAccountIDByChar(uint32 character_id) +{ + const auto& e = CharacterDataRepository::FindOne(*this, character_id); + + return e.id ? e.account_id : 0; +} + +uint32 Database::GetAccountIDByName(const std::string& account_name, const std::string& loginserver, int16* status, uint32* lsaccount_id) +{ if (!isAlphaNumeric(account_name.c_str())) { return 0; } - auto query = fmt::format( - "SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '{}' AND `ls_id` = '{}' LIMIT 1", - Strings::Escape(account_name), - Strings::Escape(loginserver) + const auto& l = AccountRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}' AND `ls_id` = '{}' LIMIT 1", + Strings::Escape(account_name), + Strings::Escape(loginserver) + ) ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { + if (l.empty()) { return 0; } - auto row = results.begin(); - auto account_id = Strings::ToUnsignedInt(row[0]); + auto e = l.front(); if (status) { - *status = static_cast(Strings::ToInt(row[1])); + *status = e.status; } - if (lsid) { - *lsid = row[2] ? Strings::ToUnsignedInt(row[2]) : 0; + if (lsaccount_id) { + *lsaccount_id = e.lsaccount_id; } - return account_id; + return e.id; } -void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - std::string query = StringFormat("SELECT `name`, `lsaccount_id` FROM `account` WHERE `id` = '%i'", accountid); - auto results = QueryDatabase(query); +const std::string& Database::GetAccountName(uint32 account_id, uint32* lsaccount_id) +{ + const auto& e = AccountRepository::FindOne(*this, account_id); - if (!results.Success()) { - return; + if (!e.id) { + return std::string(); } - if (results.RowCount() != 1) - return; - - auto row = results.begin(); - - strcpy(name, row[0]); - if (row[1] && oLSAccountID) { - *oLSAccountID = Strings::ToUnsignedInt(row[1]); + if (lsaccount_id) { + *lsaccount_id = e.lsaccount_id; } + return e.name; } -void Database::GetCharName(uint32 char_id, char* name) { - std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE id='%i'", char_id); - auto results = QueryDatabase(query); +const std::string& Database::GetCharName(uint32 character_id) +{ + const auto& e = CharacterDataRepository::FindOne(*this, character_id); - if (!results.Success()) { - return; - } - - auto row = results.begin(); - for (auto row = results.begin(); row != results.end(); ++row) { - strcpy(name, row[0]); - } + return e.id ? e.name : std::string(); } -std::string Database::GetCharNameByID(uint32 char_id) { - std::string query = fmt::format("SELECT `name` FROM `character_data` WHERE id = {}", char_id); - auto results = QueryDatabase(query); - std::string res; +const std::string& Database::GetCharNameByID(uint32 character_id) +{ + const auto& e = CharacterDataRepository::FindOne(*this, character_id); - if (!results.Success()) { - return res; - } - - if (results.RowCount() == 0) { - return res; - } - - auto row = results.begin(); - res = row[0]; - return res; + return e.id ? e.name : std::string(); } -std::string Database::GetNPCNameByID(uint32 npc_id) { - std::string query = fmt::format("SELECT `name` FROM `npc_types` WHERE id = {}", npc_id); - auto results = QueryDatabase(query); - std::string res; +const std::string& Database::GetNPCNameByID(uint32 npc_id) +{ + const auto& e = NpcTypesRepository::FindOne(*this, npc_id); - if (!results.Success()) { - return res; - } - - if (results.RowCount() == 0) { - return res; - } - - auto row = results.begin(); - res = row[0]; - return res; + return e.id ? e.name : std::string(); } -std::string Database::GetCleanNPCNameByID(uint32 npc_id) { - std::string query = fmt::format("SELECT `name` FROM `npc_types` WHERE id = {}", npc_id); - auto results = QueryDatabase(query); - std::string res; - std::string mob_name; +const std::string& Database::GetCleanNPCNameByID(uint32 npc_id) +{ + const auto& e = NpcTypesRepository::FindOne(*this, npc_id); - if (!results.Success()) { - return res; + if (!e.id) { + return std::string(); } - if (results.RowCount() == 0) { - return res; - } + std::string mob_name = e.name; + std::string result; - auto row = results.begin(); - mob_name = row[0]; - CleanMobName(mob_name.begin(), mob_name.end(), std::back_inserter(res)); - return res; + CleanMobName(mob_name.begin(), mob_name.end(), std::back_inserter(result)); + + return result; } -bool Database::LoadVariables() { - auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update)); +bool Database::LoadVariables() +{ + const auto& l = VariablesRepository::GetWhere( + *this, + fmt::format( + "UNIX_TIMESTAMP(`ts`) >= {}", + varcache.last_update + ) + ); - if (!results.Success()) - return false; - - if (results.RowCount() == 0) + if (l.empty()) { return true; + } LockMutex lock(&Mvarcache); - std::string key, value; - for (auto row = results.begin(); row != results.end(); ++row) { - varcache.last_update = Strings::ToUnsignedInt(row[2]); // ahh should we be comparing if this is newer? - key = row[0]; - value = row[1]; - std::transform(std::begin(key), std::end(key), std::begin(key), ::tolower); // keys are lower case, DB doesn't have to be - varcache.Add(key, value); + for (const auto& e : l) { + varcache.last_update = std::time(nullptr); + + varcache.Add(Strings::ToLower(e.varname), e.value); } - LogInfo("Loaded [{}] variable(s)", Strings::Commify(std::to_string(results.RowCount()))); + LogInfo( + "Loaded [{}] Variable{}", + Strings::Commify(l.size()), + l.size() != 1 ? "s" : "" + ); return true; } -// Gets variable from 'variables' table -bool Database::GetVariable(std::string varname, std::string &varvalue) +bool Database::GetVariable(const std::string& name, std::string& value) { - varvalue.clear(); - LockMutex lock(&Mvarcache); - if (varname.empty()) + if (name.empty()) { return false; + } - std::transform(std::begin(varname), std::end(varname), std::begin(varname), ::tolower); // all keys are lower case - auto tmp = varcache.Get(varname); - if (tmp) { - varvalue = *tmp; + auto v = varcache.Get(Strings::ToLower(name)); + + if (v) { + value = *v; return true; } + return false; } -bool Database::SetVariable(const std::string& varname, const std::string &varvalue) +bool Database::SetVariable(const std::string& name, const std::string& value) { - std::string escaped_name = Strings::Escape(varname); - std::string escaped_value = Strings::Escape(varvalue); - std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str()); - auto results = QueryDatabase(query); + auto l = VariablesRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) + ); - if (!results.Success()) + if (l.empty()) { return false; + } + + auto variable = l.front(); + + variable.value = value; + + const int updated = VariablesRepository::UpdateOne(*this, variable); + + if (updated) { + LoadVariables(); - if (results.RowsAffected() == 1) - { - LoadVariables(); // refresh cache return true; } - query = StringFormat("Insert Into variables (varname, value) values ('%s', '%s')", escaped_name.c_str(), escaped_value.c_str()); - results = QueryDatabase(query); + auto e = VariablesRepository::NewEntity(); - if (results.RowsAffected() != 1) - return false; + e.varname = name; + e.value = value; - LoadVariables(); // refresh cache - return true; -} + e = VariablesRepository::InsertOne(*this, e); -void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum) -{ - QueryDatabase( - fmt::format( - "UPDATE `account` SET `{}` = '{}' WHERE `id` = {}", - field_name, - checksum, - account_id - ) - ); -} - -bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid, float* graveyard_x, float* graveyard_y, float* graveyard_z, float* graveyard_heading) { - - std::string query = StringFormat("SELECT zone_id, x, y, z, heading FROM graveyard WHERE id=%i", graveyard_id); - auto results = QueryDatabase(query); - - if (!results.Success()){ + if (!e.id) { return false; } - if (results.RowCount() != 1) - return false; - - auto row = results.begin(); - - if(graveyard_zoneid != nullptr) - *graveyard_zoneid = Strings::ToUnsignedInt(row[0]); - if(graveyard_x != nullptr) - *graveyard_x = Strings::ToFloat(row[1]); - if(graveyard_y != nullptr) - *graveyard_y = Strings::ToFloat(row[2]); - if(graveyard_z != nullptr) - *graveyard_z = Strings::ToFloat(row[3]); - if(graveyard_heading != nullptr) - *graveyard_heading = Strings::ToFloat(row[4]); + LoadVariables(); return true; } -uint8 Database::GetPEQZone(uint32 zone_id, uint32 version){ +void Database::SetAccountCRCField(uint32 account_id, const std::string& field_name, uint64 checksum) +{ + auto e = AccountRepository::FindOne(*this, account_id); + if (Strings::EqualFold(field_name, "crc_basedata")) { + e.crc_basedata = checksum; + } else if (Strings::EqualFold(field_name, "crc_eqgame")) { + e.crc_eqgame = checksum; + } else if (Strings::EqualFold(field_name, "crc_skillcaps")) { + e.crc_skillcaps = checksum; + } + + AccountRepository::UpdateOne(*this, e); +} + +uint8 Database::GetPEQZone(uint32 zone_id, uint32 version) +{ auto z = GetZoneVersionWithFallback(zone_id, version); return z ? z->peqzone : 0; } -bool Database::CheckNameFilter(std::string name, bool surname) +bool Database::CheckNameFilter(const std::string& name, bool surname) { - name = Strings::ToLower(name); - // the minimum 4 is enforced by the client too if (name.empty() || name.size() < 4) { return false; @@ -957,15 +830,14 @@ bool Database::CheckNameFilter(std::string name, bool surname) } } - std::string query = "SELECT name FROM name_filter"; - auto results = QueryDatabase(query); - if (!results.Success()) { + const auto& l = NameFilterRepository::All(*this); + + if (l.empty()) { return true; } - for (auto row : results) { - std::string current_row = Strings::ToLower(row[0]); - if (name.find(current_row) != std::string::npos) { + for (const auto& e : l) { + if (Strings::Contains(Strings::ToLower(name), Strings::ToLower(e.name))) { return false; } } @@ -973,82 +845,46 @@ bool Database::CheckNameFilter(std::string name, bool surname) return true; } -bool Database::AddToNameFilter(std::string name) { - auto query = fmt::format( - "INSERT INTO name_filter (name) values ('{}')", - name - ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowsAffected()) { - return false; - } +bool Database::AddToNameFilter(const std::string& name) +{ + auto e = NameFilterRepository::NewEntity(); - return true; + e.name = name; + + return NameFilterRepository::InsertOne(*this, e).id; } -/** - * @param in_loginserver_id - * @param in_loginserver_account_id - * @param in_account_name - * @param in_status - * @return - */ uint32 Database::GetAccountIDFromLSID( - const std::string &in_loginserver_id, + const std::string& in_loginserver_id, uint32 in_loginserver_account_id, - char *in_account_name, - int16 *in_status + char* in_account_name, + int16* in_status ) { - uint32 account_id = 0; - auto query = fmt::format( - "SELECT id, `name`, status FROM account WHERE lsaccount_id = {0} AND ls_id = '{1}'", - in_loginserver_account_id, - in_loginserver_id + const auto& l = AccountRepository::GetWhere( + *this, + fmt::format( + "`lsaccount_id` = {} AND `ls_id` = '{}'", + in_loginserver_account_id, + in_loginserver_id + ) ); - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (l.empty()) { return 0; } - if (results.RowCount() != 1) { - return 0; + auto e = l.front(); + + if (in_account_name) { + strcpy(in_account_name, e.name.c_str()); } - for (auto row = results.begin(); row != results.end(); ++row) { - account_id = Strings::ToUnsignedInt(row[0]); - - if (in_account_name) { - strcpy(in_account_name, row[1]); - } - if (in_status) { - *in_status = Strings::ToInt(row[2]); - } + if (in_status) { + *in_status = e.status; } - return account_id; -} - -void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { - - std::string query = StringFormat("SELECT `name`, status FROM account WHERE id=%i", id); - auto results = QueryDatabase(query); - - if (!results.Success()){ - return; - } - - if (results.RowCount() != 1) - return; - - auto row = results.begin(); - - if (oAccountName) - strcpy(oAccountName, row[0]); - if (oStatus) - *oStatus = Strings::ToInt(row[1]); + return e.id; } void Database::ClearMerchantTemp() @@ -1056,187 +892,159 @@ void Database::ClearMerchantTemp() MerchantlistTempRepository::ClearTemporaryMerchantLists(*this); } -bool Database::UpdateName(const char* oldname, const char* newname) { - std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - std::string query = StringFormat("UPDATE `character_data` SET `name` = '%s' WHERE `name` = '%s';", newname, oldname); - auto results = QueryDatabase(query); +bool Database::UpdateName(const std::string& old_name, const std::string& new_name) +{ + LogInfo("Renaming [{}] to [{}]", old_name, new_name); - if (!results.Success()) - return false; - - if (results.RowsAffected() == 0) - return false; - - return true; -} - -// If the name is used or an error occurs, it returns false, otherwise it returns true -bool Database::CheckUsedName(std::string name) { - auto query = fmt::format( - "SELECT `id` FROM `character_data` WHERE `name` = '{}'", - name + auto l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(old_name) + ) ); - auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount()) { + + if (l.empty()) { return false; } - return true; + auto e = l.front(); + + e.name = new_name; + + return CharacterDataRepository::UpdateOne(*this, e); } -uint8 Database::GetServerType() { - std::string query("SELECT `value` FROM `variables` WHERE `varname` = 'ServerType' LIMIT 1"); - auto results = QueryDatabase(query); - if (!results.Success()) { +bool Database::CheckUsedName(const std::string& name) +{ + return !CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) + ).empty(); +} + +uint32 Database::GetServerType() +{ + const auto& l = VariablesRepository::GetWhere(*this, "`varname` = 'ServerType' LIMIT 1"); + + if (l.empty()) { return 0; } - if (results.RowCount() != 1) - return 0; + auto e = l.front(); - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + return Strings::ToUnsignedInt(e.value); } bool Database::MoveCharacterToZone(uint32 character_id, uint32 zone_id) { - std::string query = StringFormat( - "UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", - zone_id, - character_id + auto e = CharacterDataRepository::FindOne(*this, character_id); + + e.zone_id = zone_id; + + e.x = e.y = e.z = -1; + + return CharacterDataRepository::UpdateOne(*this, e); +} + +bool Database::MoveCharacterToZone(const std::string& name, uint32 zone_id) +{ + auto l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) ); - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (l.empty()) { return false; } - return results.RowsAffected() != 0; + auto e = l.front(); + + e.zone_id = zone_id; + + e.x = e.y = e.z = -1; + + return CharacterDataRepository::UpdateOne(*this, e); } -bool Database::MoveCharacterToZone(const char *charname, uint32 zone_id) +bool Database::UpdateLiveChar(const std::string& name, uint32 account_id) { - std::string query = StringFormat( - "UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `name` = '%s'", - zone_id, - charname - ); + auto e = AccountRepository::FindOne(*this, account_id); - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (!e.id) { return false; } - return results.RowsAffected() != 0; + e.charname = name; + + return AccountRepository::UpdateOne(*this, e); } -uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) +const std::string& Database::GetLiveChar(uint32 account_id) { - uint16 race_cap = 0; + auto e = AccountRepository::FindOne(*this, account_id); - //Check for a racial cap! - std::string query = StringFormat("SELECT skillcap from race_skillcaps where skill = %i && race = %i", skillid, in_race); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + return e.id ? e.charname : std::string(); } -uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id) +void Database::SetLFP(uint32 character_id, bool is_lfp) { - auto query = fmt::format( - "SELECT `id`, `account_id`, `zone_id`, `zone_instance` FROM `character_data` WHERE `name` = '{}'", - Strings::Escape(character_name) - ); + auto e = CharacterDataRepository::FindOne(*this, character_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - return 0; - } + e.lfp = is_lfp ? 1 : 0; - auto row = results.begin(); - auto character_id = Strings::ToUnsignedInt(row[0]); - *account_id = Strings::ToUnsignedInt(row[1]); - *zone_id = Strings::ToUnsignedInt(row[2]); - *instance_id = Strings::ToUnsignedInt(row[3]); - - return character_id; + CharacterDataRepository::UpdateOne(*this, e); } -bool Database::UpdateLiveChar(char* charname, uint32 account_id) { - - std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;", charname, account_id); - auto results = QueryDatabase(query); - - if (!results.Success()){ - return false; - } - - return true; -} - -bool Database::GetLiveChar(uint32 account_id, char* cname) { - - std::string query = StringFormat("SELECT charname FROM account WHERE id=%i", account_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - 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) { - std::string query = StringFormat("UPDATE `character_data` SET `lfp` = %i WHERE `id` = %i",LFP, CharID); - QueryDatabase(query); -} - -void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { - std::string query = StringFormat("update `character_data` SET `lfp` = %i, `lfg` = %i, `firstlogon` = %i WHERE `id` = %i",LFP, LFG, firstlogon, CharID); - QueryDatabase(query); -} - -void Database::SetLFG(uint32 CharID, bool LFG) { - std::string query = StringFormat("update `character_data` SET `lfg` = %i WHERE `id` = %i",LFG, CharID); - QueryDatabase(query); -} - -void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { - std::string query = StringFormat( "UPDATE `character_data` SET `firstlogon` = %i WHERE `id` = %i",firstlogon, CharID); - QueryDatabase(query); -} - -void Database::AddReport(std::string who, std::string against, std::string lines) +void Database::SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon) { - auto escape_str = new char[lines.size() * 2 + 1]; - DoEscapeString(escape_str, lines.c_str(), lines.size()); + auto e = CharacterDataRepository::FindOne(*this, character_id); - std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", Strings::Escape(who).c_str(), Strings::Escape(against).c_str(), escape_str); - QueryDatabase(query); - safe_delete_array(escape_str); + e.firstlogon = first_logon; + e.lfg = is_lfg ? 1 : 0; + e.lfp = is_lfp ? 1 : 0; + + CharacterDataRepository::UpdateOne(*this, e); } -void Database::ClearAllGroups(void) +void Database::SetLFG(uint32 character_id, bool is_lfg) { - std::string query("DELETE FROM `group_id`"); - QueryDatabase(query); - return; + auto e = CharacterDataRepository::FindOne(*this, character_id); + + e.lfg = is_lfg ? 1 : 0; + + CharacterDataRepository::UpdateOne(*this, e); +} + +void Database::SetFirstLogon(uint32 character_id, uint8 first_logon) +{ + auto e = CharacterDataRepository::FindOne(*this, character_id); + + e.firstlogon = first_logon; + + CharacterDataRepository::UpdateOne(*this, e); +} + +void Database::AddReport(const std::string& who, const std::string& against, const std::string& lines) +{ + auto e = ReportsRepository::NewEntity(); + + e.name = Strings::Escape(who); + e.reported = Strings::Escape(against); + e.reported_text = Strings::Escape(lines); + + ReportsRepository::InsertOne(*this, e); +} + +void Database::ClearAllGroups() +{ + GroupIdRepository::ClearAllGroups(*this); } void Database::ClearGroup(uint32 group_id) { @@ -1300,21 +1108,29 @@ std::string Database::GetGroupLeaderForLogin(const std::string& character_name) return e.gid ? e.leadername : std::string(); } -void Database::SetGroupLeaderName(uint32 gid, const char* name) { - std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", Strings::Escape(name).c_str(), gid); - auto result = QueryDatabase(query); +void Database::SetGroupLeaderName(uint32 group_id, const std::string& name) +{ + auto e = GroupLeadersRepository::FindOne(*this, group_id); - if(result.RowsAffected() != 0) { + e.leadername = name; + + const int updated_leader = GroupLeadersRepository::UpdateOne(*this, e); + + if (!updated_leader) { return; } - query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')", - gid, Strings::Escape(name).c_str()); - result = QueryDatabase(query); + e.gid = group_id; + e.leadername = name; + e.marknpc = std::string(); + e.leadershipaa = std::string(); + e.maintank = std::string(); + e.assist = std::string(); + e.puller = std::string(); + e.mentoree = std::string(); + e.mentor_percent = 0; - if(!result.Success()) { - LogDebug("Error in Database::SetGroupLeaderName: [{}]", result.ErrorMessage().c_str()); - } + GroupLeadersRepository::UpdateOne(*this, e); } std::string Database::GetGroupLeaderName(uint32 group_id) @@ -1335,545 +1151,498 @@ std::string Database::GetGroupLeaderName(uint32 group_id) return row[0]; } -char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, char *mentoree, int *mentor_percent, GroupLeadershipAA_Struct* GLAA) +char* Database::GetGroupLeadershipInfo( + uint32 group_id, + char* leaderbuf, + char* maintank, + char* assist, + char* puller, + char* marknpc, + char* mentoree, + int* mentor_percent, + GroupLeadershipAA_Struct* GLAA +) { - std::string query = StringFormat("SELECT `leadername`, `maintank`, `assist`, `puller`, `marknpc`, `mentoree`, `mentor_percent`, `leadershipaa` FROM `group_leaders` WHERE `gid` = %lu",(unsigned long)gid); - auto results = QueryDatabase(query); + const auto& e = GroupLeadersRepository::FindOne(*this, group_id); - if (!results.Success() || results.RowCount() == 0) { - if(leaderbuf) + if (!e.gid) { + if (leaderbuf) { strcpy(leaderbuf, "UNKNOWN"); + } - if(maintank) + if (maintank) { maintank[0] = '\0'; + } - if(assist) + if (assist) { assist[0] = '\0'; + } - if(puller) + if (puller) { puller[0] = '\0'; + } - if(marknpc) + if (marknpc) { marknpc[0] = '\0'; + } - if (mentoree) + if (mentoree) { mentoree[0] = '\0'; + } - if (mentor_percent) + if (mentor_percent) { *mentor_percent = 0; + } return leaderbuf; } - auto row = results.begin(); + if (leaderbuf) { + strcpy(leaderbuf, e.leadername.c_str()); + } - if(leaderbuf) - strcpy(leaderbuf, row[0]); + if (maintank) { + strcpy(maintank, e.maintank.c_str()); + } - if(maintank) - strcpy(maintank, row[1]); + if (assist) { + strcpy(assist, e.assist.c_str()); + } - if(assist) - strcpy(assist, row[2]); + if (puller) { + strcpy(puller, e.puller.c_str()); + } - if(puller) - strcpy(puller, row[3]); + if (marknpc) { + strcpy(marknpc, e.marknpc.c_str()); + } - if(marknpc) - strcpy(marknpc, row[4]); + if (mentoree) { + strcpy(mentoree, e.mentoree.c_str()); + } - if (mentoree) - strcpy(mentoree, row[5]); + if (mentor_percent) { + *mentor_percent = e.mentor_percent; + } - if (mentor_percent) - *mentor_percent = Strings::ToInt(row[6]); - - if(GLAA && results.LengthOfColumn(7) == sizeof(GroupLeadershipAA_Struct)) - memcpy(GLAA, row[7], sizeof(GroupLeadershipAA_Struct)); + if (GLAA && e.leadershipaa.length() == sizeof(GroupLeadershipAA_Struct)) { + memcpy(GLAA, e.leadershipaa.c_str(), sizeof(GroupLeadershipAA_Struct)); + } return leaderbuf; } -// 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; +void Database::ClearAllGroupLeaders() +{ + GroupLeadersRepository::ClearAllGroupLeaders(*this); } -void Database::ClearGroupLeader(uint32 gid) { - - if(gid == 0) - { +void Database::ClearGroupLeader(uint32 group_id) +{ + if (!group_id) { ClearAllGroupLeaders(); return; } - std::string query = StringFormat("DELETE from group_leaders where gid = %lu", (unsigned long)gid); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; + GroupLeadersRepository::DeleteOne(*this, group_id); } uint8 Database::GetAgreementFlag(uint32 account_id) { const auto& e = AccountRepository::FindOne(*this, account_id); - if (!e.id) { - return 0; - } - return e.rulesflag; + return !e.id ? 0 : e.rulesflag; } -void Database::SetAgreementFlag(uint32 account_id) { +void Database::SetAgreementFlag(uint32 account_id) +{ auto e = AccountRepository::FindOne(*this, account_id); + e.rulesflag = 1; + AccountRepository::UpdateOne(*this, e); } -void Database::ClearRaid(uint32 rid) { - if(rid == 0) - { - //clear all raids +void Database::ClearRaid(uint32 raid_id) +{ + if (!raid_id) { ClearAllRaids(); return; } - //clear a specific group - std::string query = StringFormat("delete from raid_members where raidid = %lu", (unsigned long)rid); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; + RaidMembersRepository::DeleteWhere( + *this, + fmt::format( + "`raidid` = {}", + raid_id + ) + ); } -void Database::ClearAllRaids(void) { - - std::string query("delete from raid_members"); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; -} - -void Database::ClearAllRaidDetails(void) +void Database::ClearAllRaids() { - - std::string query("delete from raid_details"); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; + RaidMembersRepository::ClearAllRaids(*this); } -void Database::ClearRaidDetails(uint32 rid) { +void Database::ClearAllRaidDetails() +{ + RaidDetailsRepository::ClearAllRaidDetails(*this); +} - if(rid == 0) - { - //clear all raids +void Database::ClearRaidDetails(uint32 raid_id) { + + if (!raid_id) { ClearAllRaidDetails(); return; } - //clear a specific group - std::string query = StringFormat("delete from raid_details where raidid = %lu", (unsigned long)rid); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; + RaidDetailsRepository::DeleteWhere( + *this, + fmt::format( + "`raidid` = {}", + raid_id + ) + ); } -void Database::PurgeAllDeletedDataBuckets() { - std::string query = StringFormat( - "DELETE FROM `data_buckets` WHERE (`expires` < %lld AND `expires` > 0)", - (long long) std::time(nullptr) +void Database::PurgeAllDeletedDataBuckets() +{ + DataBucketsRepository::DeleteWhere( + *this, + fmt::format( + "(`expires` < {} AND `expires` > 0)", + std::time(nullptr) + ) + ); +} + +uint32 Database::GetRaidID(const std::string& name) +{ + const auto& l = RaidMembersRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) ); - QueryDatabase(query); -} - -// returns 0 on error or no raid for that character, or -// the raid id that the character is a member of. -uint32 Database::GetRaidID(const char* name) -{ - std::string query = StringFormat("SELECT `raidid` FROM `raid_members` WHERE `name` = '%s'", name); - auto results = QueryDatabase(query); - - if (!results.Success()) { + if (l.empty()) { return 0; } - auto row = results.begin(); - if (row == results.end()) { - return 0; - } + auto e = l.front(); - if (row[0]) // would it ever be possible to have a null here? - return Strings::ToUnsignedInt(row[0]); - - return 0; + return e.raidid; } -const char* Database::GetRaidLeaderName(uint32 raid_id) +const std::string& Database::GetRaidLeaderName(uint32 raid_id) { - // Would be a good idea to fix this to be a passed in variable and - // make the caller responsible. static local variables like this are - // not guaranteed to be thread safe (nor is the internal guard - // variable). C++0x standard states this should be thread safe - // but may not be fully supported in some compilers. - static char name[128]; + const auto& l = RaidMembersRepository::GetWhere( + *this, + fmt::format( + "`raidid` = {} AND `israidleader` = 1", + raid_id + ) + ); - std::string query = StringFormat("SELECT `name` FROM `raid_members` WHERE `raidid` = %u AND `israidleader` = 1", raid_id); - auto results = QueryDatabase(query); - - if (!results.Success()) { - LogDebug("Unable to get Raid Leader Name for Raid ID: [{}]", raid_id); + if (l.empty()) { + LogDebug("Unable to get Raid Leader Name for Raid ID [{}]", raid_id); return "UNKNOWN"; } - auto row = results.begin(); + auto e = l.front(); - if (row == results.end()) { - return "UNKNOWN"; - } - - memset(name, 0, sizeof(name)); - strcpy(name, row[0]); - - return name; + return e.name; } -// maintank, assist, puller, marknpc currently unused -void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank, - char *assist, char *puller, char *marknpc, char *mentoree, int *mentor_percent, GroupLeadershipAA_Struct *GLAA) +void Database::GetGroupLeadershipInfo( + uint32 group_id, + uint32 raid_id, + char* maintank, + char* assist, + char* puller, + char* marknpc, + char* mentoree, + int* mentor_percent, + GroupLeadershipAA_Struct* GLAA +) { - std::string query = StringFormat( - "SELECT maintank, assist, puller, marknpc, mentoree, mentor_percent, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu", - (unsigned long)gid, (unsigned long)rid); + const std::string& query = fmt::format( + SQL( + SELECT `maintank`, `assist`, `puller`, `marknpc`, `mentoree`, `mentor_percent`, `leadershipaa` + FROM `raid_leaders` + WHERE `gid` = {} AND `rid` = {} + ), + group_id, + raid_id + ); + auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) { - if (maintank) + if (!results.Success() || !results.RowCount()) { + if (maintank) { maintank[0] = '\0'; + } - if (assist) + if (assist) { assist[0] = '\0'; + } - if (puller) + if (puller) { puller[0] = '\0'; + } - if (marknpc) + if (marknpc) { marknpc[0] = '\0'; + } - if (mentoree) + if (mentoree) { mentoree[0] = '\0'; + } - if (mentor_percent) + if (mentor_percent) { *mentor_percent = 0; + } return; } auto row = results.begin(); - if (maintank) + if (maintank) { strcpy(maintank, row[0]); + } - if (assist) + if (assist) { strcpy(assist, row[1]); + } - if (puller) + if (puller) { strcpy(puller, row[2]); + } - if (marknpc) + if (marknpc) { strcpy(marknpc, row[3]); + } - if (mentoree) + if (mentoree) { strcpy(mentoree, row[4]); + } - if (mentor_percent) + if (mentor_percent) { *mentor_percent = Strings::ToInt(row[5]); + } - if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct)) + if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct)) { memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct)); - - return; + } } -// maintank, assist, puller, marknpc currently unused -void Database::GetRaidLeadershipInfo(uint32 rid, char *maintank, - char *assist, char *puller, char *marknpc, RaidLeadershipAA_Struct *RLAA) +void Database::GetRaidLeadershipInfo( + uint32 raid_id, + char* maintank, + char* assist, + char* puller, + char* marknpc, + RaidLeadershipAA_Struct* RLAA +) { - std::string query = StringFormat( - "SELECT maintank, assist, puller, marknpc, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu", - (unsigned long)0xFFFFFFFF, (unsigned long)rid); + std::string query = fmt::format( + SQL( + SELECT `maintank`, `assist`, `puller`, `marknpc`, `leadershipaa` + FROM `raid_leaders` + WHERE `gid` = {} AND `rid` = {} + ), + std::numeric_limits::max(), + raid_id + ); + auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) { - if (maintank) + if (!results.Success() || !results.RowCount()) { + if (maintank) { maintank[0] = '\0'; + } - if (assist) + if (assist) { assist[0] = '\0'; + } - if (puller) + if (puller) { puller[0] = '\0'; + } - if (marknpc) + if (marknpc) { marknpc[0] = '\0'; + } return; } auto row = results.begin(); - if (maintank) + if (maintank) { strcpy(maintank, row[0]); + } - if (assist) + if (assist) { strcpy(assist, row[1]); + } - if (puller) + if (puller) { strcpy(puller, row[2]); + } - if (marknpc) + if (marknpc) { strcpy(marknpc, row[3]); + } - if (RLAA && results.LengthOfColumn(4) == sizeof(RaidLeadershipAA_Struct)) + if (RLAA && results.LengthOfColumn(4) == sizeof(RaidLeadershipAA_Struct)) { memcpy(RLAA, row[4], sizeof(RaidLeadershipAA_Struct)); - - return; -} - -void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid) -{ - std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '' WHERE gid = %lu AND rid = %lu", - (unsigned long)gid, (unsigned long)rid); - auto results = QueryDatabase(query); - - if (results.RowsAffected() != 0) - return; - - query = StringFormat("REPLACE INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%lu, %lu, '', '', '', '', '', '', 0)", - (unsigned long)gid, (unsigned long)rid); - results = QueryDatabase(query); - - return; -} - -// Clearing all raid leaders -void Database::ClearAllRaidLeaders(void) -{ - std::string query("DELETE from raid_leaders"); - QueryDatabase(query); - return; -} - -void Database::ClearRaidLeader(uint32 gid, uint32 rid) -{ - if (rid == 0) { - ClearAllRaidLeaders(); - return; } - - std::string query = StringFormat("DELETE from raid_leaders where gid = %lu and rid = %lu", (unsigned long)gid, (unsigned long)rid); - QueryDatabase(query); } -void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win, bool remove) +void Database::SetRaidGroupLeaderInfo(uint32 group_id, uint32 raid_id) { - std::string field; - switch(theme) { - case LDoNThemes::GUK: { - field = "guk_"; - break; - } - case LDoNThemes::MIR: { - field = "mir_"; - break; - } - case LDoNThemes::MMC: { - field = "mmc_"; - break; - } - case LDoNThemes::RUJ: { - field = "ruj_"; - break; - } - case LDoNThemes::TAK: { - field = "tak_"; - break; - } - default: { - return; - } - } - - field += win ? "wins" : "losses"; - std::string field_operation = remove ? "-" : "+"; - std::string query = fmt::format( - "UPDATE `adventure_stats` SET {} = {} {} 1 WHERE player_id = {}", - field, - field, - field_operation, - char_id + "UPDATE `raid_leaders` SET `leadershipaa` = '' WHERE `gid` = {} AND `rid` = {}", + group_id, + raid_id ); + auto results = QueryDatabase(query); if (results.RowsAffected() != 0) { return; } - if (!remove) { - query = fmt::format( - "INSERT INTO `adventure_stats` SET {} = 1, player_id = {}", - field, - char_id - ); - QueryDatabase(query); - } + query = fmt::format( + SQL( + REPLACE INTO `raid_leaders` (`gid`, `rid`, `marknpc`, `leadershipaa`, `maintank`, `assist`, `puller`, `mentoree`, `mentor_percent`) VALUES + ({}, {}, '', '', '', '', '', '', 0) + ), + group_id, + raid_id + ); + + QueryDatabase(query); } -bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as) +void Database::ClearAllRaidLeaders() { - std::string query = fmt::format( - "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 = {}", - char_id + QueryDatabase("DELETE FROM `raid_leaders`"); +} + +void Database::ClearRaidLeader(uint32 group_id, uint32 raid_id) +{ + if (!raid_id) { + ClearAllRaidLeaders(); + return; + } + + const std::string& query = fmt::format( + "DELETE FROM `raid_leaders` WHERE `gid` = {} AND `rid` = {}", + group_id, + raid_id ); - auto results = QueryDatabase(query); - if (!results.Success()) + QueryDatabase(query); +} + +void Database::UpdateAdventureStatsEntry(uint32 character_id, uint8 theme_id, bool is_win, bool is_remove) +{ + AdventureStatsRepository::UpdateAdventureStatsEntry(*this, character_id, theme_id, is_win, is_remove); +} + +bool Database::GetAdventureStats(uint32 character_id, AdventureStats_Struct* as) +{ + const auto& e = AdventureStatsRepository::FindOne(*this, character_id); + + if (!e.player_id) { return false; + } - if (results.RowCount() == 0) - return false; + as->success.guk = e.guk_wins; + as->failure.guk = e.guk_losses; + as->success.mir = e.mir_wins; + as->failure.mir = e.mir_losses; + as->success.mmc = e.mmc_wins; + as->failure.mmc = e.mmc_losses; + as->success.ruj = e.ruj_wins; + as->failure.ruj = e.ruj_losses; + as->success.tak = e.tak_wins; + as->failure.tak = e.tak_losses; - auto row = results.begin(); + as->failure.total = ( + as->failure.guk + + as->failure.mir + + as->failure.mmc + + as->failure.ruj + + as->failure.tak + ); - as->success.guk = Strings::ToUnsignedInt(row[0]); - as->success.mir = Strings::ToUnsignedInt(row[1]); - as->success.mmc = Strings::ToUnsignedInt(row[2]); - as->success.ruj = Strings::ToUnsignedInt(row[3]); - as->success.tak = Strings::ToUnsignedInt(row[4]); - as->failure.guk = Strings::ToUnsignedInt(row[5]); - as->failure.mir = Strings::ToUnsignedInt(row[6]); - as->failure.mmc = Strings::ToUnsignedInt(row[7]); - as->failure.ruj = Strings::ToUnsignedInt(row[8]); - as->failure.tak = Strings::ToUnsignedInt(row[9]); - as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak; - as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak; + as->success.total = ( + as->success.guk + + as->success.mir + + as->success.mmc + + as->success.ruj + + as->success.tak + ); return true; } uint32 Database::GetGuildIDByCharID(uint32 character_id) { - std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id='%i'", character_id); - auto results = QueryDatabase(query); + const auto& e = GuildMembersRepository::FindOne(*this, character_id); - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + return e.char_id ? e.guild_id : 0; } uint32 Database::GetGroupIDByCharID(uint32 character_id) { - std::string query = fmt::format( - SQL( - SELECT groupid - FROM group_id - WHERE charid = '{}' - ), - character_id - ); - auto results = QueryDatabase(query); + const auto& e = GroupIdRepository::FindOne(*this, character_id); - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + return e.character_id ? e.group_id : 0; } -uint32 Database::GetRaidIDByCharID(uint32 character_id) { - std::string query = fmt::format( - SQL( - SELECT raidid - FROM raid_members - WHERE charid = '{}' - ), - character_id - ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - return 0; +uint32 Database::GetRaidIDByCharID(uint32 character_id) +{ + const auto& e = RaidMembersRepository::FindOne(*this, character_id); + + return e.charid ? e.raidid : 0; +} + +int64 Database::CountInvSnapshots() +{ + return InventorySnapshotsRepository::CountInventorySnapshots(*this); +} + +void Database::ClearInvSnapshots(bool from_now) +{ + uint32 delete_time = time(nullptr); + + if (!from_now) { + delete_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; } - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + InventorySnapshotsRepository::DeleteWhere( + *this, + fmt::format( + "`time_index` <= {}", + delete_time + ) + ); } -int Database::CountInvSnapshots() { - std::string query = StringFormat("SELECT COUNT(*) FROM (SELECT * FROM `inventory_snapshots` a GROUP BY `charid`, `time_index`) b"); - auto results = QueryDatabase(query); - - if (!results.Success()) - return -1; - - auto row = results.begin(); - - int64 count = Strings::ToBigInt(row[0]); - if (count > 2147483647) - return -2; - if (count < 0) - return -3; - - return count; -} - -void Database::ClearInvSnapshots(bool from_now) { - uint32 del_time = time(nullptr); - if (!from_now) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; } - - std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time); - QueryDatabase(query); -} - -struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) +struct TimeOfDay_Struct Database::LoadTime(time_t& realtime) { - TimeOfDay_Struct t{}; - std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); + TimeOfDay_Struct t{ }; + + const std::string& query = "SELECT `minute`, `hour`, `day`, `month`, `year`, `realtime` FROM `eqtime` LIMIT 1"; auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) { + if (!results.Success() || !results.RowCount()) { LogInfo("Loading EQ time of day failed. Using defaults"); t.minute = 0; t.hour = 9; @@ -1907,137 +1676,149 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year) { - std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(nullptr)); + const std::string& query = fmt::format( + "UPDATE `eqtime` SET `minute` = {}, `hour` = {}, `day` = {}, `month` = {}, `year` = {}, `realtime` = {} LIMIT 1", + minute, + hour, + day, + month, + year, + std::time(nullptr) + ); + auto results = QueryDatabase(query); return results.Success(); - } -int Database::GetIPExemption(std::string account_ip) { - auto query = fmt::format( - "SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", - account_ip +int Database::GetIPExemption(const std::string& account_ip) +{ + const auto& l = IpExemptionsRepository::GetWhere( + *this, + fmt::format( + "`exemption_ip` = '{}'", + Strings::Escape(account_ip) + ) ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { + if (l.empty()) { return RuleI(World, MaxClientsPerIP); } - auto row = results.begin(); - return Strings::ToInt(row[0]); + auto e = l.front(); + + return e.exemption_amount; } -void Database::SetIPExemption(std::string account_ip, int exemption_amount) { - auto query = fmt::format( - "SELECT `exemption_id` FROM `ip_exemptions` WHERE `exemption_ip` = '{}'", - account_ip +void Database::SetIPExemption(const std::string& account_ip, int exemption_amount) +{ + const auto& l = IpExemptionsRepository::GetWhere( + *this, + fmt::format( + "`exemption_ip` = '{}'", + Strings::Escape(account_ip) + ) ); - uint32 exemption_id = 0; + if (l.empty()) { + auto e = IpExemptionsRepository::NewEntity(); - auto results = QueryDatabase(query); - if (results.Success() && results.RowCount()) { - auto row = results.begin(); - exemption_id = Strings::ToUnsignedInt(row[0]); + e.exemption_ip = account_ip; + e.exemption_amount = exemption_amount; + + IpExemptionsRepository::InsertOne(*this, e); + + return; } - query = fmt::format( - "INSERT INTO `ip_exemptions` (`exemption_ip`, `exemption_amount`) VALUES ('{}', {})", - account_ip, - exemption_amount + auto e = l.front(); + + e.exemption_amount = exemption_amount; + + IpExemptionsRepository::UpdateOne(*this, e); +} + +int Database::GetInstanceID(uint32 character_id, uint32 zone_id) +{ + const auto& l = InstanceListRepository::GetWhere( + *this, + fmt::format( + "`zone` = {} AND `id` IN (SELECT `id` FROM `instance_list_player` WHERE `charid` = {})", + zone_id, + character_id + ) ); - if (exemption_id) { - query = fmt::format( - "UPDATE `ip_exemptions` SET `exemption_amount` = {} WHERE `exemption_ip` = '{}'", - exemption_amount, - account_ip - ); + if (l.empty()) { + return 0; } - QueryDatabase(query); + auto e = l.front(); + + return e.id; } -int Database::GetInstanceID(uint32 char_id, uint32 zone_id) { - std::string query = StringFormat("SELECT instance_list.id FROM instance_list INNER JOIN instance_list_player ON instance_list.id = instance_list_player.id WHERE instance_list.zone = '%i' AND instance_list_player.charid = '%i'", zone_id, char_id); - auto results = QueryDatabase(query); - - if (results.Success() && results.RowCount() > 0) { - auto row = results.begin(); - return Strings::ToInt(row[0]);; - } - - return 0; -} - -/** - * @param source_character_name - * @param destination_character_name - * @param destination_account_name - * @return - */ bool Database::CopyCharacter( const std::string& source_character_name, const std::string& destination_character_name, const std::string& destination_account_name ) { - auto results = QueryDatabase( + const auto& characters = CharacterDataRepository::GetWhere( + *this, fmt::format( - "SELECT id FROM character_data WHERE name = '{}' and deleted_at is NULL LIMIT 1", - source_character_name + "`name` = '{}' AND `deleted_at` IS NULL LIMIT 1", + Strings::Escape(source_character_name) ) ); - if (results.RowCount() == 0) { + if (characters.empty()) { LogError("No character found with name [{}]", source_character_name); return false; } - auto row = results.begin(); - std::string source_character_id = row[0]; + auto character = characters.front(); - results = QueryDatabase( + const uint32 source_character_id = character.id; + + const auto& accounts = AccountRepository::GetWhere( + *this, fmt::format( - "SELECT id FROM account WHERE name = '{}' LIMIT 1", - destination_account_name + "`name` = '{}' LIMIT 1", + Strings::Escape(destination_account_name) ) ); - if (results.RowCount() == 0) { + if (accounts.empty()) { LogError("No account found with name [{}]", destination_account_name); return false; } - row = results.begin(); - std::string source_account_id = row[0]; + auto account = accounts.front(); - /** - * Fresh ID - */ - results = QueryDatabase("SELECT (MAX(id) + 1) as new_id from character_data"); - row = results.begin(); - std::string new_character_id = row[0]; + const int destination_account_id = account.id; - std::vector tables_to_zero_id = { - "keyring", - "data_buckets", - }; + const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1); + + std::vector tables_to_zero_id = { "keyring", "data_buckets" }; TransactionBegin(); - for (const auto &iter : DatabaseSchema::GetCharacterTables()) { - std::string table_name = iter.first; - std::string character_id_column_name = iter.second; - /** - * Columns - */ - results = QueryDatabase(fmt::format("SHOW COLUMNS FROM {}", table_name)); + for (const auto &t : DatabaseSchema::GetCharacterTables()) { + const std::string& table_name = t.first; + const std::string& character_id_column_name = t.second; + + auto results = QueryDatabase( + fmt::format( + "SHOW COLUMNS FROM {}", + table_name + ) + ); + std::vector columns = {}; int column_count = 0; - for (row = results.begin(); row != results.end(); ++row) { + + for (auto row : results) { columns.emplace_back(row[0]); column_count++; } @@ -2053,18 +1834,20 @@ bool Database::CopyCharacter( ); std::vector> new_rows; - for (row = results.begin(); row != results.end(); ++row) { + + for (auto row : results) { std::vector new_values = {}; - for (int column_index = 0; column_index < column_count; column_index++) { - std::string column = columns[column_index]; - std::string value = row[column_index] ? row[column_index] : "null"; + + for (int column_index = 0; column_index < column_count; column_index++) { + const std::string& column = columns[column_index]; + std::string value = row[column_index] ? row[column_index] : "null"; if (column == "id" && Strings::Contains(tables_to_zero_id, table_name)) { value = "0"; } if (column == character_id_column_name) { - value = new_character_id; + value = std::to_string(new_character_id); } if (column == "name" && table_name == "character_data") { @@ -2072,7 +1855,7 @@ bool Database::CopyCharacter( } if (column == "account_id" && table_name == "character_data") { - value = source_account_id; + value = std::to_string(destination_account_id); } new_values.emplace_back(value); @@ -2083,8 +1866,8 @@ bool Database::CopyCharacter( std::vector insert_rows; - for (auto &r: new_rows) { - std::string insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")"; + for (auto &r : new_rows) { + const std::string& insert_row = "(" + Strings::Implode(",", Strings::Wrap(r, "'")) + ")"; insert_rows.emplace_back(insert_row); } @@ -2119,7 +1902,7 @@ bool Database::CopyCharacter( return true; } -void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string url) +void Database::SourceDatabaseTableFromUrl(const std::string& table_name, const std::string& url) { try { uri request_uri(url); @@ -2154,19 +1937,19 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur if (auto res = cli.Get(request_uri.get_path())) { if (res->status == 200) { - for (auto &s: Strings::Split(res->body, ';')) { + for (auto& s : Strings::Split(res->body, ';')) { if (!Strings::Trim(s).empty()) { auto results = QueryDatabase(s); if (!results.ErrorMessage().empty()) { LogError("Error sourcing SQL [{}]", results.ErrorMessage()); return; } + sourced_queries++; } } } - } - else { + } else { LogError("Error retrieving URL [{}]", url); } @@ -2176,28 +1959,12 @@ void Database::SourceDatabaseTableFromUrl(std::string table_name, std::string ur sourced_queries ); } - - } - catch (std::invalid_argument iae) { + } catch (std::invalid_argument iae) { LogError("URI parser error [{}]", iae.what()); } } -uint8 Database::GetMinStatus(uint32 zone_id, uint32 instance_version) -{ - auto zones = ZoneRepository::GetWhere( - *this, - fmt::format( - "zoneidnumber = {} AND (version = {} OR version = 0) ORDER BY version DESC LIMIT 1", - zone_id, - instance_version - ) - ); - - return !zones.empty() ? zones[0].min_status : 0; -} - -void Database::SourceSqlFromUrl(std::string url) +void Database::SourceSqlFromUrl(const std::string& url) { try { uri request_uri(url); @@ -2235,16 +2002,14 @@ void Database::SourceSqlFromUrl(std::string url) return; } } + if (res->status == 404) { LogError("Error retrieving URL [{}]", url); } - } - else { + } else { LogError("Error retrieving URL [{}]", url); } - - } - catch (std::invalid_argument iae) { + } catch (std::invalid_argument iae) { LogError("URI parser error [{}]", iae.what()); } } diff --git a/common/database.h b/common/database.h index 857ef07bb..fd3f89b3b 100644 --- a/common/database.h +++ b/common/database.h @@ -18,8 +18,8 @@ #ifndef EQEMU_DATABASE_H #define EQEMU_DATABASE_H -#define AUTHENTICATION_TIMEOUT 60 -#define INVALID_ID 0xFFFFFFFF +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF #include "global_define.h" #include "eqemu_logsys.h" @@ -38,8 +38,7 @@ class MySQLRequestResult; class Client; -namespace EQ -{ +namespace EQ { class InventoryProfile; } @@ -52,10 +51,11 @@ struct npcDecayTimes_Struct { struct VarCache_Struct { std::map m_cache; - uint32 last_update; + uint32 last_update; VarCache_Struct() : last_update(0) { } - void Add(const std::string &key, const std::string &value) { m_cache[key] = value; } - const std::string *Get(const std::string &key) { + void Add(const std::string& key, const std::string& value) { m_cache[key] = value; } + const std::string* Get(const std::string& key) + { auto it = m_cache.find(key); return (it != m_cache.end() ? &it->second : nullptr); } @@ -76,37 +76,33 @@ class PTimerList; #define SQL(...) #__VA_ARGS__ -class LogSettings; class Database : public DBcore { public: Database(); - Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port, std::string connection_label = "default"); + Database( + const std::string& host, + const std::string& user, + const std::string& password, + const std::string& database, + uint32 port + ); + bool Connect( + const std::string& host, + const std::string& user, + const std::string& password, + const std::string& database, + uint32 port, + std::string connection_label = "default" + ); ~Database(); /* Character Creation */ - - bool CreateCharacter( - uint32 account_id, - char *name, - uint16 gender, - uint16 race, - uint16 class_, - uint8 str, - uint8 sta, - uint8 cha, - uint8 dex, - uint8 int_, - uint8 agi, - uint8 wis, - uint8 face - ); - bool DeleteCharacter(char *character_name); - bool MoveCharacterToZone(const char *charname, uint32 zone_id); + bool DeleteCharacter(const std::string& name); + bool MoveCharacterToZone(const std::string& name, uint32 zone_id); bool MoveCharacterToZone(uint32 character_id, uint32 zone_id); - bool ReserveName(uint32 account_id, char *name); - bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp); - bool UpdateName(const char *oldname, const char *newname); + bool ReserveName(uint32 account_id, const std::string& name); + bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool UpdateName(const std::string& old_name, const std::string& new_name); bool CopyCharacter( const std::string& source_character_name, const std::string& destination_character_name, @@ -114,161 +110,171 @@ public: ); /* General Information Queries */ + bool AddBannedIP(const std::string& banned_ip, const std::string& notes); //Add IP address to the banned_ips table. + bool AddToNameFilter(const std::string& name); + bool CheckBannedIPs(const std::string& login_ip); //Check incoming connection against banned IP table. + bool CheckGMIPs(const std::string& login_ip, uint32 account_id); + bool CheckNameFilter(const std::string& name, bool surname = false); + bool CheckUsedName(const std::string& name); - bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table. - bool AddToNameFilter(std::string name); - bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table. - bool CheckGMIPs(std::string login_ip, uint32 account_id); - bool CheckNameFilter(std::string name, bool surname = false); - bool CheckUsedName(std::string name); + uint32 GetAccountIDByChar(const std::string& name, uint32* character_id = 0); + uint32 GetAccountIDByChar(uint32 character_id); + uint32 GetAccountIDByName(const std::string& account_name, const std::string& loginserver, int16* status = 0, uint32* lsid = 0); + uint32 GetCharacterID(const std::string& name); + uint32 GetGuildIDByCharID(uint32 character_id); + uint32 GetGroupIDByCharID(uint32 character_id); + uint32 GetRaidIDByCharID(uint32 character_id); - uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); - uint32 GetAccountIDByChar(uint32 char_id); - uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0); - uint32 GetCharacterID(const std::string& name); - uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id); - uint32 GetGuildIDByCharID(uint32 char_id); - uint32 GetGroupIDByCharID(uint32 char_id); - uint32 GetRaidIDByCharID(uint32 char_id); - - void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); - void GetCharName(uint32 char_id, char* name); - std::string GetCharNameByID(uint32 char_id); - std::string GetNPCNameByID(uint32 npc_id); - std::string GetCleanNPCNameByID(uint32 npc_id); - void LoginIP(uint32 account_id, std::string login_ip); + const std::string& GetAccountName(uint32 account_id, uint32* lsaccount_id = 0); + const std::string& GetCharName(uint32 character_id); + const std::string& GetCharNameByID(uint32 character_id); + const std::string& GetNPCNameByID(uint32 npc_id); + const std::string& GetCleanNPCNameByID(uint32 npc_id); + void LoginIP(uint32 account_id, const std::string& login_ip); /* Instancing */ - bool AddClientToInstance(uint16 instance_id, uint32 character_id); bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id); bool CheckInstanceExists(uint16 instance_id); bool CheckInstanceExpired(uint16 instance_id); bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); - bool GetUnusedInstanceID(uint16 &instance_id); + bool GetUnusedInstanceID(uint16& instance_id); bool IsGlobalInstance(uint16 instance_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientsFromInstance(uint16 instance_id); bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id); bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); - uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); + uint16 GetInstanceID(uint32 zone, uint32 character_id, int16 version); std::vector GetInstanceIDs(uint32 zone_id, uint32 character_id); uint8_t GetInstanceVersion(uint16 instance_id); - uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); + uint32 GetTimeRemainingInstance(uint16 instance_id, bool& is_perma); uint32 GetInstanceZoneID(uint16 instance_id); - void AssignGroupToInstance(uint32 gid, uint32 instance_id); - void AssignRaidToInstance(uint32 rid, uint32 instance_id); + void AssignGroupToInstance(uint32 group_id, uint32 instance_id); + void AssignRaidToInstance(uint32 raid_id, uint32 instance_id); void DeleteInstance(uint16 instance_id); - void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id); - void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id); - void GetCharactersInInstance(uint16 instance_id, std::list &character_ids); + void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id); + void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id); + void GetCharactersInInstance(uint16 instance_id, std::list& character_ids); void PurgeExpiredInstances(); void SetInstanceDuration(uint16 instance_id, uint32 new_duration); void CleanupInstanceCorpses(); /* Adventure related. */ - - void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false); - bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as); + void UpdateAdventureStatsEntry(uint32 character_id, uint8 theme_id, bool is_win = false, bool is_remove = false); + bool GetAdventureStats(uint32 character_id, AdventureStats_Struct* as); /* Account Related */ + const std::string& GetLiveChar(uint32 account_id); + bool SetAccountStatus(const std::string& account_name, int16 status); + bool SetLocalPassword(uint32 account_id, const std::string& password); + bool UpdateLiveChar(const std::string& name, uint32 account_id); + int16 CheckStatus(uint32 account_id); + void SetAccountCRCField(uint32 account_id, const std::string& field_name, uint64 checksum); + uint32 CheckLogin(const std::string& name, const std::string& password, const std::string& loginserver, int16* status = 0); + uint32 CreateAccount( + const std::string& name, + const std::string& password, + int16 status, + const std::string& loginserver, + uint32 lsaccount_id + ); + uint32 GetAccountIDFromLSID( + const std::string& in_loginserver_id, + uint32 in_loginserver_account_id, + char* in_account_name = 0, + int16* in_status = 0 + ); - bool DeleteAccount(const char *name, const char* loginserver); - bool GetLiveChar(uint32 account_id, char* cname); - bool SetAccountStatus(const char* name, int16 status); - bool SetAccountStatus(const std::string& account_name, int16 status); - bool SetLocalPassword(uint32 accid, const char* password); - bool UpdateLiveChar(char* charname, uint32 account_id); + uint8 GetAgreementFlag(uint32 account_id); + void SetAgreementFlag(uint32 account_id); - int16 CheckStatus(uint32 account_id); + int GetIPExemption(const std::string& account_ip); + void SetIPExemption(const std::string& account_ip, int exemption_amount); - void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum); - - uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0); - uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id); - uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0); - uint8 GetAgreementFlag(uint32 account_id); - - void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); - void SetAgreementFlag(uint32 account_id); - - int GetIPExemption(std::string account_ip); - void SetIPExemption(std::string account_ip, int exemption_amount); - - int GetInstanceID(uint32 char_id, uint32 zone_id); + int GetInstanceID(uint32 character_id, uint32 zone_id); /* Groups */ - std::string GetGroupLeaderForLogin(const std::string& character_name); - char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); - + char* GetGroupLeadershipInfo( + uint32 group_id, + char* leaderbuf, + char* maintank = nullptr, + char* assist = nullptr, + char* puller = nullptr, + char* marknpc = nullptr, + char* mentoree = nullptr, + int* mentor_percent = nullptr, + GroupLeadershipAA_Struct* GLAA = nullptr + ); std::string GetGroupLeaderName(uint32 group_id); - - uint32 GetGroupID(const std::string& name); - - void ClearGroup(uint32 group_id = 0); - void ClearGroupLeader(uint32 gid = 0); - void SetGroupLeaderName(uint32 gid, const char* name); + uint32 GetGroupID(const std::string& name); + void ClearGroup(uint32 group_id = 0); + void ClearGroupLeader(uint32 group_id = 0); + void SetGroupLeaderName(uint32 group_id, const std::string& name); /* Raids */ + const std::string& GetRaidLeaderName(uint32 raid_id); + uint32 GetRaidID(const std::string& name); + void ClearRaid(uint32 raid_id = 0); + void ClearRaidDetails(uint32 raid_id = 0); + void ClearRaidLeader(uint32 group_id = std::numeric_limits::max(), uint32 raid_id = 0); + void GetGroupLeadershipInfo( + uint32 group_id, + uint32 raid_id, + char* maintank = nullptr, + char* assist = nullptr, + char* puller = nullptr, + char* marknpc = nullptr, + char* mentoree = nullptr, + int* mentor_percent = nullptr, + GroupLeadershipAA_Struct* GLAA = nullptr + ); + void GetRaidLeadershipInfo( + uint32 raid_id, + char* maintank = nullptr, + char* assist = nullptr, + char* puller = nullptr, + char* marknpc = nullptr, + RaidLeadershipAA_Struct* RLAA = nullptr + ); + void SetRaidGroupLeaderInfo(uint32 group_id, uint32 raid_id); - const char *GetRaidLeaderName(uint32 rid); - - uint32 GetRaidID(const char* name); - - void ClearRaid(uint32 rid = 0); - void ClearRaidDetails(uint32 rid = 0); - void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0); - void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); - void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr); - void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid); - - void PurgeAllDeletedDataBuckets(); + void PurgeAllDeletedDataBuckets(); /* Database Variables */ + bool GetVariable(const std::string& name, std::string& value); + bool SetVariable(const std::string& name, const std::string& value); + bool LoadVariables(); - bool GetVariable(std::string varname, std::string &varvalue); - bool SetVariable(const std::string& varname, const std::string &varvalue); - bool LoadVariables(); + uint8 GetPEQZone(uint32 zone_id, uint32 version); + uint32 GetServerType(); + void AddReport(const std::string& who, const std::string& against, const std::string& lines); + struct TimeOfDay_Struct LoadTime(time_t& realtime); + bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year); + void ClearMerchantTemp(); + void ClearPTimers(uint32 character_id); + void SetFirstLogon(uint32 character_id, uint8 first_logon); + void SetLFG(uint32 character_id, bool is_lfg); + void SetLFP(uint32 character_id, bool is_lfp); + void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon); - /* General Queries */ + int64 CountInvSnapshots(); + void ClearInvSnapshots(bool from_now = false); - bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); - bool LoadPTimers(uint32 charid, PTimerList &into); - - uint8 GetPEQZone(uint32 zone_id, uint32 version); - uint8 GetMinStatus(uint32 zone_id, uint32 instance_version); - uint8 GetRaceSkill(uint8 skillid, uint8 in_race); - uint8 GetServerType(); - - void AddReport(std::string who, std::string against, std::string lines); - struct TimeOfDay_Struct LoadTime(time_t &realtime); - bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year); - void ClearMerchantTemp(); - void ClearPTimers(uint32 charid); - void SetFirstLogon(uint32 CharID, uint8 firstlogon); - void SetLFG(uint32 CharID, bool LFG); - void SetLFP(uint32 CharID, bool LFP); - void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); - - int CountInvSnapshots(); - void ClearInvSnapshots(bool from_now = false); - - void SourceDatabaseTableFromUrl(std::string table_name, std::string url); - void SourceSqlFromUrl(std::string url); + void SourceDatabaseTableFromUrl(const std::string& table_name, const std::string& url); + void SourceSqlFromUrl(const std::string& url); private: - - Mutex Mvarcache; + Mutex Mvarcache; VarCache_Struct varcache; /* Groups, utility methods. */ - void ClearAllGroupLeaders(); - void ClearAllGroups(); + void ClearAllGroupLeaders(); + void ClearAllGroups(); /* Raid, utility methods. */ void ClearAllRaids(); diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 85b26a917..e9068a534 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -509,7 +509,7 @@ void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 ch return; } - auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id)); + auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id).c_str()); auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version); if (!raid_leader_instance_id) { diff --git a/common/repositories/account_repository.h b/common/repositories/account_repository.h index 83d221911..3689e7f2b 100644 --- a/common/repositories/account_repository.h +++ b/common/repositories/account_repository.h @@ -44,7 +44,51 @@ public: */ // Custom extended repository methods here + static int16 GetAccountStatus(Database& db, const uint32 account_id) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `{}` WHERE `{}` = {}", + TableName(), + PrimaryKey(), + account_id + ) + ); + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto row = results.begin(); + + int16 status = static_cast(Strings::ToInt(row[0])); + int date_diff = 0; + + if (row[1]) { + date_diff = Strings::ToInt(row[1]); + } + + if (date_diff > 0) { + status = -1; + } + + return status; + } + + static bool UpdatePassword(Database& db, const uint32 account_id, const std::string& password) + { + auto results = db.QueryDatabase( + fmt::format( + "UPDATE `{}` SET `password` = MD5('{}') WHERE `{}` = {}", + TableName(), + password, + PrimaryKey(), + account_id + ) + ); + + return results.Success(); + } }; #endif //EQEMU_ACCOUNT_REPOSITORY_H diff --git a/common/repositories/adventure_stats_repository.h b/common/repositories/adventure_stats_repository.h index 6fe223e88..a4025ed2b 100644 --- a/common/repositories/adventure_stats_repository.h +++ b/common/repositories/adventure_stats_repository.h @@ -44,7 +44,65 @@ public: */ // Custom extended repository methods here + static void UpdateAdventureStatsEntry(Database& db, uint32 character_id, uint8 theme_id, bool is_win, bool is_remove) + { + std::string field; + switch (theme_id) { + case LDoNThemes::GUK: { + field = "guk_"; + break; + } + case LDoNThemes::MIR: { + field = "mir_"; + break; + } + case LDoNThemes::MMC: { + field = "mmc_"; + break; + } + case LDoNThemes::RUJ: { + field = "ruj_"; + break; + } + case LDoNThemes::TAK: { + field = "tak_"; + break; + } + } + + field += is_win ? "wins" : "losses"; + + auto e = FindOne(db, character_id); + + if (!e.player_id && !is_remove) { + const std::string& query = fmt::format( + "INSERT INTO `{}` SET `{}` = 1, `{}` = {}", + TableName(), + field, + PrimaryKey(), + character_id + ); + + db.QueryDatabase(query); + + return; + } + + const std::string& field_operation = is_remove ? "-" : "+"; + + const std::string& query = fmt::format( + "UPDATE `{}` SET `{}` = {} {} 1 WHERE `{}` = {}", + TableName(), + field, + field, + field_operation, + PrimaryKey(), + character_id + ); + + db.QueryDatabase(query); + } }; #endif //EQEMU_ADVENTURE_STATS_REPOSITORY_H diff --git a/common/repositories/base/base_account_ip_repository.h b/common/repositories/base/base_account_ip_repository.h index 44ec6a84c..c61a696f0 100644 --- a/common/repositories/base/base_account_ip_repository.h +++ b/common/repositories/base/base_account_ip_repository.h @@ -22,7 +22,7 @@ public: int32_t accid; std::string ip; int32_t count; - std::string lastused; + time_t lastused; }; static std::string PrimaryKey() @@ -46,7 +46,7 @@ public: "accid", "ip", "count", - "lastused", + "UNIX_TIMESTAMP(lastused)", }; } @@ -130,7 +130,7 @@ public: e.accid = row[0] ? static_cast(atoi(row[0])) : 0; e.ip = row[1] ? row[1] : ""; e.count = row[2] ? static_cast(atoi(row[2])) : 1; - e.lastused = row[3] ? row[3] : std::time(nullptr); + e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10); return e; } @@ -167,7 +167,7 @@ public: v.push_back(columns[0] + " = " + std::to_string(e.accid)); v.push_back(columns[1] + " = '" + Strings::Escape(e.ip) + "'"); v.push_back(columns[2] + " = " + std::to_string(e.count)); - v.push_back(columns[3] + " = '" + Strings::Escape(e.lastused) + "'"); + v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -192,7 +192,7 @@ public: v.push_back(std::to_string(e.accid)); v.push_back("'" + Strings::Escape(e.ip) + "'"); v.push_back(std::to_string(e.count)); - v.push_back("'" + Strings::Escape(e.lastused) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -225,7 +225,7 @@ public: v.push_back(std::to_string(e.accid)); v.push_back("'" + Strings::Escape(e.ip) + "'"); v.push_back(std::to_string(e.count)); - v.push_back("'" + Strings::Escape(e.lastused) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -262,7 +262,7 @@ public: e.accid = row[0] ? static_cast(atoi(row[0])) : 0; e.ip = row[1] ? row[1] : ""; e.count = row[2] ? static_cast(atoi(row[2])) : 1; - e.lastused = row[3] ? row[3] : std::time(nullptr); + e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -290,7 +290,7 @@ public: e.accid = row[0] ? static_cast(atoi(row[0])) : 0; e.ip = row[1] ? row[1] : ""; e.count = row[2] ? static_cast(atoi(row[2])) : 1; - e.lastused = row[3] ? row[3] : std::time(nullptr); + e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -368,7 +368,7 @@ public: v.push_back(std::to_string(e.accid)); v.push_back("'" + Strings::Escape(e.ip) + "'"); v.push_back(std::to_string(e.count)); - v.push_back("'" + Strings::Escape(e.lastused) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -394,7 +394,7 @@ public: v.push_back(std::to_string(e.accid)); v.push_back("'" + Strings::Escape(e.ip) + "'"); v.push_back(std::to_string(e.count)); - v.push_back("'" + Strings::Escape(e.lastused) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_variables_repository.h b/common/repositories/base/base_variables_repository.h index dec022fec..9f3516c90 100644 --- a/common/repositories/base/base_variables_repository.h +++ b/common/repositories/base/base_variables_repository.h @@ -23,7 +23,7 @@ public: std::string varname; std::string value; std::string information; - std::string ts; + time_t ts; }; static std::string PrimaryKey() @@ -49,7 +49,7 @@ public: "varname", "value", "information", - "ts", + "UNIX_TIMESTAMP(ts)", }; } @@ -135,7 +135,7 @@ public: e.varname = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.information = row[3] ? row[3] : ""; - e.ts = row[4] ? row[4] : std::time(nullptr); + e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10); return e; } @@ -172,7 +172,7 @@ public: v.push_back(columns[1] + " = '" + Strings::Escape(e.varname) + "'"); v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); v.push_back(columns[3] + " = '" + Strings::Escape(e.information) + "'"); - v.push_back(columns[4] + " = '" + Strings::Escape(e.ts) + "'"); + v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -198,7 +198,7 @@ public: v.push_back("'" + Strings::Escape(e.varname) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back("'" + Strings::Escape(e.information) + "'"); - v.push_back("'" + Strings::Escape(e.ts) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -232,7 +232,7 @@ public: v.push_back("'" + Strings::Escape(e.varname) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back("'" + Strings::Escape(e.information) + "'"); - v.push_back("'" + Strings::Escape(e.ts) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -270,7 +270,7 @@ public: e.varname = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.information = row[3] ? row[3] : ""; - e.ts = row[4] ? row[4] : std::time(nullptr); + e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -299,7 +299,7 @@ public: e.varname = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.information = row[3] ? row[3] : ""; - e.ts = row[4] ? row[4] : std::time(nullptr); + e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -378,7 +378,7 @@ public: v.push_back("'" + Strings::Escape(e.varname) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back("'" + Strings::Escape(e.information) + "'"); - v.push_back("'" + Strings::Escape(e.ts) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -405,7 +405,7 @@ public: v.push_back("'" + Strings::Escape(e.varname) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back("'" + Strings::Escape(e.information) + "'"); - v.push_back("'" + Strings::Escape(e.ts) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/group_id_repository.h b/common/repositories/group_id_repository.h index d2717acfc..84aad5904 100644 --- a/common/repositories/group_id_repository.h +++ b/common/repositories/group_id_repository.h @@ -44,7 +44,15 @@ public: */ // Custom extended repository methods here - + static void ClearAllGroups(Database& db) + { + db.QueryDatabase( + fmt::format( + "DELETE FROM `{}`", + TableName() + ) + ); + } }; #endif //EQEMU_GROUP_ID_REPOSITORY_H diff --git a/common/repositories/group_leaders_repository.h b/common/repositories/group_leaders_repository.h index 9dcef525e..33677b421 100644 --- a/common/repositories/group_leaders_repository.h +++ b/common/repositories/group_leaders_repository.h @@ -44,7 +44,15 @@ public: */ // Custom extended repository methods here - + static void ClearAllGroupLeaders(Database& db) + { + db.QueryDatabase( + fmt::format( + "DELETE FROM `{}`", + TableName() + ) + ); + } }; #endif //EQEMU_GROUP_LEADERS_REPOSITORY_H diff --git a/common/repositories/guild_members_repository.h b/common/repositories/guild_members_repository.h index 9d1133f63..330f5e743 100644 --- a/common/repositories/guild_members_repository.h +++ b/common/repositories/guild_members_repository.h @@ -191,4 +191,5 @@ public: return UpdateOne(db, m); } }; + #endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/inventory_snapshots_repository.h b/common/repositories/inventory_snapshots_repository.h index 742810a25..0fb1f815c 100644 --- a/common/repositories/inventory_snapshots_repository.h +++ b/common/repositories/inventory_snapshots_repository.h @@ -44,7 +44,30 @@ public: */ // Custom extended repository methods here + static int64 CountInventorySnapshots(Database& db) + { + const std::string& query = "SELECT COUNT(*) FROM (SELECT * FROM `inventory_snapshots` a GROUP BY `charid`, `time_index`) b"; + auto results = db.QueryDatabase(query); + + if (!results.Success() || !results.RowCount()) { + return -1; + } + + auto row = results.begin(); + + const int64 count = Strings::ToBigInt(row[0]); + + if (count > std::numeric_limits::max()) { + return -2; + } + + if (count < 0) { + return -3; + } + + return count; + } }; #endif //EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H diff --git a/common/repositories/raid_details_repository.h b/common/repositories/raid_details_repository.h index d37a42434..6903db2a3 100644 --- a/common/repositories/raid_details_repository.h +++ b/common/repositories/raid_details_repository.h @@ -66,6 +66,16 @@ public: return results.Success() ? results.RowsAffected() : 0; } + + static void ClearAllRaidDetails(Database& db) + { + db.QueryDatabase( + fmt::format( + "DELETE FROM `{}`", + TableName() + ) + ); + } }; #endif //EQEMU_RAID_DETAILS_REPOSITORY_H diff --git a/common/repositories/raid_leaders_repository.h b/common/repositories/raid_leaders_repository.h deleted file mode 100644 index 0b6c344ff..000000000 --- a/common/repositories/raid_leaders_repository.h +++ /dev/null @@ -1,297 +0,0 @@ -#ifndef EQEMU_RAID_LEADERS_REPOSITORY_H -#define EQEMU_RAID_LEADERS_REPOSITORY_H - -#include "../database.h" -#include "../strings.h" - -class RaidLeadersRepository { -public: - struct RaidLeaders { - int gid; - int rid; - std::string marknpc; - std::string maintank; - std::string assist; - std::string puller; - std::string leadershipaa; - std::string mentoree; - int mentor_percent; - }; - - static std::string PrimaryKey() - { - return std::string(""); - } - - static std::vector Columns() - { - return { - "gid", - "rid", - "marknpc", - "maintank", - "assist", - "puller", - "leadershipaa", - "mentoree", - "mentor_percent", - }; - } - - static std::string ColumnsRaw() - { - return std::string(Strings::Implode(", ", Columns())); - } - - static std::string InsertColumnsRaw() - { - std::vector insert_columns; - - for (auto &column : Columns()) { - if (column == PrimaryKey()) { - continue; - } - - insert_columns.push_back(column); - } - - return std::string(Strings::Implode(", ", insert_columns)); - } - - static std::string TableName() - { - return std::string("raid_leaders"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - ColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - InsertColumnsRaw() - ); - } - - static RaidLeaders NewEntity() - { - RaidLeaders entry{}; - - entry.gid = 0; - entry.rid = 0; - entry.marknpc = ""; - entry.maintank = ""; - entry.assist = ""; - entry.puller = ""; - entry.leadershipaa = 0; - entry.mentoree = ""; - entry.mentor_percent = 0; - - return entry; - } - - static RaidLeaders GetRaidLeadersEntry( - const std::vector &raid_leaderss, - int raid_leaders_id - ) - { - for (auto &raid_leaders : raid_leaderss) { - if (raid_leaders. == raid_leaders_id) { - return raid_leaders; - } - } - - return NewEntity(); - } - - static RaidLeaders FindOne( - int raid_leaders_id - ) - { - auto results = database.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - raid_leaders_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - RaidLeaders entry{}; - - entry.gid = atoi(row[0]); - entry.rid = atoi(row[1]); - entry.marknpc = row[2]; - entry.maintank = row[3]; - entry.assist = row[4]; - entry.puller = row[5]; - entry.leadershipaa = row[6]; - entry.mentoree = row[7]; - entry.mentor_percent = atoi(row[8]); - - return entry; - } - - return NewEntity(); - } - - static int DeleteOne( - int raid_leaders_id - ) - { - auto results = database.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - raid_leaders_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - RaidLeaders raid_leaders_entry - ) - { - std::vector update_values; - - auto columns = Columns(); - - update_values.push_back(columns[0] + " = " + std::to_string(raid_leaders_entry.gid)); - update_values.push_back(columns[1] + " = " + std::to_string(raid_leaders_entry.rid)); - update_values.push_back(columns[2] + " = '" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); - update_values.push_back(columns[3] + " = '" + Strings::Escape(raid_leaders_entry.maintank) + "'"); - update_values.push_back(columns[4] + " = '" + Strings::Escape(raid_leaders_entry.assist) + "'"); - update_values.push_back(columns[5] + " = '" + Strings::Escape(raid_leaders_entry.puller) + "'"); - update_values.push_back(columns[6] + " = '" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); - update_values.push_back(columns[7] + " = '" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); - update_values.push_back(columns[8] + " = " + std::to_string(raid_leaders_entry.mentor_percent)); - - auto results = database.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - Strings::Implode(", ", update_values), - PrimaryKey(), - raid_leaders_entry. - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static RaidLeaders InsertOne( - RaidLeaders raid_leaders_entry - ) - { - std::vector insert_values; - - insert_values.push_back(std::to_string(raid_leaders_entry.gid)); - insert_values.push_back(std::to_string(raid_leaders_entry.rid)); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); - insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent)); - - auto results = database.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - Strings::Implode(",", insert_values) - ) - ); - - if (results.Success()) { - raid_leaders_entry.id = results.LastInsertedID(); - return raid_leaders_entry; - } - - raid_leaders_entry = InstanceListRepository::NewEntity(); - - return raid_leaders_entry; - } - - static int InsertMany( - std::vector raid_leaders_entries - ) - { - std::vector insert_chunks; - - for (auto &raid_leaders_entry: raid_leaders_entries) { - std::vector insert_values; - - insert_values.push_back(std::to_string(raid_leaders_entry.gid)); - insert_values.push_back(std::to_string(raid_leaders_entry.rid)); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'"); - insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'"); - insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent)); - - insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); - } - - std::vector insert_values; - - auto results = database.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - Strings::Implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All() - { - std::vector all_entries; - - auto results = database.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - RaidLeaders entry{}; - - entry.gid = atoi(row[0]); - entry.rid = atoi(row[1]); - entry.marknpc = row[2]; - entry.maintank = row[3]; - entry.assist = row[4]; - entry.puller = row[5]; - entry.leadershipaa = row[6]; - entry.mentoree = row[7]; - entry.mentor_percent = atoi(row[8]); - - all_entries.push_back(entry); - } - - return all_entries; - } - -}; - -#endif //EQEMU_RAID_LEADERS_REPOSITORY_H diff --git a/common/repositories/raid_members_repository.h b/common/repositories/raid_members_repository.h index 2c2aae1de..822f3e1f6 100644 --- a/common/repositories/raid_members_repository.h +++ b/common/repositories/raid_members_repository.h @@ -60,7 +60,7 @@ public: ); return results.Success() ? results.RowsAffected() : 0; } - + static int UpdateRaidAssister( Database& db, int32_t raid_id, @@ -98,5 +98,15 @@ public: return results.Success() ? results.RowsAffected() : 0; } + + static void ClearAllRaids(Database& db) + { + db.QueryDatabase( + fmt::format( + "DELETE FROM `{}`", + TableName() + ) + ); + } }; #endif //EQEMU_RAID_MEMBERS_REPOSITORY_H diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d20d520d8..0bba4b5a1 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -794,8 +794,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) } if (cv_conflict) { - char char_name[64] = ""; - GetCharName(char_id, char_name); + const std::string& char_name = GetCharName(char_id); LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])", char_name, char_id, diff --git a/utils/scripts/generators/repository-generator.pl b/utils/scripts/generators/repository-generator.pl index 8aef34a20..0c1bb705c 100644 --- a/utils/scripts/generators/repository-generator.pl +++ b/utils/scripts/generators/repository-generator.pl @@ -280,7 +280,7 @@ foreach my $table_to_generate (@tables) { # column names (string) $column_names_quoted .= sprintf("\t\t\t\"%s\",\n", format_column_name_for_mysql($column_name)); - if ($data_type =~ /datetime/) { + if ($data_type =~ /datetime|timestamp/) { $select_column_names_quoted .= sprintf("\t\t\t\"UNIX_TIMESTAMP(%s)\",\n", format_column_name_for_mysql($column_name)); } else { @@ -293,7 +293,7 @@ foreach my $table_to_generate (@tables) { if ($data_type =~ /int|float|double|decimal/) { $query_value = sprintf('" + std::to_string(e.%s));', $column_name_formatted); } - elsif ($data_type =~ /datetime/) { + elsif ($data_type =~ /datetime|timestamp/) { $query_value = sprintf('FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")");', $column_name_formatted, $column_name_formatted); } @@ -309,7 +309,7 @@ foreach my $table_to_generate (@tables) { if ($data_type =~ /int|float|double|decimal/) { $value = sprintf('std::to_string(e.%s)', $column_name_formatted); } - elsif ($data_type =~ /datetime/) { + elsif ($data_type =~ /datetime|timestamp/) { $value = sprintf('"FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")"', $column_name_formatted, $column_name_formatted); } @@ -332,7 +332,7 @@ foreach my $table_to_generate (@tables) { $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value); $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value); } - elsif ($data_type =~ /datetime/) { + elsif ($data_type =~ /datetime|timestamp/) { $all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); $find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index); } @@ -591,7 +591,7 @@ sub translate_mysql_data_type_to_c elsif ($mysql_data_type =~ /double/) { $struct_data_type = 'double'; } - elsif ($mysql_data_type =~ /datetime/) { + elsif ($mysql_data_type =~ /datetime|timestamp/) { $struct_data_type = 'time_t'; } diff --git a/world/client.cpp b/world/client.cpp index 9fd97f98e..4f42662e8 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -54,6 +54,7 @@ #include "../common/events/player_event_logs.h" #include "../common/content/world_content_service.h" #include "../common/repositories/group_id_repository.h" +#include "../common/repositories/character_data_repository.h" #include #include @@ -191,9 +192,9 @@ bool Client::CanTradeFVNoDropItem() void Client::SendEnterWorld(std::string name) { - char char_name[64] = { 0 }; - if (is_player_zoning && database.GetLiveChar(GetAccountID(), char_name)) { - if(database.GetAccountIDByChar(char_name) != GetAccountID()) { + const std::string& live_name = database.GetLiveChar(GetAccountID()); + if (is_player_zoning) { + if(database.GetAccountIDByChar(live_name) != GetAccountID()) { eqs->Close(); return; } else { @@ -201,8 +202,8 @@ void Client::SendEnterWorld(std::string name) } } - auto outapp = new EQApplicationPacket(OP_EnterWorld, strlen(char_name) + 1); - memcpy(outapp->pBuffer,char_name,strlen(char_name)+1); + auto outapp = new EQApplicationPacket(OP_EnterWorld, live_name.length() + 1); + memcpy(outapp->pBuffer, live_name.c_str(), live_name.length() + 1); QueuePacket(outapp); safe_delete(outapp); } @@ -765,9 +766,15 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { auto ew = (EnterWorld_Struct *) app->pBuffer; strn0cpy(char_name, ew->name, sizeof(char_name)); - uint32 temporary_account_id = 0; - charid = database.GetCharacterInfo(char_name, &temporary_account_id, &zone_id, &instance_id); - if (!charid) { + const auto& l = CharacterDataRepository::GetWhere( + database, + fmt::format( + "`name` = '{}' LIMIT 1", + Strings::Escape(char_name) + ) + ); + + if (l.empty()) { LogInfo("Could not get CharInfo for [{}]", char_name); eqs->Close(); return true; @@ -785,13 +792,24 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { instance_id = r.instance.id; } + const auto& e = l.front(); + // Make sure this account owns this character - if (temporary_account_id != account_id) { - LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id); + if (e.account_id != account_id) { + LogInfo( + "Account [{}] does not own the character named [{}] from account [{}]", + account_id, + char_name, + e.account_id + ); eqs->Close(); return true; } + charid = e.id; + zone_id = e.zone_id; + instance_id = e.zone_instance; + // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!is_player_zoning) { diff --git a/world/cliententry.cpp b/world/cliententry.cpp index 3dda07e66..6ed12b821 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -344,7 +344,7 @@ bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_p paccountid = database.CreateAccount( loginserver_account_name, - 0, + std::string(), default_account_status, source_loginserver, LSID() diff --git a/world/console.cpp b/world/console.cpp index 24778e02e..c9d3ab2f6 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -57,8 +57,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string &username, const return ret; } - char account_name[64]; - database.GetAccountName(ret.account_id, account_name); + const std::string& account_name = database.GetAccountName(ret.account_id); ret.account_name = account_name; ret.status = database.CheckStatus(ret.account_id); diff --git a/zone/api_service.cpp b/zone/api_service.cpp index c7935b6e5..edc52ffbe 100644 --- a/zone/api_service.cpp +++ b/zone/api_service.cpp @@ -57,9 +57,7 @@ EQ::Net::WebsocketLoginStatus CheckLogin( return ret; } - char account_name[64]; - database.GetAccountName(static_cast(ret.account_id), account_name); - ret.account_name = account_name; + ret.account_name = database.GetAccountName(static_cast(ret.account_id)); ret.logged_in = true; ret.status = database.CheckStatus(ret.account_id); return ret; diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index cf91e7e97..ba85b9071 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1579,9 +1579,7 @@ std::string Perl__GetCharactersInInstance(uint16 instance_id) char_id_string = fmt::format("{} player(s) in instance: ", character_ids.size()); auto iter = character_ids.begin(); while (iter != character_ids.end()) { - char char_name[64]; - database.GetCharName(*iter, char_name); - char_id_string += char_name; + char_id_string += database.GetCharName(*iter); char_id_string += "("; char_id_string += itoa(*iter); char_id_string += ")"; diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index b157d2316..c20d6f229 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -53,7 +53,7 @@ void command_movechar(Client *c, const Seperator *sep) return; } - const bool moved = database.MoveCharacterToZone(character_name.c_str(), zone_id); + const bool moved = database.MoveCharacterToZone(character_name, zone_id); std::string moved_string = moved ? "Succeeded" : "Failed"; c->Message( Chat::White, diff --git a/zone/zone.cpp b/zone/zone.cpp index 0e08f0dc5..b03150651 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -67,6 +67,7 @@ #include "../common/serverinfo.h" #include "../common/repositories/merc_stance_entries_repository.h" #include "../common/repositories/alternate_currency_repository.h" +#include "../common/repositories/graveyard_repository.h" #include @@ -1023,9 +1024,16 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) if (graveyard_id() > 0) { LogDebug("Graveyard ID is [{}]", graveyard_id()); - bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_graveyard.x, &m_graveyard.y, &m_graveyard.z, &m_graveyard.w); + const auto& e = GraveyardRepository::FindOne(content_db, graveyard_id()); + + if (e.id) { + pgraveyard_zoneid = e.zone_id; + + m_graveyard.x = e.x; + m_graveyard.y = e.y; + m_graveyard.z = e.z; + m_graveyard.w = e.heading; - if (GraveYardLoaded) { LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_graveyard).c_str()); } else {