From 4432c070815873489923c234cab131b01acd825f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 4 Sep 2014 07:24:17 -0500 Subject: [PATCH] State of Commit: Testable if you ask me (Akkadius) what you need to do - Need to convert a list of functions and columns and should be ready to start intensive testing phase - All preliminary tests show things working great - All of player profile is saved and loaded from the database - DBAsync has been completely removed from all code - Removed zone/dbasync.cpp/.h - Removed common/dbasync.cpp/.h - Removed dbasync from cmake commmon and zone - Cleaned up a ton of functions - Added several tables to world CheckDatabaseConversions script: - `character_skills` - `character_languages` - `character_bind` - `character_alternate_abilities` - `character_currency` - `character_data` - `character_spells` - `character_memmed_spells` - `character_disciplines` - `character_material` - `character_tribute` - `character_bandolier` - `character_potionbelt` - Character select now loads from `character_data` - Character creation now creates to `character_data` - Updated function Database::UpdateName to use `character_data` - Updated function Database::CheckUsedName to use `character_data` - Updated function Database::MoveCharacterToZone to use `character_data` - Updated function Database::SetLoginFlags to use `character_data` - Updated function Database::SetFirstLogon to use `character_data` - Updated function Database::SetLFG to use `character_data` - Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with - Removed SharedDatabase::SetPlayerProfile - Trimmed down redundant case switch statements for World sendpackets to QueryServ - Added Character Methods to Database class: Loads: bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); Saves: bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot); bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); Deletes: bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); --- common/CMakeLists.txt | 2 - common/database.cpp | 1354 ++++++++++++++++--------------- common/database.h | 15 +- common/dbasync.cpp | 669 --------------- common/dbasync.h | 176 ---- common/eq_packet_structs.h | 15 +- common/mysql_request_result.cpp | 1 + common/mysql_request_result.h | 2 +- common/shareddb.cpp | 107 +-- common/shareddb.h | 3 - world/client.cpp | 161 ++-- world/net.cpp | 3 - world/worlddb.cpp | 17 +- world/zoneserver.cpp | 109 +-- zone/CMakeLists.txt | 2 - zone/client.cpp | 90 +- zone/client.h | 10 +- zone/client_packet.cpp | 61 +- zone/client_process.cpp | 3 +- zone/command.cpp | 32 +- zone/command.h | 1 - zone/effects.cpp | 1 + zone/entity.cpp | 5 +- zone/entity.h | 4 +- zone/exp.cpp | 9 +- zone/inventory.cpp | 24 +- zone/net.cpp | 10 - zone/questmgr.cpp | 12 +- zone/spells.cpp | 3 +- zone/trading.cpp | 11 +- zone/tribute.cpp | 10 +- zone/zone.cpp | 5 - zone/zonedb.cpp | 395 ++++++--- zone/zonedb.h | 148 ++-- zone/zonedbasync.cpp | 103 --- zone/zonedbasync.h | 22 - zone/zoning.cpp | 10 +- 37 files changed, 1235 insertions(+), 2370 deletions(-) delete mode 100644 common/dbasync.cpp delete mode 100644 common/dbasync.h delete mode 100644 zone/zonedbasync.cpp delete mode 100644 zone/zonedbasync.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f02212161..55e8a8a72 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -8,7 +8,6 @@ SET(common_sources crc16.cpp crc32.cpp database.cpp - dbasync.cpp dbcore.cpp debug.cpp emu_opcodes.cpp @@ -103,7 +102,6 @@ SET(common_headers crc16.h crc32.h database.h - dbasync.h dbcore.h debug.h deity.h diff --git a/common/database.cpp b/common/database.cpp index d926cb950..5de92ba08 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -71,55 +71,25 @@ Database::Database(const char* host, const char* user, const char* passwd, const Connect(host, user, passwd, database, port); } -bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) -{ +bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) { uint32 errnum= 0; char errbuf[MYSQL_ERRMSG_SIZE]; - if (!Open(host, user, passwd, database, port, &errnum, errbuf)) - { + if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); - HandleMysqlError(errnum); return false; } - else - { + else { LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port); return true; } } -void Database::DBInitVars() { - +void Database::DBInitVars() { varcache_array = 0; varcache_max = 0; varcache_lastupdate = 0; } - -void Database::HandleMysqlError(uint32 errnum) { -/* switch(errnum) { - case 0: - break; - case 1045: // Access Denied - case 2001: { - AddEQEMuError(EQEMuError_Mysql_1405, true); - break; - } - case 2003: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2003, true); - break; - } - case 2005: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2005, true); - break; - } - case 2007: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2007, true); - break; - } - }*/ -} - /* Close the connection to the database @@ -191,24 +161,18 @@ bool Database::CheckBannedIPs(const char* loginIP) return false; } -bool Database::AddBannedIP(char* bannedIP, const char* notes) -{ - std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; +bool Database::AddBannedIP(char* bannedIP, const char* notes) { + std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in Database::AddBannedIP query '" << query << "' " << results.ErrorMessage() << std::endl; return false; - } - + } return true; } bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { - std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); - + std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); auto results = QueryDatabase(query); if (!results.Success()) @@ -221,32 +185,24 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::AddGMIP(char* ip_address, char* name) { - std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); - - auto results = QueryDatabase(query); - + std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); + auto results = QueryDatabase(query); return results.Success(); } -void Database::LoginIP(uint32 AccountID, const char* LoginIP) -{ - std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); - - auto results = QueryDatabase(query); - +void Database::LoginIP(uint32 AccountID, const char* LoginIP) { + std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); + auto results = QueryDatabase(query); if (!results.Success()) std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; } -int16 Database::CheckStatus(uint32 account_id) -{ +int16 Database::CheckStatus(uint32 account_id) { std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" " FROM `account` WHERE `id` = %i", account_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -254,10 +210,8 @@ int16 Database::CheckStatus(uint32 account_id) if (results.RowCount() != 1) return 0; - auto row = results.begin(); - - int16 status = atoi(row[0]); - + auto row = results.begin(); + int16 status = atoi(row[0]); int32 suspendeduntil = 0; // MariaDB initalizes with NULL if unix_timestamp() is out of range @@ -281,12 +235,10 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta else query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); - std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; - + std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -301,8 +253,7 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta } bool Database::DeleteAccount(const char* name) { - std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); - + std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); std::cout << "Account Attempting to be deleted:" << name << std::endl; auto results = QueryDatabase(query); @@ -317,7 +268,7 @@ bool Database::DeleteAccount(const char* name) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid); + std::string query = StringFormat("UPDATE `account` SET `password` = MD5('%s') where id=%i;", password, accid); auto results = QueryDatabase(query); @@ -342,275 +293,394 @@ bool Database::SetAccountStatus(const char* name, int16 status) { if (results.RowsAffected() == 0) { std::cout << "Account: " << name << " does not exist, therefore it cannot be flagged\n"; - return false; + return false; } return true; } -bool Database::ReserveName(uint32 account_id, char* name) -{ - std::string query = StringFormat("INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; - return false; - } - +/* This initially creates the character during character create */ +bool Database::ReserveName(uint32 account_id, char* name) { + std::string query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); + auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::ReserveName", query); return true; } +bool Database::ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query){ + if (ErrorMessage != ""){ std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n" << std::endl; return true; } + return false; +} + /* -Delete the character with the name "name" -returns false on failure, true otherwise + Delete the character with the name "name" + returns false on failure, true otherwise */ -bool Database::DeleteCharacter(char *name) -{ - std::string query=StringFormat("SELECT id from character_ WHERE name='%s'", name); - int charid; - - if(!name || !strlen(name)) - { +bool Database::DeleteCharacter(char *name) { + uint32 charid = 0; + printf("Database::DeleteCharacter name : %s \n", name); + if(!name || !strlen(name)) { std::cerr << "DeleteCharacter: request to delete without a name (empty char slot)" << std::endl; return false; } -// get id from character_ before deleting record so we can clean up inventory and qglobal - -#if DEBUG >= 5 - std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; -#endif - + /* Get id from character_data before deleting record so we can clean up the rest of the tables */ + std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } + if (charid <= 0){ std::cerr << "Database::DeleteCharacter :: Character not found, stopping delete...\n"; return false; } - if(results.RowCount() != 1) - { - std::cerr << "DeleteCharacter error: got " << results.RowCount() << " rows matching '" << name << "'" << std::endl; - return false; - } - - auto row = results.begin(); - charid = atoi(row[0]); - -#if DEBUG >= 5 - std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; - std::cout << "DeleteCharacter: deleting << '" << name << "' (id " << charid << "): " << std::endl; - std::cout << " quest_globals"; -#endif - - query = StringFormat("DELETE from quest_globals WHERE charid='%d'", charid); + query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); +#ifdef BOTS + query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); +#else + query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid); +#endif QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_tasks"; -#endif - - query = StringFormat("DELETE from character_tasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_activities"; -#endif - - query = StringFormat("DELETE from character_activities WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_enabledtasks"; -#endif - - query = StringFormat("DELETE from character_enabledtasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " completed_tasks"; -#endif - - query = StringFormat("DELETE from completed_tasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " friends"; -#endif - - query = StringFormat("DELETE from friends WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " mail"; -#endif - - query = StringFormat( "DELETE from mail WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " ptimers"; -#endif - - query = StringFormat("DELETE from timers WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " inventory"; -#endif - - query = StringFormat("DELETE from inventory WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " guild_members"; -#endif - -#ifdef BOTS - query = StringFormat("DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid); -#else - query = StringFormat("DELETE FROM guild_members WHERE char_id='%d'", charid); -#endif - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " recipes"; -#endif - - query = StringFormat("DELETE FROM char_recipe_list WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " adventure_stats"; -#endif - - query = StringFormat("DELETE FROM adventure_stats WHERE player_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " zone_flags"; -#endif - - query = StringFormat("DELETE FROM zone_flags WHERE charID='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " titles"; -#endif - - query = StringFormat("DELETE FROM titles WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " titlesets"; -#endif - - query = StringFormat("DELETE FROM player_titlesets WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " keyring"; -#endif - - query = StringFormat("DELETE FROM keyring WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " factions"; -#endif - - query = StringFormat("DELETE FROM faction_values WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " instances"; -#endif - - query = StringFormat("DELETE FROM instance_list_player WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " _character"; -#endif - - query = StringFormat("DELETE from character_ WHERE id='%d'", charid); - results = QueryDatabase(query); - - if(results.RowsAffected() != 1) // here we have to have a match or it's an error - { - LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", results.RowsAffected()); - return false; - } - -#if DEBUG >= 5 - std::cout << " alternate currency"; -#endif - - query = StringFormat("DELETE FROM character_alt_currency WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << std::endl; -#endif - std::cout << "DeleteCharacter: successfully deleted '" << name << "' (id " << charid << ")" << std::endl; - + return true; } -/* This only for new Character creation storing */ -bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext) -{ - char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; - char* end = query; - uint32 charid = 0; - char zone[50]; - float x, y, z; +bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "REPLACE INTO `character_data` (" + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer) " + "VALUES (" + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%i," // hunger_level + "%i," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_point + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_strea + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u" // RestTimer + ")", + character_id, // " id, " + account_id, // " account_id, " + pp->name, // " `name`, " + pp->last_name, // " last_name, " + pp->gender, // " gender, " + pp->race, // " race, " + pp->class_, // " class, " + pp->level, // " `level`, " + pp->deity, // " deity, " + pp->birthday, // " birthday, " + pp->lastlogin, // " last_login, " + pp->timePlayedMin, // " time_played, " + pp->pvp, // " pvp_status, " + pp->level2, // " level2, " + pp->anon, // " anon, " + pp->gm, // " gm, " + pp->intoxication, // " intoxication, " + pp->haircolor, // " hair_color, " + pp->beardcolor, // " beard_color, " + pp->eyecolor1, // " eye_color_1, " + pp->eyecolor2, // " eye_color_2, " + pp->hairstyle, // " hair_style, " + pp->beard, // " beard, " + pp->ability_time_seconds, // " ability_time_seconds, " + pp->ability_number, // " ability_number, " + pp->ability_time_minutes, // " ability_time_minutes, " + pp->ability_time_hours, // " ability_time_hours, " + pp->title, // " title, " + pp->suffix, // " suffix, " + pp->exp, // " exp, " + pp->points, // " points, " + pp->mana, // " mana, " + pp->cur_hp, // " cur_hp, " + pp->STR, // " str, " + pp->STA, // " sta, " + pp->CHA, // " cha, " + pp->DEX, // " dex, " + pp->INT, // " `int`, " + pp->AGI, // " agi, " + pp->WIS, // " wis, " + pp->face, // " face, " + pp->y, // " y, " + pp->x, // " x, " + pp->z, // " z, " + pp->heading, // " heading, " + pp->pvp2, // " pvp2, " + pp->pvptype, // " pvp_type, " + pp->autosplit, // " autosplit_enabled, " + pp->zone_change_count, // " zone_change_count, " + pp->drakkin_heritage, // " drakkin_heritage, " + pp->drakkin_tattoo, // " drakkin_tattoo, " + pp->drakkin_details, // " drakkin_details, " + pp->toxicity, // " toxicity, " + pp->hunger_level, // " hunger_level, " + pp->thirst_level, // " thirst_level, " + pp->ability_up, // " ability_up, " + pp->zone_id, // " zone_id, " + pp->zoneInstance, // " zone_instance, " + pp->leadAAActive, // " leadership_exp_on, " + pp->ldon_points_guk, // " ldon_points_guk, " + pp->ldon_points_mir, // " ldon_points_mir, " + pp->ldon_points_mmc, // " ldon_points_mmc, " + pp->ldon_points_ruj, // " ldon_points_ruj, " + pp->ldon_points_tak, // " ldon_points_tak, " + pp->ldon_points_available, // " ldon_points_available, " + pp->tribute_time_remaining, // " tribute_time_remaining, " + pp->showhelm, // " show_helm, " + pp->career_tribute_points, // " career_tribute_points, " + pp->tribute_points, // " tribute_points, " + pp->tribute_active, // " tribute_active, " + pp->endurance, // " endurance, " + pp->group_leadership_exp, // " group_leadership_exp, " + pp->raid_leadership_exp, // " raid_leadership_exp, " + pp->group_leadership_points, // " group_leadership_points, " + pp->raid_leadership_points, // " raid_leadership_points, " + pp->air_remaining, // " air_remaining, " + pp->PVPKills, // " pvp_kills, " + pp->PVPDeaths, // " pvp_deaths, " + pp->PVPCurrentPoints, // " pvp_current_points, " + pp->PVPCareerPoints, // " pvp_career_points, " + pp->PVPBestKillStreak, // " pvp_best_kill_streak, " + pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, " + pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, " + pp->aapoints_spent, // " aa_points_spent, " + pp->expAA, // " aa_exp, " + pp->aapoints, // " aa_points, " + pp->groupAutoconsent, // " group_auto_consent, " + pp->raidAutoconsent, // " raid_auto_consent, " + pp->guildAutoconsent, // " guild_auto_consent, " + pp->RestTimer // " RestTimer) " + ); + auto results = QueryDatabase(query); + return true; +} + +/* This only for new Character creation storing */ +bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { + uint32 charid = 0; char zone[50]; float x, y, z; charid = GetCharacterID(pp->name); - if(!charid) - { + if(!charid) { LogFile->write(EQEMuLog::Error, "StoreCharacter: no character id"); return false; } const char *zname = GetZoneName(pp->zone_id); if(zname == nullptr) { - //zone not in the DB, something to prevent crash... + /* Zone not in the DB, something to prevent crash... */ strn0cpy(zone, "qeynos", 49); pp->zone_id = 1; - } else - strn0cpy(zone, zname, 49); - - x=pp->x; - y=pp->y; - z=pp->z; - - // construct the character_ query - end += sprintf(end, - "UPDATE character_ SET timelaston=0, " - "zonename=\'%s\', x=%f, y=%f, z=%f, profile=\'", - zone, x, y, z - ); - end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end, "\', extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\' WHERE account_id=%d AND name='%s'",account_id, pp->name); - - auto results = QueryDatabase(query, (uint32) (end - query)); - // stack assigned query, no need to delete it. - - if(!results.RowsAffected()) - { - LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, results.ErrorMessage().c_str()); - return false; } + else{ strn0cpy(zone, zname, 49); } - // now the inventory + x = pp->x; + y = pp->y; + z = pp->z; + + /* Saves Player Profile Data to `character_data` */ + SaveCharacterCreate(charid, account_id, pp); + + /* Insert starting inventory... */ std::string invquery; - for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) - { + for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) { const ItemInst* newinv = inv->GetItem(i); - if (newinv) - { + if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor()); @@ -624,69 +694,41 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven #endif } - if (i == MainCursor) { - i = EmuConstants::GENERAL_BAGS_BEGIN; - continue; - } - else if (i == EmuConstants::CURSOR_BAG_END) { - i = EmuConstants::BANK_BEGIN; - continue; - } - else if (i == EmuConstants::BANK_END) { - i = EmuConstants::BANK_BAGS_BEGIN; - continue; - } - + if (i == MainCursor) { i = EmuConstants::GENERAL_BAGS_BEGIN; continue; } + else if (i == EmuConstants::CURSOR_BAG_END) { i = EmuConstants::BANK_BEGIN; continue; } + else if (i == EmuConstants::BANK_END) { i = EmuConstants::BANK_BAGS_BEGIN; continue; } i++; } return true; } -//0=failure, otherwise returns the char ID for the given char name. uint32 Database::GetCharacterID(const char *name) { - uint32 cid = 0; - if(GetAccountIDByChar(name, &cid) == 0) - return(0); - return(cid); + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); + auto results = QueryDatabase(query); + auto row = results.begin(); + if (row[0]){ return atoi(row[0]); } + return 0; } /* -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. + 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_ WHERE name='%s'", charname); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - if (results.RowCount() != 1) - return 0; - +uint32 Database::GetAccountIDByChar(const char* charname) { + uint32 accountId = 0; + std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE `name` = '%s' LIMIT 1", charname); + auto results = QueryDatabase(query); auto row = results.begin(); - - uint32 accountId = atoi(row[0]); - - if (oCharID) - *oCharID = atoi(row[1]); - + if (row[0]){ accountId = atoi(row[0]); } 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_ WHERE id=%i", char_id); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { + std::string query = StringFormat("SELECT `account_id` FROM `character_` WHERE `id` = %i LIMIT 1", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return 0; } @@ -694,8 +736,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { if (results.RowCount() != 1) return 0; - auto row = results.begin(); - + auto row = results.begin(); return atoi(row[0]); } @@ -703,11 +744,10 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (!isAlphaNumeric(accname)) return 0; - std::string query = StringFormat("SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname); + std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' LIMIT 1", accname); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -722,8 +762,7 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (status) *status = atoi(row[1]); - if (lsid) - { + if (lsid) { if (row[2]) *lsid = atoi(row[2]); else @@ -734,12 +773,10 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - std::string query = StringFormat("SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid); - + std::string query = StringFormat("SELECT `name`, `lsaccount_id` FROM `account` WHERE `id` = '%i'", accountid); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; return; } @@ -773,11 +810,9 @@ void Database::GetCharName(uint32 char_id, char* name) { } static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { - if ((x != n) && (x % (n / 100 + 1) != 0)) return; - + if ((x != n) && (x % (n / 100 + 1) != 0)) return; float ratio = x / (float)n; - int c = ratio * w; - + int c = ratio * w; std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; for (int x = 0; xcareerRadCrystals, pp->currentEbonCrystals, pp->careerEbonCrystals - ); + ); auto results = QueryDatabase(rquery); if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } @@ -1228,7 +1322,7 @@ bool Database::CheckDatabaseConversions() { "drakkin_heritage," "drakkin_tattoo," "drakkin_details," - "toxicity," + "toxicity," "hunger_level," "thirst_level," "ability_up," @@ -1319,7 +1413,7 @@ bool Database::CheckDatabaseConversions() { "%u," // drakkin_heritage "%u," // drakkin_tattoo "%u," // drakkin_details - "%u," // toxicity + "%i," // toxicity "%u," // hunger_level "%u," // thirst_level "%u," // ability_up @@ -1463,35 +1557,38 @@ bool Database::CheckDatabaseConversions() { } /* Run Bind Home Convert */ - rquery = StringFormat("REPLACE INTO `character_bind_home` (id, zone_id, instance_id, x, y, z, heading)" - " VALUES (%u, %u, %u, %f, %f, %f, %f)", + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* Run Bind Convert */ + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Language Convert */ for (i = 0; i < MAX_PP_LANGUAGE; i++){ if (pp->languages[i] > 0){ rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Skill Convert */ for (i = 0; i < MAX_PP_SKILL; i++){ - if (pp->skills[i] > 0){ + if (pp->skills[i] > 0){ rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Spell Convert */ for (i = 0; i < MAX_PP_SPELLBOOK; i++){ - if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Max Memmed Spell Convert */ for (i = 0; i < MAX_PP_MEMSPELL; i++){ if (pp->mem_spells[i] > 0){ @@ -1499,12 +1596,11 @@ bool Database::CheckDatabaseConversions() { QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Discipline Convert */ for (i = 0; i < MAX_PP_DISCIPLINES; i++){ if (pp->disciplines.values[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_disciplines` (id, disc_id) VALUES (%u, %u)", character_id, pp->disciplines.values[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } /* Run Material Color Convert */ @@ -1512,9 +1608,32 @@ bool Database::CheckDatabaseConversions() { if (pp->item_tint[i].color > 0){ rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); // printf("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u);\n", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } + /* Run Tribute Convert */ + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } + /* Run Bandolier Convert */ + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } + } + /* Run Potion Belt Convert */ + for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ + if (pp->potionbelt.items[i].item_id > 0){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } } /* Print out the entire Player Profile for testing */ @@ -2283,7 +2402,7 @@ bool Database::AddToNameFilter(const char* name) { } uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) { - + uint32 account_id = 0; std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID); auto results = QueryDatabase(query); @@ -2296,14 +2415,14 @@ uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* o if (results.RowCount() != 1) return 0; - auto row = results.begin(); + for (auto row = results.begin(); row != results.end(); ++row) { + account_id = atoi(row[0]); - uint32 account_id = atoi(row[0]); - - if (oAccountName) - strcpy(oAccountName, row[1]); - if (oStatus) - *oStatus = atoi(row[2]); + if (oAccountName) + strcpy(oAccountName, row[1]); + if (oStatus) + *oStatus = atoi(row[2]); + } return account_id; } @@ -2339,11 +2458,9 @@ void Database::ClearMerchantTemp(){ std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; } -bool Database::UpdateName(const char* oldname, const char* newname) { - - std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - - std::string query = StringFormat("UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname); +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); if (!results.Success()) @@ -2356,13 +2473,10 @@ bool Database::UpdateName(const char* oldname, const char* newname) { } // If the name is used or an error occurs, it returns false, otherwise it returns true -bool Database::CheckUsedName(const char* name) -{ - std::string query = StringFormat("SELECT id FROM character_ where name='%s'", name); - auto results = QueryDatabase(query); - - if (!results.Success()) - { +bool Database::CheckUsedName(const char* name) { + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2373,13 +2487,10 @@ bool Database::CheckUsedName(const char* name) return true; } -uint8 Database::GetServerType() -{ - std::string query("SELECT value FROM variables WHERE varname='ServerType'"); - auto results = QueryDatabase(query); - - if (!results.Success()) - { +uint8 Database::GetServerType() { + std::string query("SELECT `value` FROM `variables` WHERE `varname` = 'ServerType' LIMIT 1"); + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -2391,15 +2502,14 @@ uint8 Database::GetServerType() return atoi(row[0]); } -bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { +bool Database::MoveCharacterToZone(const char* charname, const char* zonename, uint32 zoneid) { if(zonename == nullptr || strlen(zonename) == 0) return false; - std::string query = StringFormat("UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname); + std::string query = StringFormat("UPDATE `character_data` SET `zoneid` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `name` = '%s'", zoneid, charname); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2414,13 +2524,11 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { return MoveCharacterToZone(charname, zonename, GetZoneID(zonename)); } -bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - - std::string query = StringFormat("UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID); +bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { + std::string query = StringFormat("UPDATE `character_data` SET `zoneid` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2428,57 +2536,11 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { return results.RowsAffected() != 0; } -uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { - - PlayerProfile_Struct* pp; - ExtendedProfile_Struct* ext; - - std::string query = StringFormat("SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname); +bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { + std::string query = StringFormat("INSERT INTO `hackers` (account, name, hacked) values('%s','%s','%s')", accountname, charactername, hacked); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in CopyCharacter read query '" << query << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - auto row = results.begin(); - - pp = (PlayerProfile_Struct*)row[0]; - strcpy(pp->name, newname); - - ext = (ExtendedProfile_Struct*)row[1]; - - char query2[276 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 1]; - char* end=query2; - - end += sprintf(end, "INSERT INTO character_ SET zonename=\'%s\', x = %f, y = %f, z = %f, profile=\'", GetZoneName(pp->zone_id), pp->x, pp->y, pp->z); - end += DoEscapeString(end, (char*) pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end,"\', extprofile=\'"); - end += DoEscapeString(end, (char*) ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\', account_id=%d, name='%s'", acctid, newname); - - results = QueryDatabase(query2, (uint32) (end - query2)); - - if (!results.Success()) - { - std::cerr << "Error in CopyCharacter query '" << query2 << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - if (results.RowsAffected() == 0) - return 0; - - return 1; -} - -bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - - std::string query = StringFormat("INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2486,8 +2548,7 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, return results.RowsAffected() != 0; } -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { - +bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone); auto results = QueryDatabase(query); @@ -2573,8 +2634,6 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo std::string query = StringFormat("SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'", iName); auto results = QueryDatabase(query); - printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); - if (!results.Success()) { std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; @@ -2583,7 +2642,7 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo if (results.RowCount() != 1) return 0; - auto row = results.begin(); + auto row = results.begin(); uint32 charid = atoi(row[0]); if (oAccID){ *oAccID = atoi(row[1]); } if (oZoneID){ *oZoneID = atoi(row[2]); } @@ -2592,8 +2651,6 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo if (oY){ *oY = atof(row[5]); } if (oZ){ *oZ = atof(row[6]); } - printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); - return charid; } @@ -2631,45 +2688,35 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { return true; } -void Database::SetLFP(uint32 CharID, bool LFP) { - - std::string query = StringFormat("update character_ set lfp=%i where id=%i",LFP, CharID); - auto results = QueryDatabase(query); - +void Database::SetLFP(uint32 CharID, bool LFP) { + std::string query = StringFormat("UPDATE `character_data` SET `lfp` = %i WHERE `id` = %i",LFP, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { - - std::string query = StringFormat("update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID); - auto results = QueryDatabase(query); - +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); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetLFG(uint32 CharID, bool LFG) { - - std::string query = StringFormat("update character_ set lfg=%i where id=%i",LFG, CharID); - auto results = QueryDatabase(query); - +void Database::SetLFG(uint32 CharID, bool LFG) { + std::string query = StringFormat("update `character_data` SET `lfg` = %i WHERE `id` = %i",LFG, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { - - std::string query = StringFormat( "update character_ set firstlogon=%i where id=%i",firstlogon, CharID); - auto results = QueryDatabase(query); - +void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { + std::string query = StringFormat( "UPDATE `character_data` SET `firstlogon` = %i WHERE `id` = %i",firstlogon, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::AddReport(std::string who, std::string against, std::string lines) -{ - +void Database::AddReport(std::string who, std::string against, std::string lines) { char *escape_str = new char[lines.size()*2+1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); @@ -2681,11 +2728,9 @@ void Database::AddReport(std::string who, std::string against, std::string lines LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } -void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc){ - +void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc) { std::string query; - if (id == 0) - { + if (id == 0) { // removing from group query = StringFormat("delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc); auto results = QueryDatabase(query); @@ -2696,8 +2741,8 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism return; } - // adding to group - query = StringFormat("replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc); + /* Add to the Group */ + query = StringFormat("REPLACE INTO `group_id` SET `charid` = %i, `groupid` = %i, `name` = '%s', `ismerc` = '%i'", charid, id, name, ismerc); auto results = QueryDatabase(query); if (!results.Success()) @@ -2755,46 +2800,34 @@ uint32 Database::GetGroupID(const char* name){ return atoi(row[0]); } -char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ - - PlayerProfile_Struct pp; - - std::string query = StringFormat("SELECT profile from character_ where name='%s'", name); +/* Is this really getting used properly... A half implementation ? Akkadius */ +char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf){ + std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name); auto results = QueryDatabase(query); + auto row = results.begin(); uint32 group_id = 0; + if (row[0]){ group_id = atoi(row[0]); } - if (!results.Success()) - { - std::cout << "Unable to get leader name: " << results.ErrorMessage() << std::endl; - return leaderbuf; - } - - if (results.LengthOfColumn(0) != sizeof(PlayerProfile_Struct)) - return leaderbuf; - - auto row = results.begin(); - - memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); - strcpy(leaderbuf,pp.groupMembers[0]); + query = StringFormat("SELECT `name` FROM `group_id` WHERE `name` != '%s' AND `groupid` = %u", name, group_id); + results = QueryDatabase(query); + row = results.begin(); + if (row[0]){ strcpy(leaderbuf, row[0]); } return leaderbuf; } -void Database::SetGroupLeaderName(uint32 gid, const char* name) { - - std::string query = StringFormat("Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name); +void Database::SetGroupLeaderName(uint32 gid, const char* name) { + std::string query = StringFormat("REPLACE INTO `group_leaders` SET `gid` = %lu, `leadername` = '%s'",(unsigned long)gid,name); auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; } -char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - - std::string query = StringFormat("SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid); +char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ + std::string query = StringFormat("SELECT `leadername`, `maintank`, `assist`, `puller`, `marknpc`, `leadershipaa` FROM `group_leaders` WHERE `gid` = %lu",(unsigned long)gid); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - { + if (!results.Success() || results.RowCount() == 0) { if(leaderbuf) strcpy(leaderbuf, "UNKNOWN"); @@ -2837,8 +2870,7 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta } // Clearing all group leaders -void Database::ClearAllGroupLeaders(void) -{ +void Database::ClearAllGroupLeaders(void) { std::string query("DELETE from group_leaders"); auto results = QueryDatabase(query); @@ -2863,8 +2895,7 @@ void Database::ClearGroupLeader(uint32 gid) { std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; } -uint8 Database::GetAgreementFlag(uint32 acctid) -{ +uint8 Database::GetAgreementFlag(uint32 acctid) { std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid); auto results = QueryDatabase(query); @@ -2880,14 +2911,12 @@ uint8 Database::GetAgreementFlag(uint32 acctid) return atoi(row[0]); } -void Database::SetAgreementFlag(uint32 acctid) -{ +void Database::SetAgreementFlag(uint32 acctid) { std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid); QueryDatabase(query); } void Database::ClearRaid(uint32 rid) { - if(rid == 0) { //clear all raids @@ -2903,8 +2932,7 @@ void Database::ClearRaid(uint32 rid) { std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; } -void Database::ClearAllRaids(void) -{ +void Database::ClearAllRaids(void) { std::string query("delete from raid_members"); auto results = QueryDatabase(query); diff --git a/common/database.h b/common/database.h index a22e6d406..c70464094 100644 --- a/common/database.h +++ b/common/database.h @@ -105,10 +105,16 @@ public: 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); ~Database(); + bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query); + /* * General Character Related Stuff */ + + /* Character Creation */ + bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool MoveCharacterToZone(const char* charname, const char* zonename); bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid); bool MoveCharacterToZone(uint32 iCharID, const char* iZonename); @@ -118,16 +124,15 @@ public: bool AddToNameFilter(const char* name); bool ReserveName(uint32 account_id, char* name); 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 StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext); + bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv); bool DeleteCharacter(char* name); - uint8 CopyCharacter(const char* oldname, const char* newname, uint32 acctid); /* * General Information Getting Queries */ bool CheckNameFilter(const char* name, bool surname = false); bool CheckUsedName(const char* name); - uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); + uint32 GetAccountIDByChar(const char* charname); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); uint32 GetGuildIDByCharID(uint32 char_id); @@ -252,10 +257,6 @@ public: void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); void AddReport(std::string who, std::string against, std::string lines); - -protected: - void HandleMysqlError(uint32 errnum); - private: void DBInitVars(); diff --git a/common/dbasync.cpp b/common/dbasync.cpp deleted file mode 100644 index 00714c2a0..000000000 --- a/common/dbasync.cpp +++ /dev/null @@ -1,669 +0,0 @@ -#include "debug.h" -#ifdef _WINDOWS - #include - #include - #include -#endif -#include -#include "dbasync.h" -#include "database.h" -#include -#include -#include -#include "dbcore.h" -#include -//#include "../common/misc_functions.h" -#include "string_util.h" -#define ASYNC_LOOP_GRANULARITY 4 //# of ms between checking our work - -bool DBAsyncCB_LoadVariables(DBAsyncWork* iWork) { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* result = 0; - DBAsyncQuery* dbaq = iWork->PopAnswer(); - if (dbaq->GetAnswer(errbuf, &result)) - iWork->GetDB()->LoadVariables_result(result); - else - std::cout << "Error: DBAsyncCB_LoadVariables failed: !GetAnswer: '" << errbuf << "'" << std::endl; - return true; -} - -void AsyncLoadVariables(DBAsync *dba, Database *db) { - char* query = 0; - DBAsyncWork* dbaw = new DBAsyncWork(db, &DBAsyncCB_LoadVariables, 0, DBAsync::Read); - dbaw->AddQuery(0, &query, db->LoadVariables_MQ(&query)); - dba->AddWork(&dbaw); -} - - -//we only need to do anything when somebody puts work on the queue -//so instead of checking all the time, we will wait on a condition -//which will get signaled when somebody puts something on the queue -ThreadReturnType DBAsyncLoop(void* tmp) { - DBAsync* dba = (DBAsync*) tmp; - -#ifndef WIN32 - _log(COMMON__THREADS, "Starting DBAsyncLoop with thread ID %d", pthread_self()); -#endif - - dba->MLoopRunning.lock(); - while (dba->RunLoop()) { - //wait before working so we check the loop condition - //as soon as were done working - dba->CInList.Wait(); - //we could check dba->RunLoop() again to see if we - //got turned off while we were waiting - { - dba->Process(); - } - } - dba->MLoopRunning.unlock(); - -#ifndef WIN32 - _log(COMMON__THREADS, "Ending DBAsyncLoop with thread ID %d", pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -DBAsync::DBAsync(DBcore* iDBC) -: Timeoutable(10000) -{ - pDBC = iDBC; - pRunLoop = true; - pNextID = 1; -#ifdef _WINDOWS - _beginthread(DBAsyncLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, DBAsyncLoop, this); -#endif -} - -DBAsync::~DBAsync() { - StopThread(); -} - -bool DBAsync::StopThread() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - pRunLoop = false; - MRunLoop.unlock(); - - //signal the condition so we exit the loop if were waiting - CInList.Signal(); - - //this effectively waits for the processing thread to finish - MLoopRunning.lock(); - MLoopRunning.unlock(); - - return ret; -} - -uint32 DBAsync::AddWork(DBAsyncWork** iWork, uint32 iDelay) { - MInList.lock(); - uint32 ret = GetNextID(); - if (!(*iWork)->SetWorkID(ret)) { - MInList.unlock(); - return 0; - } - InList.Append(*iWork); - (*iWork)->SetStatus(Queued); - if (iDelay) - (*iWork)->pExecuteAfter = Timer::GetCurrentTime() + iDelay; -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "Adding AsyncWork #" << (*iWork)->GetWorkID() << std::endl; - std::cout << "ExecuteAfter = " << (*iWork)->pExecuteAfter << " (" << Timer::GetCurrentTime() << " + " << iDelay << ")" << std::endl; -#endif - *iWork = 0; - MInList.unlock(); - - //wake up the processing thread and tell it to get to work. - CInList.Signal(); - - return ret; -} - -bool DBAsync::CancelWork(uint32 iWorkID) { - if (iWorkID == 0) - return false; -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "DBAsync::CancelWork: " << iWorkID << std::endl; -#endif - MCurrentWork.lock(); - if (CurrentWork && CurrentWork->GetWorkID() == iWorkID) { - CurrentWork->Cancel(); - MCurrentWork.unlock(); - return true; - } - MCurrentWork.unlock(); - MInList.lock(); - LinkedListIterator iterator(InList); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->GetWorkID() == iWorkID) { - iterator.RemoveCurrent(true); - MInList.unlock(); - return true; - } - iterator.Advance(); - } - MInList.unlock(); - return false; -} - -bool DBAsync::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - -DBAsyncWork* DBAsync::InListPop() { - DBAsyncWork* ret = 0; - MInList.lock(); - LinkedListIterator iterator(InList); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->pExecuteAfter <= Timer::GetCurrentTime()) { - ret = iterator.GetData(); -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "Poping AsyncWork #" << ret->GetWorkID() << std::endl; - std::cout << ret->pExecuteAfter << " <= " << Timer::GetCurrentTime() << std::endl; -#endif - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MInList.unlock(); - return ret; -} - -DBAsyncWork* DBAsync::InListPopWrite() { - MInList.lock(); - LinkedListIterator iterator(InList); - - DBAsyncWork* ret = 0; - DBAsync::Type tmpType; - iterator.Reset(); - while (iterator.MoreElements()) { - tmpType = iterator.GetData()->Type(); - if (tmpType == Write || tmpType == Both) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MInList.unlock(); - return ret; -} - -void DBAsync::AddFQ(DBAsyncFinishedQueue* iDBAFQ) { - MFQList.lock(); - DBAsyncFinishedQueue** tmp = new DBAsyncFinishedQueue*; - *tmp = iDBAFQ; - FQList.Append(tmp); - MFQList.unlock(); -} - -void DBAsync::Process() { - DBAsyncWork* tmpWork; - MCurrentWork.lock(); - while ((CurrentWork = InListPop())) { - MCurrentWork.unlock(); - //move from queued to executing - Status tmpStatus = CurrentWork->SetStatus(Executing); - if (tmpStatus == Queued) { - //execute the work - ProcessWork(CurrentWork); - tmpWork = CurrentWork; - MCurrentWork.lock(); - CurrentWork = 0; - MCurrentWork.unlock(); - //move from executing to finished - tmpStatus = tmpWork->SetStatus(DBAsync::Finished); - if (tmpStatus != Executing) { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #1" << std::endl; - } - MCurrentWork.lock(); - safe_delete(tmpWork); - } - else { - //call callbacks or put results on finished queue - DispatchWork(tmpWork); - Sleep(25); - MCurrentWork.lock(); - } - } - else { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #2" << std::endl; - } - MCurrentWork.lock(); - safe_delete(CurrentWork); - } - } - MCurrentWork.unlock(); -} - -void DBAsync::CheckTimeout() { - try{ - MFQList.lock(); - LinkedListIterator iterator(FQList); - - iterator.Reset(); - while (iterator.MoreElements()) { - (*iterator.GetData())->CheckTimeouts(); - iterator.Advance(); - } - MFQList.unlock(); - } - catch(...){ - - } -} - -void DBAsync::CommitWrites() { -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "DBAsync::CommitWrites() called." << std::endl; -#endif - DBAsyncWork* tmpWork; - while ((tmpWork = InListPopWrite())) { - Status tmpStatus = tmpWork->SetStatus(Executing); - if (tmpStatus == Queued) { - ProcessWork(tmpWork); - tmpStatus = tmpWork->SetStatus(DBAsync::Finished); - if (tmpStatus != Executing) { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #1" << std::endl; - } - safe_delete(tmpWork); - } - else { - DispatchWork(tmpWork); - } - } - else { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #2" << std::endl; - } - safe_delete(tmpWork); - } - } -} - -void DBAsync::ProcessWork(DBAsyncWork* iWork, bool iSleep) { - DBAsyncQuery* CurrentQuery; - while ((CurrentQuery = iWork->PopQuery())) { - CurrentQuery->Process(pDBC); - iWork->PushAnswer(CurrentQuery); - if (iSleep) - Sleep(1); - } -} - -void DBAsync::DispatchWork(DBAsyncWork* iWork) { - //if this work has a callback, call it - //otherwise, stick the work on the finish queue - if (iWork->pCB) { - if (iWork->pCB(iWork)) - safe_delete(iWork); - } - else { - if (!iWork->pDBAFQ->Push(iWork)) - safe_delete(iWork); - } -} - - - -DBAsyncFinishedQueue::DBAsyncFinishedQueue(uint32 iTimeout) { - pTimeout = iTimeout; -} - -DBAsyncFinishedQueue::~DBAsyncFinishedQueue() { -} - -void DBAsyncFinishedQueue::CheckTimeouts() { - if (pTimeout == 0xFFFFFFFF) - return; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->CheckTimeout(pTimeout)) - iterator.RemoveCurrent(true); - iterator.Advance(); - } - MLock.unlock(); -} - -DBAsyncWork* DBAsyncFinishedQueue::Pop() { - DBAsyncWork* ret = 0; - MLock.lock(); - ret = list.Pop(); - MLock.unlock(); - return ret; -} - -DBAsyncWork* DBAsyncFinishedQueue::Find(uint32 iWorkID) { - DBAsyncWork* ret = 0; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->GetWorkID() == iWorkID) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MLock.unlock(); - return ret; -} - -DBAsyncWork* DBAsyncFinishedQueue::PopByWPT(uint32 iWPT) { - DBAsyncWork* ret = 0; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->WPT() == iWPT) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MLock.unlock(); - return ret; -} - -bool DBAsyncFinishedQueue::Push(DBAsyncWork* iDBAW) { - if (!this) - return false; - MLock.lock(); - list.Append(iDBAW); - MLock.unlock(); - return true; -} - - - -DBAsyncWork::DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout) -: m_db(db) -{ - pstatus = DBAsync::AddingWork; - pType = iType; - pExecuteAfter = 0; - pWorkID = 0; - pDBAFQ = iDBAFQ; - pCB = 0; - pWPT = iWPT; - pQuestionCount = 0; - pAnswerCount = 0; - pTimeout = iTimeout; - pTSFinish = 0; -} - -DBAsyncWork::DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout) -: m_db(db) -{ - pstatus = DBAsync::AddingWork; - pType = iType; - pExecuteAfter = 0; - pWorkID = 0; - pDBAFQ = 0; - pCB = iCB; - pWPT = iWPT; - pQuestionCount = 0; - pAnswerCount = 0; - pTimeout = iTimeout; - pTSFinish = 0; -} - -DBAsyncWork::~DBAsyncWork() { - DBAsyncQuery* dbaq = 0; - while ((dbaq = todo.pop())) - safe_delete(dbaq); - while ((dbaq = done.pop())) - safe_delete(dbaq); - while ((dbaq = todel.pop())) - safe_delete(dbaq); -} - -bool DBAsyncWork::AddQuery(DBAsyncQuery** iDBAQ) { - bool ret; - MLock.lock(); - if (pstatus != DBAsync::AddingWork) - ret = false; - else { - ret = true; - pQuestionCount++; - todo.push(*iDBAQ); - (*iDBAQ)->pstatus = DBAsync::Queued; - *iDBAQ = 0; - } - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - DBAsyncQuery* DBAQ = new DBAsyncQuery(iQPT, iQuery, iQueryLen, iGetResultSet, iGetErrbuf); - if (AddQuery(&DBAQ)) - return true; - else { - safe_delete(DBAQ); - return false; - } -} - -bool DBAsyncWork::SetWorkID(uint32 iWorkID) { - bool ret = true; - MLock.lock(); - if (pWorkID) - ret = false; - else - pWorkID = iWorkID; - MLock.unlock(); - return ret; -} - -uint32 DBAsyncWork::GetWorkID() { - uint32 ret; - MLock.lock(); - ret = pWorkID; - MLock.unlock(); - return ret; -} - -uint32 DBAsyncWork::WPT() { - uint32 ret; - MLock.lock(); - ret = pWPT; - MLock.unlock(); - return ret; -} - -DBAsync::Type DBAsyncWork::Type() { - DBAsync::Type ret; - MLock.lock(); - ret = pType; - MLock.unlock(); - return ret; -} - -DBAsyncQuery* DBAsyncWork::PopAnswer() { - DBAsyncQuery* ret; - MLock.lock(); - ret = done.pop(); - if (ret) - pAnswerCount--; - todel.push(ret); - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::CheckTimeout(uint32 iFQTimeout) { - if (pTimeout == 0xFFFFFFFF) - return false; - bool ret = false; - MLock.lock(); - if (pTimeout > iFQTimeout) - iFQTimeout = pTimeout; - if (Timer::GetCurrentTime() > (pTSFinish + iFQTimeout)) - ret = true; - MLock.unlock(); - return ret; -} - -//sets the work's status to the supplied value and returns -//the revious status -DBAsync::Status DBAsyncWork::SetStatus(DBAsync::Status iStatus) { - DBAsync::Status ret; - MLock.lock(); - if (iStatus == DBAsync::Finished) - pTSFinish = Timer::GetCurrentTime(); - ret = pstatus; - pstatus = iStatus; - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::Cancel() { - bool ret; - MLock.lock(); - if (pstatus != DBAsync::Finished) { - pstatus = DBAsync::Canceled; - ret = true; - } - else - ret = false; - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::IsCancled() { - bool ret; - MLock.lock(); - ret = (bool) (pstatus == DBAsync::Canceled); - MLock.unlock(); - return ret; -} - -DBAsyncQuery* DBAsyncWork::PopQuery() { - DBAsyncQuery* ret = 0; - MLock.lock(); - ret = todo.pop(); - if (ret) - pQuestionCount--; - MLock.unlock(); - return ret; -} - -void DBAsyncWork::PushAnswer(DBAsyncQuery* iDBAQ) { - MLock.lock(); - done.push(iDBAQ); - pAnswerCount++; - MLock.unlock(); -} - - -DBAsyncQuery::DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - if (iQueryLen == 0xFFFFFFFF) - pQueryLen = strlen(*iQuery); - else - pQueryLen = iQueryLen; - pQuery = *iQuery; - *iQuery = 0; - Init(iQPT, iGetResultSet, iGetErrbuf); -} - -DBAsyncQuery::DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - if (iQueryLen == 0xFFFFFFFF) - pQueryLen = strlen(iQuery); - else - pQueryLen = iQueryLen; - pQuery = strn0cpy(new char[pQueryLen+1], iQuery, pQueryLen+1); - Init(iQPT, iGetResultSet, iGetErrbuf); -} - -void DBAsyncQuery::Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf) { - pstatus = DBAsync::AddingWork; - pQPT = iQPT; - pGetResultSet = iGetResultSet; - pGetErrbuf = iGetErrbuf; - - pmysqlsuccess = false; - perrbuf = 0; - perrnum = 0; - presult = 0; - paffected_rows = 0; - plast_insert_id = 0; -} - -DBAsyncQuery::~DBAsyncQuery() { - safe_delete_array(perrbuf); - safe_delete_array(pQuery); - if (presult) - mysql_free_result(presult); -} - -bool DBAsyncQuery::GetAnswer(char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum) { - if (pstatus != DBAsync::Finished) { - if (errbuf) - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error: Query not finished."); - if (errnum) - *errnum = UINT_MAX; - return false; - } - if (errbuf) { - if (pGetErrbuf) { - if (perrbuf) - strn0cpy(errbuf, perrbuf, MYSQL_ERRMSG_SIZE); - else - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message should've been saved, but hasnt. errno: %u", perrnum); - } - else - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message not saved. errno: %u", perrnum); - } - if (errnum) - *errnum = perrnum; - if (affected_rows) - *affected_rows = paffected_rows; - if (last_insert_id) - *last_insert_id = plast_insert_id; - if (result) - *result = presult; - return pmysqlsuccess; -} - -void DBAsyncQuery::Process(DBcore* iDBC) { - pstatus = DBAsync::Executing; - if (pGetErrbuf) - perrbuf = new char[MYSQL_ERRMSG_SIZE]; - MYSQL_RES** resultPP = 0; - if (pGetResultSet) - resultPP = &presult; - pmysqlsuccess = iDBC->RunQuery(pQuery, pQueryLen, perrbuf, resultPP, &paffected_rows, &plast_insert_id, &perrnum); - pstatus = DBAsync::Finished; -} - - - - - - - - - diff --git a/common/dbasync.h b/common/dbasync.h deleted file mode 100644 index f65f9cb58..000000000 --- a/common/dbasync.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef DBASYNC_H -#define DBASYNC_H -#include "../common/dbcore.h" -#include "../common/timeoutmgr.h" - - -class DBAsyncFinishedQueue; -class DBAsyncWork; -class DBAsyncQuery; -class Database; - -// Big daddy that owns the threads and does the work -class DBAsync : private Timeoutable { -public: - enum Status { AddingWork, Queued, Executing, Finished, Canceled }; - enum Type { Read, Write, Both }; - - DBAsync(DBcore* iDBC); - ~DBAsync(); - bool StopThread(); - - uint32 AddWork(DBAsyncWork** iWork, uint32 iDelay = 0); - bool CancelWork(uint32 iWorkID); - void CommitWrites(); - - void AddFQ(DBAsyncFinishedQueue* iDBAFQ); -protected: - //things related to the processing thread: - friend ThreadReturnType DBAsyncLoop(void* tmp); - Mutex MLoopRunning; - Condition CInList; - bool RunLoop(); - void Process(); - -private: - virtual void CheckTimeout(); - - void ProcessWork(DBAsyncWork* iWork, bool iSleep = true); - void DispatchWork(DBAsyncWork* iWork); - inline uint32 GetNextID() { return pNextID++; } - DBAsyncWork* InListPop(); - DBAsyncWork* InListPopWrite(); // Ignores delay - void OutListPush(DBAsyncWork* iDBAW); - - Mutex MRunLoop; - bool pRunLoop; - - DBcore* pDBC; - uint32 pNextID; - Mutex MInList; - LinkedList InList; - - Mutex MFQList; - LinkedList FQList; - - // Mutex for outside access to current work & when current work is being changed. - // NOT locked when CurrentWork is being accessed by the DBAsync thread. - // Never change pointer from outside DBAsync thread! - // Only here for access to thread-safe DBAsyncWork functions. - Mutex MCurrentWork; - DBAsyncWork* CurrentWork; - -}; - -/* - DB Work Complete Callback: - This will be called under the DBAsync thread! Never access any non-threadsafe - data/functions/classes. (ie: zone, entitylist, client, etc are not threadsafe) - Function prototype: - return value: true if we should delete the data, false if we should keep it -*/ -typedef bool(*DBWorkCompleteCallBack)(DBAsyncWork*); - -class DBAsyncFinishedQueue { -public: - DBAsyncFinishedQueue(uint32 iTimeout = 90000); - ~DBAsyncFinishedQueue(); - - DBAsyncWork* Pop(); - DBAsyncWork* PopByWPT(uint32 iWPT); - DBAsyncWork* Find(uint32 iWPT); - bool Push(DBAsyncWork* iDBAW); - - void CheckTimeouts(); -private: - Mutex MLock; - uint32 pTimeout; - LinkedList list; -}; - -// Container class for multiple queries -class DBAsyncWork { -public: - DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0); - DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0); - ~DBAsyncWork(); - - bool AddQuery(DBAsyncQuery** iDBAQ); - bool AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - uint32 WPT(); - DBAsync::Type Type(); - - // Pops finished queries off the work - DBAsyncQuery* PopAnswer(); - uint32 QueryCount(); - - Database *GetDB() const { return(m_db); } - - bool CheckTimeout(uint32 iFQTimeout); - bool SetWorkID(uint32 iWorkID); - uint32 GetWorkID(); -protected: - friend class DBAsync; - DBAsync::Status SetStatus(DBAsync::Status iStatus); - bool Cancel(); - bool IsCancled(); - DBAsyncQuery* PopQuery(); // Get query to be run - void PushAnswer(DBAsyncQuery* iDBAQ); // Push answer back into workset - - // not mutex'd cause only to be accessed from dbasync class - uint32 pExecuteAfter; -private: - Mutex MLock; - uint32 pQuestionCount; - uint32 pAnswerCount; - uint32 pWorkID; - uint32 pWPT; - uint32 pTimeout; - uint32 pTSFinish; // timestamp when finished - DBAsyncFinishedQueue* pDBAFQ; //we do now own this pointer - DBWorkCompleteCallBack pCB; - DBAsync::Status pstatus; - DBAsync::Type pType; - MyQueue todo; - MyQueue done; - MyQueue todel; - Database *const m_db; //we do now own this pointer -}; - -// Container class for the query information -class DBAsyncQuery { -public: - DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - ~DBAsyncQuery(); - - bool GetAnswer(char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0); - inline uint32 QPT() { return pQPT; } -protected: - friend class DBAsyncWork; - uint32 pQPT; - - friend class DBAsync; - void Process(DBcore* iDBC); - - void Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf); - DBAsync::Status pstatus; - char* pQuery; - uint32 pQueryLen; - bool pGetResultSet; - bool pGetErrbuf; - - bool pmysqlsuccess; - char* perrbuf; - uint32 perrnum; - uint32 paffected_rows; - uint32 plast_insert_id; - MYSQL_RES* presult; -}; - - -void AsyncLoadVariables(DBAsync *dba, Database *db); - - -#endif - diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c561e3a22..061f498d4 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -800,9 +800,12 @@ struct SuspendedMinion_Struct ** Length: 4308 bytes ** OpCode: 0x006a */ -static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF -static const uint32 MAX_PP_MEMSPELL = 9; +static const uint32 MAX_PP_LANGUAGE = 28; +static const uint32 MAX_PP_SPELLBOOK = 720; // Set for all functions +static const uint32 MAX_PP_MEMSPELL = 12; // Set to latest client so functions can work right +static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain +static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain + static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 240; static const uint32 MAX_GROUP_MEMBERS = 6; @@ -880,7 +883,7 @@ struct PlayerProfile_Struct /*0245*/ uint8 guildbanker; /*0246*/ uint8 unknown0246[6]; // /*0252*/ uint32 intoxication; -/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms +/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms /*0292*/ uint32 abilitySlotRefresh; /*0296*/ uint8 haircolor; // Player hair color /*0297*/ uint8 beardcolor; // Player beard color @@ -919,9 +922,9 @@ struct PlayerProfile_Struct /*2505*/ uint8 unknown2541[47]; // ? /*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2580*/ uint8 unknown2616[4]; -/*2584*/ uint32 spell_book[MAX_PP_SPELLBOOK]; +/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff -/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL]; +/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL]; /*4668*/ uint8 unknown4704[32]; // /*4700*/ float y; // Player y position /*4704*/ float x; // Player x position diff --git a/common/mysql_request_result.cpp b/common/mysql_request_result.cpp index ffbc3ef40..df598c8cd 100644 --- a/common/mysql_request_result.cpp +++ b/common/mysql_request_result.cpp @@ -32,6 +32,7 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u void MySQLRequestResult::FreeInternals() { + safe_delete_array(m_ErrorBuffer); if (m_Result != nullptr) diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index cd561be56..693c4d43a 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -40,7 +40,7 @@ public: MySQLRequestResult& operator=(MySQLRequestResult&& other); bool Success() const { return m_Success;} - std::string ErrorMessage() const {return std::string(m_ErrorBuffer);} + std::string ErrorMessage() const { return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string(""); } uint32 ErrorNumber() const {return m_ErrorNumber;} uint32 RowsAffected() const {return m_RowsAffected;} uint32 RowCount() const {return m_RowCount;} diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 6124d37f1..f6f960cc3 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -61,46 +61,6 @@ bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) return true; } -bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 affected_rows = 0; - bool ret = false; - - if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { - ret = (affected_rows != 0); - } - - if (!ret) { - LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -// Generate SQL for updating player profile -uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - *query = new char[396 + sizeof(PlayerProfile_Struct)* 2 + sizeof(ExtendedProfile_Struct)* 2 + 4]; - char* end = *query; - if (!current_zone) - current_zone = pp->zone_id; - - if (!current_instance) - current_instance = pp->zoneInstance; - - if (strlen(pp->name) == 0) // Sanity check in case pp never loaded - return false; - - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, ", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); - // end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end, " extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); - - return (uint32)(end - (*query)); -} - uint8 SharedDatabase::GetGMSpeed(uint32 account_id) { @@ -386,12 +346,11 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) return 0; } -bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) -{ +bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `sharedplat` = `sharedplat` + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); return false; @@ -401,35 +360,24 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) return true; } -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; +bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { const Item_Struct* myitem; - - RunQuery - ( - query, - MakeAnyLenString - ( - &query, - "SELECT itemid, item_charges, slot FROM starting_items " - "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " - "(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND " - "gm <= %i ORDER BY id", - si_race, si_class, si_deity, si_current_zone, admin_level - ), - errbuf, - &result - ); - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - int itemid = atoi(row[0]); - int charges = atoi(row[1]); - int slot = atoi(row[2]); + uint32 itemid = 0; + uint32 charges = 0; + uint32 slot = 0; + auto query = StringFormat( + "SELECT `itemid`, `item_charges`, `slot` FROM `starting_items`" + " WHERE (`race` = %i OR `race` = 0)" + " AND (`class` = %i OR `class` = 0)" + " AND (`deityid` = %i OR `deityid` = 0)" + " AND (`zoneid` = %i OR `zoneid` = 0)" + " AND gm <= %i ORDER BY id", + si_race, si_class, si_deity, si_current_zone, admin_level); + auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + itemid = atoi(row[0]); + charges = atoi(row[1]); + slot = atoi(row[2]); myitem = GetItem(itemid); if(!myitem) continue; @@ -439,9 +387,6 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, inv->PutItem(slot, *myinst); safe_delete(myinst); } - - if(result) mysql_free_result(result); - return true; } @@ -675,8 +620,13 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) bool ret = false; // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid", + if (RunQuery(query, MakeAnyLenString(&query, + " SELECT `slotid`, `itemid`, `charges`, `color`, `augslot1`, `augslot2`, `augslot3`, `augslot4`, `augslot5`, `instnodrop`, `custom_data`" + " FROM `inventory`" + " INNER JOIN character_ ch ON ch.id = charid" + " WHERE ch.NAME = '%s'" + " AND ch.account_id = % i" + " ORDER BY `slotid`", name, account_id), errbuf, &result)) { while ((row = mysql_fetch_row(result))) { @@ -736,7 +686,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) } } } - if (slot_id>=8000 && slot_id <= 8999) + if (slot_id >= 8000 && slot_id <= 8999) put_slot_id = inv->PushCursor(*inst); else put_slot_id = inv->PutItem(slot_id, *inst); @@ -2053,8 +2003,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { return nullptr; } -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - +void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; MYSQL_RES *result; diff --git a/common/shareddb.h b/common/shareddb.h index c55163465..5401bfa0a 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -34,9 +34,6 @@ public: SharedDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); virtual ~SharedDatabase(); - /* Temp */ - uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); - bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); /* * General Character Related Stuff */ diff --git a/world/client.cpp b/world/client.cpp index fc7e525db..c8fea66c9 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -64,8 +64,6 @@ extern ClientList client_list; extern uint32 numclients; extern volatile bool RunLoops; - - Client::Client(EQStreamInterface* ieqs) : autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)), CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)), @@ -128,9 +126,8 @@ void Client::SendLogServer() safe_delete(outapp); } -void Client::SendEnterWorld(std::string name) -{ -char char_name[32]= { 0 }; +void Client::SendEnterWorld(std::string name) { + char char_name[32]= { 0 }; if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) { if(database.GetAccountIDByChar(char_name) != GetAccountID()) { eqs->Close(); @@ -472,7 +469,6 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { } bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { - if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account"); return false; @@ -491,19 +487,10 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { outapp->size = 1; bool valid; - if(!database.CheckNameFilter(char_name)) { - valid = false; - } - else if(char_name[0] < 'A' && char_name[0] > 'Z') { - //name must begin with an upper-case letter. - valid = false; - } - else if (database.ReserveName(GetAccountID(), char_name)) { - valid = true; - } - else { - valid = false; - } + if(!database.CheckNameFilter(char_name)) { valid = false; } + else if (char_name[0] < 'A' && char_name[0] > 'Z') { valid = false; } /* Name must begin with an upper-case letter. */ + else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; } + else { valid = false; } outapp->pBuffer[0] = valid? 1 : 0; QueuePacket(outapp); safe_delete(outapp); @@ -642,13 +629,11 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) } bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { - if (GetAccountID() == 0) - { + if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character."); return false; } - else if (app->size != sizeof(CharCreate_Struct)) - { + else if (app->size != sizeof(CharCreate_Struct)) { clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct)); DumpPacket(app); // the previous behavior was essentially returning true here @@ -657,8 +642,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { } CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer; - if(OPCharCreate(char_name, cc) == false) - { + if(OPCharCreate(char_name, cc) == false) { database.DeleteCharacter(char_name); EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApproveName, 1); outapp->pBuffer[0] = 0; @@ -675,8 +659,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { return true; } -bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { - +bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Enter world with no logged in account"); eqs->Close(); @@ -713,8 +696,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { return true; } - if(!pZoning && ew->return_home && !ew->tutorial) - { + if(!pZoning && ew->return_home && !ew->tutorial) { CharacterSelect_Struct* cs = new CharacterSelect_Struct; memset(cs, 0, sizeof(CharacterSelect_Struct)); database.GetCharSelectInfo(GetAccountID(), cs); @@ -733,12 +715,10 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } safe_delete(cs); - if(home_enabled) - { + if(home_enabled) { zoneID = database.MoveCharacterToBind(charid,4); } - else - { + else { clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name); database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able."); eqs->Close(); @@ -807,16 +787,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { database.SetLoginFlags(charid, false, false, 1); } else{ - uint32 groupid=database.GetGroupID(char_name); - if(groupid>0){ - char* leader=0; - char leaderbuf[64]={0}; - if((leader=database.GetGroupLeaderForLogin(char_name,leaderbuf)) && strlen(leader)>1){ + uint32 groupid = database.GetGroupID(char_name); + if(groupid > 0){ + char* leader = 0; + char leaderbuf[64] = {0}; + if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){ EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer; gj->action=8; - strcpy(gj->yourname,char_name); - strcpy(gj->membername,leader); + strcpy(gj->yourname, char_name); + strcpy(gj->membername, leader); QueuePacket(outapp3); safe_delete(outapp3); } @@ -895,8 +875,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) { uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer); - if(char_acct_id == GetAccountID()) - { + if(char_acct_id == GetAccountID()) { clog(WORLD__CLIENT,"Delete character: %s",app->pBuffer); database.DeleteCharacter((char *)app->pBuffer); SendCharInfo(); @@ -1347,8 +1326,7 @@ void Client::SendApproveWorld() safe_delete(outapp); } -bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) -{ +bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) { PlayerProfile_Struct pp; ExtendedProfile_Struct ext; Inventory inv; @@ -1356,12 +1334,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) char startzone[50]={0}; uint32 i; struct in_addr in; - - - int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + - cc->WIS + cc->INT + cc->CHA; + + int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA; in.s_addr = GetIP(); + clog(WORLD__CLIENT,"Character creation request from %s LS#%d (%s:%d) : ", GetCLE()->LSName(), GetCLE()->LSID(), inet_ntoa(in), GetPort()); clog(WORLD__CLIENT,"Name: %s", name); clog(WORLD__CLIENT,"Race: %d Class: %d Gender: %d Deity: %d Start zone: %d", @@ -1374,38 +1351,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) clog(WORLD__CLIENT,"Hairstyle: %d Haircolor: %d", cc->hairstyle, cc->haircolor); clog(WORLD__CLIENT,"Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor); - // validate the char creation struct + /* Validate the char creation struct */ if(ClientVersionBit & BIT_SoFAndLater) { - if(!CheckCharCreateInfoSoF(cc)) - { + if(!CheckCharCreateInfoSoF(cc)) { clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)"); return false; } } else { - if(!CheckCharCreateInfoTitanium(cc)) - { + if(!CheckCharCreateInfoTitanium(cc)) { clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)"); return false; } } - // Convert incoming cc_s to the new PlayerProfile_Struct + /* Convert incoming cc_s to the new PlayerProfile_Struct */ memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile - InitExtendedProfile(&ext); - strn0cpy(pp.name, name, 63); - // clean the capitalization of the name -#if 0 // on second thought, don't - this will just make the creation fail -// because the name won't match what was already reserved earlier - for (i = 0; pp.name[i] && i < 63; i++) - { - if(!isalpha(pp.name[i])) - return false; - pp.name[i] = tolower(pp.name[i]); - } - pp.name[0] = toupper(pp.name[0]); -#endif pp.race = cc->race; pp.class_ = cc->class_; @@ -1432,44 +1394,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.lastlogin = bday; pp.level = 1; pp.points = 5; - pp.cur_hp = 1000; // 1k hp during dev only - //what was the point of this? zone dosent handle this: - //pp.expAA = 0xFFFFFFFF; - + pp.cur_hp = 1000; // 1k hp during dev only pp.hunger_level = 6000; pp.thirst_level = 6000; - - // FIXME: FV roleplay, database goodness... - - // Racial Languages - SetRacialLanguages( &pp ); // bUsh - SetRaceStartingSkills( &pp ); // bUsh - SetClassStartingSkills( &pp ); // bUsh + /* Racial Languages */ + SetRacialLanguages( &pp ); + SetRaceStartingSkills( &pp ); + SetClassStartingSkills( &pp ); pp.skills[SkillSenseHeading] = 200; // Some one fucking fix this to use a field name. -Doodman //pp.unknown3596[28] = 15; // @bp: This is to enable disc usage // strcpy(pp.servername, WorldConfig::get()->ShortName.c_str()); - for(i = 0; i < MAX_PP_SPELLBOOK; i++) + for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++) pp.spell_book[i] = 0xFFFFFFFF; - for(i = 0; i < MAX_PP_MEMSPELL; i++) + for(i = 0; i < MAX_PP_REF_MEMSPELL; i++) pp.mem_spells[i] = 0xFFFFFFFF; for(i = 0; i < BUFF_COUNT; i++) pp.buffs[i].spellid = 0xFFFF; + /* + Was memset(pp.unknown3704, 0xffffffff, 8); + but I dont think thats what you really wanted to do... + memset is byte based + */ - //was memset(pp.unknown3704, 0xffffffff, 8); - //but I dont think thats what you really wanted to do... - //memset is byte based - - //If server is PVP by default, make all character set to it. + /* If server is PVP by default, make all character set to it. */ pp.pvp = database.GetServerType() == 1 ? 1 : 0; - //If it is an SoF Client and the SoF Start Zone rule is set, send new chars there + /* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */ if((ClientVersionBit & BIT_SoFAndLater) && (RuleI(World, SoFStartZoneID) > 0)) { clog(WORLD__CLIENT,"Found 'SoFStartZoneID' rule setting: %i", (RuleI(World, SoFStartZoneID))); pp.zone_id = (RuleI(World, SoFStartZoneID)); @@ -1478,11 +1435,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) else clog(WORLD__CLIENT_ERR,"Error getting zone id for Zone ID %i", (RuleI(World, SoFStartZoneID))); } - else - { - // if there's a startzone variable put them in there - if(database.GetVariable("startzone", startzone, 50)) - { + else { + /* if there's a startzone variable put them in there */ + if(database.GetVariable("startzone", startzone, 50)) { clog(WORLD__CLIENT,"Found 'startzone' variable setting: %s", startzone); pp.zone_id = database.GetZoneID(startzone); if(pp.zone_id) @@ -1490,8 +1445,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) else clog(WORLD__CLIENT_ERR,"Error getting zone id for '%s'", startzone); } - else // otherwise use normal starting zone logic - { + else{ /* otherwise use normal starting zone logic */ bool ValidStartZone = false; if(ClientVersionBit & BIT_TitaniumAndEarlier) @@ -1504,14 +1458,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) } } - if(!pp.zone_id) - { + if(!pp.zone_id) { pp.zone_id = 1; // qeynos pp.x = pp.y = pp.z = -1; } - if(!pp.binds[0].zoneId) - { + if(!pp.binds[0].zoneId) { pp.binds[0].zoneId = pp.zone_id; pp.binds[0].x = pp.x; pp.binds[0].y = pp.y; @@ -1519,7 +1471,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.binds[0].heading = pp.heading; } - // set starting city location to the initial bind point + /* Set Starting city */ pp.binds[4] = pp.binds[0]; @@ -1528,28 +1480,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) clog(WORLD__CLIENT,"Bind location: %s %0.2f, %0.2f, %0.2f", database.GetZoneName(pp.binds[0].zoneId), pp.binds[0].x, pp.binds[0].y, pp.binds[0].z); - - // Starting Items inventory + /* Starting Items inventory */ database.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin()); - // now we give the pp and the inv we made to StoreCharacter // to see if we can store it - if (!database.StoreCharacter(GetAccountID(), &pp, &inv, &ext)) - { + if (!database.StoreCharacter(GetAccountID(), &pp, &inv)) { clog(WORLD__CLIENT_ERR,"Character creation failed: %s", pp.name); return false; } - else - { + else { clog(WORLD__CLIENT,"Character creation successful: %s", pp.name); return true; } } // returns true if the request is ok, false if there's an error -bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) -{ +bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) { if(!cc) return false; _log(WORLD__CLIENT, "Validating char creation info..."); diff --git a/world/net.cpp b/world/net.cpp index 2d186c1af..3c4ab53c3 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -67,7 +67,6 @@ #endif -#include "../common/dbasync.h" #include "../common/emu_tcp_server.h" #include "../common/patches/patches.h" #include "zoneserver.h" @@ -98,7 +97,6 @@ UCSConnection UCSLink; QueryServConnection QSLink; LauncherList launcher_list; AdventureManager adventure_manager; -DBAsync *dbasync = nullptr; volatile bool RunLoops = true; uint32 numclients = 0; uint32 numzones = 0; @@ -175,7 +173,6 @@ int main(int argc, char** argv) { _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); return 1; } - dbasync = new DBAsync(&database); guild_mgr.SetDatabase(&database); if (argc >= 2) { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index deccc9207..fdbcc704d 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -21,7 +21,6 @@ #include "../common/string_util.h" #include "../common/eq_packet_structs.h" #include "../common/item.h" -#include "../common/dbasync.h" #include "../common/rulesys.h" #include #include @@ -390,12 +389,16 @@ bool WorldDatabase::GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Stru in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0; in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "SELECT x,y,z,heading,bind_id FROM start_zones WHERE zone_id=%i AND player_class=%i " - "AND player_deity=%i AND player_race=%i", - in_cc->start_zone, - in_cc->class_, - in_cc->deity, - in_cc->race), errbuf, &result)) + if(!RunQuery(query, MakeAnyLenString(&query, "SELECT `x`, `y`, ``z, `heading`, `bind_id` " + " FROM `start_zones` " + " WHERE `zone_id` = %i " + " AND `player_class` = %i " + " AND player_deity=%i" + " AND player_race=%i", + in_cc->start_zone, + in_cc->class_, + in_cc->deity, + in_cc->race), errbuf, &result)) { LogFile->write(EQEMuLog::Status, "SoF Start zone query failed: %s : %s\n", query, errbuf); safe_delete_array(query); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index af0752a95..6529a1f3d 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -652,17 +652,17 @@ bool ZoneServer::Process() { client->Clearance(wtz->response); } case ServerOP_ZoneToZoneRequest: { - // - // solar: ZoneChange is received by the zone the player is in, then the - // zone sends a ZTZ which ends up here. This code then find the target - // (ingress point) and boots it if needed, then sends the ZTZ to it. - // The ingress server will decide wether the player can enter, then will - // send back the ZTZ to here. This packet is passed back to the egress - // server, which will send a ZoneChange response back to the client - // which can be an error, or a success, in which case the client will - // disconnect, and their zone location will be saved when ~Client is - // called, so it will be available when they ask to zone. - // + // + // solar: ZoneChange is received by the zone the player is in, then the + // zone sends a ZTZ which ends up here. This code then find the target + // (ingress point) and boots it if needed, then sends the ZTZ to it. + // The ingress server will decide wether the player can enter, then will + // send back the ZTZ to here. This packet is passed back to the egress + // server, which will send a ZoneChange response back to the client + // which can be an error, or a success, in which case the client will + // disconnect, and their zone location will be saved when ~Client is + // called, so it will be available when they ask to zone. + // if(pack->size != sizeof(ZoneToZone_Struct)) @@ -675,43 +675,31 @@ bool ZoneServer::Process() { zlog(WORLD__ZONE,"ZoneToZone request for %s current zone %d req zone %d\n", ztz->name, ztz->current_zone_id, ztz->requested_zone_id); - printf("\n\n ZoneToZone request for %s current zone %d req zone %d\n\n", - ztz->name, ztz->current_zone_id, ztz->requested_zone_id); - - if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) // this is a request from the egress zone - { + /* This is a request from the egress zone */ + if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) { zlog(WORLD__ZONE,"Processing ZTZ for egress from zone for client %s\n", ztz->name); - if - ( - ztz->admin < 80 && - ztz->ignorerestrictions < 2 && - zoneserver_list.IsZoneLocked(ztz->requested_zone_id) - ) - { + if (ztz->admin < 80 && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) { ztz->response = 0; SendPacket(pack); break; } ZoneServer *ingress_server = nullptr; - if(ztz->requested_instance_id > 0) - { + if(ztz->requested_instance_id > 0) { ingress_server = zoneserver_list.FindByInstanceID(ztz->requested_instance_id); } - else - { - ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id); - + else { + ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id); } - if(ingress_server) // found a zone already running - { + /* Zone was already running*/ + if(ingress_server) { _log(WORLD__ZONE,"Found a zone already booted for %s\n", ztz->name); ztz->response = 1; } - else // need to boot one - { + /* Boot the Zone*/ + else { int server_id; if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id, ztz->requested_instance_id))){ _log(WORLD__ZONE,"Successfully booted a zone for %s\n", ztz->name); @@ -719,8 +707,7 @@ bool ZoneServer::Process() { ztz->response = 1; ingress_server = zoneserver_list.FindByID(server_id); } - else - { + else { _log(WORLD__ZONE_ERR,"FAILED to boot a zone for %s\n", ztz->name); // bootup failed, send back error code 0 ztz->response = 0; @@ -728,27 +715,24 @@ bool ZoneServer::Process() { } if(ztz->response!=0 && client) client->LSZoneChange(ztz); - SendPacket(pack); // send back to egress server - if(ingress_server) // if we couldn't boot one, this is 0 - { - ingress_server->SendPacket(pack); // inform target server - } + SendPacket(pack); // send back to egress server + if(ingress_server) { + ingress_server->SendPacket(pack); // inform target server + } } - else // this is response from the ingress server, route it back to the egress server - { + /* Response from Ingress server, route back to egress */ + else{ + zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name); ZoneServer *egress_server = nullptr; - if(ztz->current_instance_id > 0) - { + if(ztz->current_instance_id > 0) { egress_server = zoneserver_list.FindByInstanceID(ztz->current_instance_id); } - else - { + else { egress_server = zoneserver_list.FindByZoneID(ztz->current_zone_id); } - if(egress_server) - { + if(egress_server) { egress_server->SendPacket(pack); } } @@ -786,21 +770,18 @@ bool ZoneServer::Process() { delete whom; break; } - case ServerOP_RequestOnlineGuildMembers: - { + case ServerOP_RequestOnlineGuildMembers: { ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*) pack->pBuffer; zlog(GUILDS__IN_PACKETS, "ServerOP_RequestOnlineGuildMembers Recieved. FromID=%i GuildID=%i", srogms->FromID, srogms->GuildID); client_list.SendOnlineGuildMembers(srogms->FromID, srogms->GuildID); break; } - case ServerOP_ClientVersionSummary: - { + case ServerOP_ClientVersionSummary: { ServerRequestClientVersionSummary_Struct *srcvss = (ServerRequestClientVersionSummary_Struct*) pack->pBuffer; client_list.SendClientVersionSummary(srcvss->Name); break; } - case ServerOP_ReloadRules: - { + case ServerOP_ReloadRules: { zoneserver_list.SendPacket(pack); RuleManager::Instance()->LoadRules(&database, "default"); break; @@ -1275,30 +1256,10 @@ bool ZoneServer::Process() { case ServerOP_QueryServGeneric: case ServerOP_Speech: case ServerOP_QSPlayerLogTrades: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogHandins: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogNPCKills: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogDeletes: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogMoves: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogMerchantTransactions: { QSLink.SendPacket(pack); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 0b6ebc10a..8cd086405 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -119,7 +119,6 @@ SET(zone_sources zone_logsys.cpp zone_config.cpp zonedb.cpp - zonedbasync.cpp zoning.cpp ) @@ -207,7 +206,6 @@ SET(zone_headers zone.h zone_config.h zonedb.h - zonedbasync.h zonedump.h ) diff --git a/zone/client.cpp b/zone/client.cpp index c56d47b4d..962715b86 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -73,8 +73,6 @@ extern uint32 numclients; extern PetitionList petition_list; bool commandlogged; char entirecommand[255]; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; Client::Client(EQStreamInterface* ieqs) : Mob("No name", // name @@ -544,8 +542,9 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Currency */ database.SaveCharacterCurrency(this->CharacterID(), &m_pp); - /* Save Character AA */ - // SaveAA(); + /* Save Current Bind Points : Sets Instance to 0 because it is currently not implemented */ + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); /* Regular bind */ + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[4].zoneId, 0, m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0, 1); /* Home Bind */ /* Save Character Buffs */ database.SaveBuffs(this); @@ -557,15 +556,11 @@ bool Client::Save(uint8 iCommitNow) { /* Save Mercs */ if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)){ GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); } - if(GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } + if (GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } if (GetMerc() && !dead) { } else { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); } m_pp.lastlogin = time(nullptr); - if (pQueuedSaveWorkID) { - dbasync->CancelWork(pQueuedSaveWorkID); - pQueuedSaveWorkID = 0; - } if (GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() && !dead) { NPC *pet = GetPet()->CastToNPC(); @@ -585,34 +580,10 @@ bool Client::Save(uint8 iCommitNow) { p_timers.Store(&database); - /* Save Character Task */ - SaveTaskState(); + database.SaveCharacterTribute(this->CharacterID(), &m_pp); - // if (iCommitNow <= 1) { - // // char* query = 0; - // // uint32_breakdown workpt; - // // workpt.b4() = DBA_b4_Entity; - // // workpt.w2_3() = GetID(); - // // workpt.b1() = DBA_b1_Entity_Client_Save; - // // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - // // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - // // if (iCommitNow == 0){ - // // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - // // } - // // else { - // // dbasync->AddWork(&dbaw, 0); - // // SaveBackup(); - // // } - // // safe_delete_array(query); - // // return true; - // } - // else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - // SaveBackup(); - // } - // else { - // std::cerr << "Failed to update player profile" << std::endl; - // return false; - // } + /* Save Character Task */ + SaveTaskState(); /* Save Character Data */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); @@ -624,12 +595,6 @@ bool Client::Save(uint8 iCommitNow) { } void Client::SaveBackup() { - if (!RunLoops) - return; - char* query = 0; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &DBAsyncCB_CharacterBackup, this->CharacterID(), DBAsync::Read); - dbaw->AddQuery(0, &query, MakeAnyLenString(&query, "Select id, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ts) as age from character_backup where charid=%u and backupreason=0 order by ts asc", this->CharacterID()), true); - dbasync->AddWork(&dbaw, 0); } CLIENTPACKET::CLIENTPACKET() @@ -1393,12 +1358,14 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme) void Client::SetSkill(SkillUseTypes skillid, uint16 value) { if (skillid > HIGHEST_SKILL) - return; - m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills + return; + m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills + + database.SaveCharacterSkill(this->CharacterID(), skillid, value); EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; - skill->skillId=skillid; + skill->skillId=skillid; skill->value=value; QueuePacket(outapp); safe_delete(outapp); @@ -1414,10 +1381,12 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) { if (m_pp.languages[skill_id] > 100) //Lang skill above max m_pp.languages[skill_id] = 100; + database.SaveCharacterLanguage(this->CharacterID(), skill_id, m_pp.languages[skill_id]); + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; skill->skillId = 100 + skill_id; - skill->value = m_pp.languages[skill_id]; + skill->value = m_pp.languages[skill_id]; QueuePacket(outapp); safe_delete(outapp); @@ -2165,32 +2134,27 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){ uint64 tmp2; tmp = copper; - // Add Amount of Platinum + /* Add Amount of Platinum */ tmp2 = tmp/1000; int32 new_val = m_pp.platinum + tmp2; - if(new_val < 0) { - m_pp.platinum = 0; - } else { - m_pp.platinum = m_pp.platinum + tmp2; - } + if(new_val < 0) { m_pp.platinum = 0; } + else { m_pp.platinum = m_pp.platinum + tmp2; } tmp-=tmp2*1000; //if (updateclient) // SendClientMoneyUpdate(3,tmp2); - // Add Amount of Gold + /* Add Amount of Gold */ tmp2 = tmp/100; new_val = m_pp.gold + tmp2; - if(new_val < 0) { - m_pp.gold = 0; - } else { - m_pp.gold = m_pp.gold + tmp2; - } + if(new_val < 0) { m_pp.gold = 0; } + else { m_pp.gold = m_pp.gold + tmp2; } + tmp-=tmp2*100; //if (updateclient) // SendClientMoneyUpdate(2,tmp2); - // Add Amount of Silver + /* Add Amount of Silver */ tmp2 = tmp/10; new_val = m_pp.silver + tmp2; if(new_val < 0) { @@ -2226,8 +2190,7 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){ LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); } -void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ - +void Client::EVENT_ITEM_ScriptStopReturn(){ /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items This will stopgap players from items being returned if global_npc.pl has a catch all return_items */ @@ -2236,6 +2199,10 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat gettimeofday(&read_time, 0); sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); this->SetEntityVariable("Stop_Return", buffer); +} + +void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ + this->EVENT_ITEM_ScriptStopReturn(); int32 new_value = m_pp.platinum + platinum; if(new_value >= 0 && new_value > m_pp.platinum) @@ -3184,6 +3151,7 @@ void Client::SetLanguageSkill(int langid, int value) value = 100; //Max lang value m_pp.languages[langid] = value; + database.SaveCharacterLanguage(this->CharacterID(), langid, value); EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; diff --git a/zone/client.h b/zone/client.h index bab48e8ea..e33dcd755 100644 --- a/zone/client.h +++ b/zone/client.h @@ -234,7 +234,6 @@ public: bool KeyRingCheck(uint32 item_id); void KeyRingList(); virtual bool IsClient() const { return true; } - virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw); void CompleteConnect(); bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); @@ -654,14 +653,14 @@ public: void OnDisconnect(bool hard_disconnect); - uint16 GetSkillPoints() {return m_pp.points;} - void SetSkillPoints(int inp) {m_pp.points = inp;} + uint16 GetSkillPoints() { return m_pp.points;} + void SetSkillPoints(int inp) { m_pp.points = inp;} void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } void IncreaseLanguageSkill(int skill_id, int value = 1); - virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0)? m_pp.skills[skill_id]*(100 + itembonuses.skillmod[skill_id])/100 : m_pp.skills[skill_id]); } return 0; } + virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; } uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } - bool HasSkill(SkillUseTypes skill_id) const; + bool HasSkill(SkillUseTypes skill_id) const; bool CanHaveSkill(SkillUseTypes skill_id) const; void SetSkill(SkillUseTypes skill_num, uint16 value); void AddSkill(SkillUseTypes skillid, uint16 value); @@ -782,6 +781,7 @@ public: int16 acmod(); // Item methods + void EVENT_ITEM_ScriptStopReturn(); uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 87d884eb7..3b34878d5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -77,9 +77,6 @@ extern volatile bool ZoneLoaded; extern WorldServer worldserver; extern PetitionList petition_list; extern EntityList entity_list; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; - typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app); //Use a map for connecting opcodes since it dosent get used a lot and is sparse @@ -525,7 +522,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) client_state = CLIENT_KICKED; return; } - strcpy(name, cze->char_name); /* Check for Client Spoofing */ @@ -592,19 +588,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (LFG){ LFG = atoi(row[12]); } if (firstlogon){ firstlogon = atoi(row[15]); } } - + loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ + database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */ + database.LoadCharacterPotions(cid, &m_pp); /* Load Character Potion Belt */ database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */ database.LoadCharacterData(cid, &m_pp); /* Load Character Data from DB into PP */ - database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */ - database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency */ database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */ - database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ + database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */ database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */ database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */ database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ + database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ if (level){ level = m_pp.level; } @@ -612,9 +609,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (gmhideme) { trackable = false; } /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; - - // m_pp.zone_id = zone->GetZoneID(); - // m_pp.zoneInstance = zone->GetInstanceID(); /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; @@ -9168,38 +9162,6 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) return; } -void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { - Entity::DBAWComplete(workpt_b1, dbaw); - switch (workpt_b1) { - case DBA_b1_Entity_Client_Save: { - clock_t t = std::clock(); /* Function timer start */ - - char errbuf[MYSQL_ERRMSG_SIZE]; - uint32 affected_rows = 0; - DBAsyncQuery* dbaq = dbaw->PopAnswer(); - if (dbaq->GetAnswer(errbuf, 0, &affected_rows) && affected_rows == 1) { - if (dbaq->QPT()) { - SaveBackup(); - } - } - else { - std::cout << "Async client save failed. '" << errbuf << "'" << std::endl; - Message(13, "Error: Asyncronous save of your character failed."); - if (Admin() >= 200) - Message(13, "errbuf: %s", errbuf); - } - pQueuedSaveWorkID = 0; - - LogFile->write(EQEMuLog::Status, "Client::DBAWComplete Save Character Async done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); - break; - } - default: { - std::cout << "Error: Client::DBAWComplete(): Unknown workpt_b1" << std::endl; - break; - } - } -} - /* Finish client connecting state */ void Client::CompleteConnect() { UpdateWho(); @@ -9221,7 +9183,7 @@ void Client::CompleteConnect() { SendAppearancePacket(AT_GuildID, GuildID(), false); SendAppearancePacket(AT_GuildRank, GuildRank(), false); } - for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++) { + for (uint32 spellInt = 0; spellInt < MAX_PP_REF_SPELLBOOK; spellInt++) { if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000) m_pp.spell_book[spellInt] = 0xFFFFFFFF; } @@ -9417,7 +9379,7 @@ void Client::CompleteConnect() { SendWearChange(x); Mob *pet = GetPet(); if (pet != nullptr) { - for (x = 0; x < 8; x++) + for (x = 0; x < 8; x++) pet->SendWearChange(x); } @@ -9497,6 +9459,8 @@ void Client::CompleteConnect() { alternate_currency_loaded = true; ProcessAlternateCurrencyQueue(); + + CalcItemScale(); DoItemEnterZone(); @@ -10504,8 +10468,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) { } } -void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { - +void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { if(app->size != sizeof(MovePotionToBelt_Struct)) { LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_PotionBelt expected %i got %i", sizeof(MovePotionToBelt_Struct), app->size); @@ -10519,6 +10482,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { m_pp.potionbelt.items[mptbs->SlotNumber].item_id = BaseItem->ID; m_pp.potionbelt.items[mptbs->SlotNumber].icon = BaseItem->Icon; strn0cpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, BaseItem->Name, sizeof(BaseItem->Name)); + database.SaveCharacterPotionBelt(this->CharacterID(), mptbs->SlotNumber, m_pp.potionbelt.items[mptbs->SlotNumber].item_id, m_pp.potionbelt.items[mptbs->SlotNumber].icon); } } else { @@ -10526,9 +10490,6 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { m_pp.potionbelt.items[mptbs->SlotNumber].icon = 0; strncpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, "\0", 1); } - - Save(); - } void Client::Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app) { diff --git a/zone/client_process.cpp b/zone/client_process.cpp index fd8cb3740..4c9c8ca2d 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1717,6 +1717,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) } uint16 skilllevel = GetRawSkill(skill); + if(skilllevel == 0) { //this is a new skill.. uint16 t_level = SkillTrainLevel(skill, GetClass()); @@ -1726,7 +1727,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) } SetSkill(skill, t_level); - } else { + } else { switch(skill) { case SkillBrewing: case SkillMakePoison: diff --git a/zone/command.cpp b/zone/command.cpp index b1d195bf4..ea85fb9af 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -225,7 +225,6 @@ int command_init(void) { command_add("worldshutdown","- Shut down world and all zones",200,command_worldshutdown) || command_add("sendzonespawns","- Refresh spawn list for all clients in zone",150,command_sendzonespawns) || command_add("dbspawn2","[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table",100,command_dbspawn2) || - command_add("copychar","[character name] [new character] [new account id] - Create a copy of a character",100,command_copychar) || command_add("shutdown","- Shut this zone process down",150,command_shutdown) || command_add("delacct","[accountname] - Delete an account",150,command_delacct) || command_add("setpass","[accountname] [password] - Set local password for accountname",150,command_setpass) || @@ -2227,28 +2226,6 @@ void command_dbspawn2(Client *c, const Seperator *sep) } } -void command_copychar(Client *c, const Seperator *sep) -{ - if(sep->arg[1][0]==0 || sep->arg[2][0] == 0 || sep->arg[3][0] == 0) - c->Message(0, "Usage: #copychar [character name] [new character] [new account id]"); - //CheckUsedName.... TRUE=No Char, FALSE=Char/Error - //If there is no source... - else if (database.CheckUsedName((char*)sep->arg[1])) { - c->Message(0, "Source character not found!"); - } - else { - //If there is a name is not used.... - if (database.CheckUsedName((char*) sep->arg[2])) { - if (!database.CopyCharacter((char*) sep->arg[1], (char*) sep->arg[2], atoi(sep->arg[3]))) - c->Message(0, "Character copy operation failed!"); - else - c->Message(0, "Character copy complete."); - } - else - c->Message(0, "Target character already exists!"); - } -} - void command_shutdown(Client *c, const Seperator *sep) { CatchSignal(2); @@ -2423,8 +2400,8 @@ void command_showskills(Client *c, const Seperator *sep) c->Message(0, "Skills for %s", t->GetName()); for (SkillUseTypes i=Skill1HBlunt; i <= HIGHEST_SKILL; i=(SkillUseTypes)(i+1)) - c->Message(0, "Skill [%d] is at [%d]", i, t->GetSkill(i)); -} + c->Message(0, "Skill [%d] is at [%d] - %u", i, t->GetSkill(i), t->GetRawSkill(i)); +} void command_findspell(Client *c, const Seperator *sep) { @@ -2801,7 +2778,7 @@ void command_charbackup(Client *c, const Seperator *sep) if (sep->IsNumber(2)) charid = atoi(sep->arg[2]); else - database.GetAccountIDByChar(sep->arg[2], &charid); + database.GetAccountIDByChar(sep->arg[2]); if (charid) { if (database.RunQuery(query, MakeAnyLenString(&query, "Select id, backupreason, charid, account_id, zoneid, DATE_FORMAT(ts, '%%m/%%d/%%Y %%H:%%i:%%s') " @@ -2828,7 +2805,7 @@ void command_charbackup(Client *c, const Seperator *sep) if (sep->IsNumber(2)) charid = atoi(sep->arg[2]); else - database.GetAccountIDByChar(sep->arg[2], &charid); + database.GetAccountIDByChar(sep->arg[2]); if (charid && sep->IsNumber(3)) { uint32 cbid = atoi(sep->arg[3]); @@ -8725,6 +8702,7 @@ void command_traindisc(Client *c, const Seperator *sep) break; //continue the 1st loop } else if(t->GetPP().disciplines.values[r] == 0) { t->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(c->CharacterID(), r, curspell); t->SendDisciplineUpdate(); t->Message(0, "You have learned a new discipline!"); count++; //success counter diff --git a/zone/command.h b/zone/command.h index 6a880625e..ef7302c51 100644 --- a/zone/command.h +++ b/zone/command.h @@ -125,7 +125,6 @@ void command_worldshutdown(Client *c, const Seperator *sep); void command_sendzonespawns(Client *c, const Seperator *sep); void command_zsave(Client *c, const Seperator *sep); void command_dbspawn2(Client *c, const Seperator *sep); -void command_copychar(Client *c, const Seperator *sep); void command_shutdown(Client *c, const Seperator *sep); void command_delacct(Client *c, const Seperator *sep); void command_setpass(Client *c, const Seperator *sep); diff --git a/zone/effects.cpp b/zone/effects.cpp index 5e07d5f9a..10748c0e1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -606,6 +606,7 @@ bool Client::TrainDiscipline(uint32 itemid) { return(false); } else if(m_pp.disciplines.values[r] == 0) { m_pp.disciplines.values[r] = spell_id; + database.SaveCharacterDisc(this->CharacterID(), r, spell_id); SendDisciplineUpdate(); Message(0, "You have learned a new discipline!"); return(true); diff --git a/zone/entity.cpp b/zone/entity.cpp index 2ca3f640d..b59822d73 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -40,7 +40,6 @@ #include "../common/spdat.h" #include "../common/features.h" #include "string_ids.h" -#include "../common/dbasync.h" #include "guild_mgr.h" #include "raids.h" #include "quest_parser_collection.h" @@ -57,7 +56,6 @@ extern WorldServer worldserver; extern NetConnection net; extern uint32 numclients; extern PetitionList petition_list; -extern DBAsync *dbasync; extern char errorname[32]; extern uint16 adverrornum; @@ -65,12 +63,11 @@ extern uint16 adverrornum; Entity::Entity() { id = 0; - pDBAsyncWorkID = 0; } Entity::~Entity() { - dbasync->CancelWork(pDBAsyncWorkID); + } Client *Entity::CastToClient() diff --git a/zone/entity.h b/zone/entity.h index cc302fe75..9599aa7fc 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -28,7 +28,6 @@ #include "zonedb.h" #include "zonedump.h" -#include "zonedbasync.h" #include "qglobals.h" class EQApplicationPacket; @@ -53,7 +52,7 @@ class Bot; class BotRaids; #endif -extern EntityList entity_list; +extern EntityList entity_list; class Entity { @@ -100,7 +99,6 @@ public: inline const uint16& GetID() const { return id; } virtual const char* GetName() { return ""; } - virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; } bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1); #ifdef BOTS diff --git a/zone/exp.cpp b/zone/exp.cpp index 9415022ca..a82aa25d9 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -51,14 +51,7 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level) void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); + this->EVENT_ITEM_ScriptStopReturn(); uint32 add_exp = in_add_exp; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 02cf6e568..69570faf2 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -200,14 +200,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) { } bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) { - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Recieved_Item", buffer); + this->EVENT_ITEM_ScriptStopReturn(); // TODO: update calling methods and script apis to handle a failure return @@ -2320,10 +2313,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { _log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name); strcpy(m_pp.bandoliers[bs->number].name, bs->name); - const ItemInst* InvItem; - - const Item_Struct *BaseItem; - + const ItemInst* InvItem; + const Item_Struct *BaseItem; int16 WeaponSlot; for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) { @@ -2334,6 +2325,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { _log(INVENTORY__BANDOLIER, "Char: %s adding item %s to slot %i", GetName(),BaseItem->Name, WeaponSlot); m_pp.bandoliers[bs->number].items[BandolierSlot].item_id = BaseItem->ID; m_pp.bandoliers[bs->number].items[BandolierSlot].icon = BaseItem->Icon; + database.SaveCharacterBandolier(this->CharacterID(), bs->number, BandolierSlot, m_pp.bandoliers[bs->number].items[BandolierSlot].item_id, m_pp.bandoliers[bs->number].items[BandolierSlot].icon, bs->name); } else { _log(INVENTORY__BANDOLIER, "Char: %s no item in slot %i", GetName(), WeaponSlot); @@ -2341,21 +2333,17 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { m_pp.bandoliers[bs->number].items[BandolierSlot].icon = 0; } } - Save(); } void Client::RemoveBandolier(const EQApplicationPacket *app) { - - // Delete bandolier with the specified number - BandolierDelete_Struct *bds = (BandolierDelete_Struct*)app->pBuffer; _log(INVENTORY__BANDOLIER, "Char: %s removing set", GetName(), bds->number); memset(m_pp.bandoliers[bds->number].name, 0, 32); for(int i = bandolierMainHand; i <= bandolierAmmo; i++) { m_pp.bandoliers[bds->number].items[i].item_id = 0; - m_pp.bandoliers[bds->number].items[i].icon = 0; + m_pp.bandoliers[bds->number].items[i].icon = 0; } - Save(); + database.DeleteCharacterBandolier(this->CharacterID(), bds->number); } void Client::SetBandolier(const EQApplicationPacket *app) { diff --git a/zone/net.cpp b/zone/net.cpp index 8a8421786..498ed5102 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -97,8 +97,6 @@ extern Zone* zone; EQStreamFactory eqsf(ZoneStream); npcDecayTimes_Struct npcCorpseDecayTimes[100]; TitleManager title_manager; -DBAsyncFinishedQueue MTdbafq; -DBAsync *dbasync = nullptr; QueryServ *QServ = 0; TaskManager *taskmanager = 0; QuestParserCollection *parse = 0; @@ -168,8 +166,6 @@ int main(int argc, char** argv) { _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); return 1; } - dbasync = new DBAsync(&database); - dbasync->AddFQ(&MTdbafq); guild_mgr.SetDatabase(&database); GuildBanks = nullptr; @@ -444,10 +440,6 @@ int main(int argc, char** argv) { } } - DBAsyncWork* dbaw = 0; - while ((dbaw = MTdbafq.Pop())) { - DispatchFinishedDBAsync(dbaw); - } if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); @@ -507,8 +499,6 @@ int main(int argc, char** argv) { //Fix for Linux world server problem. eqsf.Close(); worldserver.Disconnect(); - dbasync->CommitWrites(); - dbasync->StopThread(); safe_delete(taskmanager); command_deinit(); safe_delete(parse); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fc31178ae..776376bdf 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -974,6 +974,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID); if (SpellGlobalCheckResult) { initiator->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(Char_ID, r, curspell); initiator->SendDisciplineUpdate(); initiator->Message(0, "You have learned a new discipline!"); count++; //success counter @@ -981,11 +982,12 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { break; //continue the 1st loop } else { - initiator->GetPP().disciplines.values[r] = curspell; - initiator->SendDisciplineUpdate(); - initiator->Message(0, "You have learned a new discipline!"); - count++; //success counter - break; //continue the 1st loop + initiator->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(Char_ID, r, curspell); + initiator->SendDisciplineUpdate(); + initiator->Message(0, "You have learned a new discipline!"); + count++; //success counter + break; //continue the 1st loop } } //if we get to this point, there's already a discipline in this slot, so we skip it } diff --git a/zone/spells.cpp b/zone/spells.cpp index 94921c685..1f37a21e4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4933,8 +4933,9 @@ void Client::UntrainDisc(int slot, bool update_client) if(slot >= MAX_PP_DISCIPLINES || slot < 0) return; - mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot); + mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot); m_pp.disciplines.values[slot] = 0; + database.DeleteCharacterDisc(this->CharacterID(), slot); if(update_client) { diff --git a/zone/trading.cpp b/zone/trading.cpp index 23d8d77af..414b397fc 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -913,14 +913,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(!tradingWith->IsMoving()) tradingWith->FaceTarget(this); - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); + this->EVENT_ITEM_ScriptStopReturn(); } } @@ -938,7 +931,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st parse->AddVar(temp1, temp2); snprintf(temp1, 100, "platinum.%d", tradingWith->GetNPCTypeID()); snprintf(temp2, 100, "%u", trade->pp); - parse->AddVar(temp1, temp2); + parse->AddVar(temp1, temp2); if(tradingWith->GetAppearance() != eaDead) { tradingWith->FaceTarget(this); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 95da9b5a3..08bbf4662 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -254,8 +254,10 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { return(0); } - //make sure they have enough of them - //and remove it from inventory + /* + Make sure they have enough of them + and remove it from inventory + */ if(inst->IsStackable()) { if(inst->GetCharges() < (int32)quantity) //dont have enough.... return(0); @@ -267,7 +269,7 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { pts *= quantity; - //add the tribute value in points + /* Add the tribute value in points */ AddTributePoints(pts); return(pts); } @@ -279,7 +281,7 @@ int32 Client::TributeMoney(uint32 platinum) { return(0); } - //add the tribute value in points + /* Add the tribute value in points */ AddTributePoints(platinum); return(platinum); } diff --git a/zone/zone.cpp b/zone/zone.cpp index a9c63b22f..9ae17381d 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -77,8 +77,6 @@ extern bool staticzone; Zone* zone = 0; volatile bool ZoneLoaded = false; extern QuestParserCollection* parse; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { const char* zonename = database.GetZoneName(iZoneID); @@ -705,7 +703,6 @@ void Zone::Shutdown(bool quite) zone->ResetAuth(); safe_delete(zone); - dbasync->CommitWrites(); entity_list.ClearAreas(); parse->ReloadQuests(true); UpdateWindowTitle(); @@ -844,8 +841,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) } Zone::~Zone() { - if(pQueuedMerchantsWorkID != 0) - dbasync->CancelWork(pQueuedMerchantsWorkID); spawn2_list.Clear(); safe_delete(zonemap); safe_delete(watermap); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 794b1240f..77e5739ee 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -626,8 +626,7 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ return loadti; } -ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { - +ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; MYSQL_RES *result; @@ -687,8 +686,7 @@ void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNum safe_delete_array(query); } -void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { - +void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { _log(TRADING__CLIENT, "ZoneDatabase::UpdateTraderItemCharges(%i, %i, %i)", CharID, SerialNumber, Charges); char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -784,8 +782,7 @@ void ZoneDatabase::DeleteBuyLines(uint32 CharID){ safe_delete_array(query); } -void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { - +void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; if (!(RunQuery(query,MakeAnyLenString(&query, "replace INTO buyer VALUES(%i,%i, %i,\"%s\",%i,%i)", @@ -795,8 +792,7 @@ void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, cons safe_delete_array(query); } -void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { - +void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -806,8 +802,7 @@ void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { safe_delete_array(query); } -void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) { - +void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) { if(Quantity <= 0) { RemoveBuyLine(CharID, BuySlot); return; @@ -1016,7 +1011,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* } bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) { - std::string query = StringFormat("SELECT faction_id,current_value FROM faction_values WHERE char_id = %i", character_id); + std::string query = StringFormat("SELECT `faction_id`, `current_value` FROM `faction_values` WHERE `char_id` = %i", character_id); auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } return true; @@ -1055,8 +1050,12 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str "`value` " "FROM " "`character_languages` " - "WHERE `id` = %u ORDER BY `language_id`", character_id); + "WHERE `id` = %u ORDER BY `lang_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; + /* Initialize Languages */ + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + pp->languages[i] = 0; + } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); } return true; } @@ -1069,8 +1068,8 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S "`character_disciplines`" "WHERE `id` = %u ORDER BY `disc_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } - return true; + for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } + return true; } bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp){ @@ -1081,7 +1080,11 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct "FROM " "`character_skills` " "WHERE `id` = %u ORDER BY `skill_id`", character_id); - auto results = database.QueryDatabase(query); int i = 0; + auto results = database.QueryDatabase(query); int i = 0; + /* Initialize Skill */ + for (i = 0; i < MAX_PP_SKILL; i++){ + pp->skills[i] = 0; + } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->skills[i] = atoi(row[1]); } return true; } @@ -1131,44 +1134,162 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru return true; } +bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id); + auto results = database.QueryDatabase(query); int i = 0; int r = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + r = 0; + i = atoi(row[r]); /* Slot */ r++; + pp->item_tint[i].rgb.blue = atoi(row[r]); r++; + pp->item_tint[i].rgb.green = atoi(row[r]); r++; + pp->item_tint[i].rgb.red = atoi(row[r]); r++; + pp->item_tint[i].rgb.use_tint = atoi(row[r]); + } + return true; +} + +bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT 16", character_id); + auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0; + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + pp->bandoliers[i].items[si].icon = 0; + } + } + + for (auto row = results.begin(); row != results.end(); ++row) { + r = 0; + i = atoi(row[r]); /* Bandolier ID */ r++; + si = atoi(row[r]); /* Bandolier Slot */ r++; + pp->bandoliers[i].items[si].item_id = atoi(row[r]); r++; + pp->bandoliers[i].items[si].icon = atoi(row[r]); r++; + strcpy(pp->bandoliers[i].name, row[r]); r++; + si++; + } + return true; +} + +bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + pp->tributes[i].tribute = 0; + pp->tributes[i].tier = 0; + } + for (auto row = results.begin(); row != results.end(); ++row) { + pp->tributes[i].tier = atoi(row[0]); + pp->tributes[i].tribute = atoi(row[1]); + } + return true; +} + +bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT 4", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ + pp->potionbelt.items[i].icon = 0; + pp->potionbelt.items[i].item_id = 0; + strncpy(pp->potionbelt.items[i].item_name, "\0", 1); + } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); /* Potion belt slot number */ + pp->potionbelt.items[i].item_id = atoi(row[1]); + pp->potionbelt.items[i].icon = atoi(row[2]); + } + return true; +} + bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat("SELECT id, zone_id, instance_id, x, y, z, heading FROM character_bind_home WHERE `id` = %u", character_id); + std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z, heading, is_home FROM character_bind WHERE `id` = %u LIMIT 2", character_id); auto results = database.QueryDatabase(query); int i = 0; for (auto row = results.begin(); row != results.end(); ++row) { - pp->binds[4].zoneId = atoi(row[i]); i++; - i++; /* Instance ID can go here eventually */ - pp->binds[4].x = atoi(row[i]); i++; - pp->binds[4].y = atoi(row[i]); i++; - pp->binds[4].z = atoi(row[i]); i++; - pp->binds[4].heading = atoi(row[i]); i++; + i = 0; + /* Is home bind */ + if (atoi(row[6]) == 1){ + pp->binds[4].zoneId = atoi(row[i]); i++; + i++; /* Instance ID can go here eventually */ + pp->binds[4].x = atoi(row[i]); i++; + pp->binds[4].y = atoi(row[i]); i++; + pp->binds[4].z = atoi(row[i]); i++; + pp->binds[4].heading = atoi(row[i]); i++; + } + /* Is regular bind point */ + else{ + pp->binds[0].zoneId = atoi(row[i]); i++; + i++; /* Instance ID can go here eventually */ + pp->binds[0].x = atoi(row[i]); i++; + pp->binds[0].y = atoi(row[i]); i++; + pp->binds[0].z = atoi(row[i]); i++; + pp->binds[0].heading = atoi(row[i]); i++; + } } return true; } +bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value){ + std::string query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, lang_id, value); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterLanguage for character ID: %i, lang_id:%u value:%u done", character_id, lang_id, value); + return true; +} + +bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home){ + /* Save Home Bind Point */ + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, x, y, z, heading, is_home); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home); + auto results = QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + return true; +} + bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){ std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", character_id, slot_id, color); QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color); return true; } -bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id); - auto results = database.QueryDatabase(query); int i = 0; int r = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - r = 0; - i = atoi(row[r]); /* Slot */ r++; - pp->item_tint[i].rgb.blue = atoi(row[r]); r++; - pp->item_tint[i].rgb.green = atoi(row[r]); r++; - pp->item_tint[i].rgb.red = atoi(row[r]); r++; - pp->item_tint[i].rgb.use_tint = atoi(row[r]); - printf("Material Load: %u %u %u %u\n", pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint); +bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value){ + std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value); + return true; +} + +bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){ + std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u value:%u done", character_id, slot_id, disc_id); + return true; +} + +bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); + /* Save Tributes only if we have values... */ + for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != UINT32_MAX){ + std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + } } return true; } +bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name){ + char bandolier_name_esc[64]; + DoEscapeString(bandolier_name_esc, bandolier_name, strlen(bandolier_name)); + std::string query = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%u, %u, %u, %u, %u,'%s')", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name_esc); + auto results = QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name); + if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + return true; +} + +bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon) { + std::string query = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%u, %u, %u, %u)", character_id, potion_id, item_id, icon); + auto results = QueryDatabase(query); + if (!results.RowsAffected()){ std::cout << "ERROR Potionbelt Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + return true; +} + bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){ clock_t t = std::clock(); /* Function timer start */ - if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } std::string query = StringFormat( "REPLACE INTO `character_data` (" " id, " @@ -1352,97 +1473,97 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " "%u" // RestTimer pp->RestTimer, " RestTimer) " - ")", - character_id, - account_id, - pp->name, - pp->last_name, - pp->gender, - pp->race, - pp->class_, - pp->level, - pp->deity, - pp->birthday, - pp->lastlogin, - pp->timePlayedMin, - pp->pvp, - pp->level2, - pp->anon, - pp->gm, - pp->intoxication, - pp->haircolor, - pp->beardcolor, - pp->eyecolor1, - pp->eyecolor2, - pp->hairstyle, - pp->beard, - pp->ability_time_seconds, - pp->ability_number, - pp->ability_time_minutes, - pp->ability_time_hours, - pp->title, - pp->suffix, - pp->exp, - pp->points, - pp->mana, - pp->cur_hp, - pp->STR, - pp->STA, - pp->CHA, - pp->DEX, - pp->INT, - pp->AGI, - pp->WIS, - pp->face, - pp->y, - pp->x, - pp->z, - pp->heading, - pp->pvp2, - pp->pvptype, - pp->autosplit, - pp->zone_change_count, - pp->drakkin_heritage, - pp->drakkin_tattoo, - pp->drakkin_details, - pp->toxicity, - pp->hunger_level, - pp->thirst_level, - pp->ability_up, - pp->zone_id, - pp->zoneInstance, - pp->leadAAActive, - pp->ldon_points_guk, - pp->ldon_points_mir, - pp->ldon_points_mmc, - pp->ldon_points_ruj, - pp->ldon_points_tak, - pp->ldon_points_available, - pp->tribute_time_remaining, - pp->showhelm, - pp->career_tribute_points, - pp->tribute_points, - pp->tribute_active, - pp->endurance, - pp->group_leadership_exp, - pp->raid_leadership_exp, - pp->group_leadership_points, - pp->raid_leadership_points, - pp->air_remaining, - pp->PVPKills, - pp->PVPDeaths, - pp->PVPCurrentPoints, - pp->PVPCareerPoints, - pp->PVPBestKillStreak, - pp->PVPWorstDeathStreak, - pp->PVPCurrentKillStreak, - pp->aapoints_spent, - pp->expAA, - pp->aapoints, - pp->groupAutoconsent, - pp->raidAutoconsent, - pp->guildAutoconsent, - pp->RestTimer + ")", + character_id, // " id, " + account_id, // " account_id, " + pp->name, // " `name`, " + pp->last_name, // " last_name, " + pp->gender, // " gender, " + pp->race, // " race, " + pp->class_, // " class, " + pp->level, // " `level`, " + pp->deity, // " deity, " + pp->birthday, // " birthday, " + pp->lastlogin, // " last_login, " + pp->timePlayedMin, // " time_played, " + pp->pvp, // " pvp_status, " + pp->level2, // " level2, " + pp->anon, // " anon, " + pp->gm, // " gm, " + pp->intoxication, // " intoxication, " + pp->haircolor, // " hair_color, " + pp->beardcolor, // " beard_color, " + pp->eyecolor1, // " eye_color_1, " + pp->eyecolor2, // " eye_color_2, " + pp->hairstyle, // " hair_style, " + pp->beard, // " beard, " + pp->ability_time_seconds, // " ability_time_seconds, " + pp->ability_number, // " ability_number, " + pp->ability_time_minutes, // " ability_time_minutes, " + pp->ability_time_hours, // " ability_time_hours, " + pp->title, // " title, " + pp->suffix, // " suffix, " + pp->exp, // " exp, " + pp->points, // " points, " + pp->mana, // " mana, " + pp->cur_hp, // " cur_hp, " + pp->STR, // " str, " + pp->STA, // " sta, " + pp->CHA, // " cha, " + pp->DEX, // " dex, " + pp->INT, // " `int`, " + pp->AGI, // " agi, " + pp->WIS, // " wis, " + pp->face, // " face, " + pp->y, // " y, " + pp->x, // " x, " + pp->z, // " z, " + pp->heading, // " heading, " + pp->pvp2, // " pvp2, " + pp->pvptype, // " pvp_type, " + pp->autosplit, // " autosplit_enabled, " + pp->zone_change_count, // " zone_change_count, " + pp->drakkin_heritage, // " drakkin_heritage, " + pp->drakkin_tattoo, // " drakkin_tattoo, " + pp->drakkin_details, // " drakkin_details, " + pp->toxicity, // " toxicity, " + pp->hunger_level, // " hunger_level, " + pp->thirst_level, // " thirst_level, " + pp->ability_up, // " ability_up, " + pp->zone_id, // " zone_id, " + pp->zoneInstance, // " zone_instance, " + pp->leadAAActive, // " leadership_exp_on, " + pp->ldon_points_guk, // " ldon_points_guk, " + pp->ldon_points_mir, // " ldon_points_mir, " + pp->ldon_points_mmc, // " ldon_points_mmc, " + pp->ldon_points_ruj, // " ldon_points_ruj, " + pp->ldon_points_tak, // " ldon_points_tak, " + pp->ldon_points_available, // " ldon_points_available, " + pp->tribute_time_remaining, // " tribute_time_remaining, " + pp->showhelm, // " show_helm, " + pp->career_tribute_points, // " career_tribute_points, " + pp->tribute_points, // " tribute_points, " + pp->tribute_active, // " tribute_active, " + pp->endurance, // " endurance, " + pp->group_leadership_exp, // " group_leadership_exp, " + pp->raid_leadership_exp, // " raid_leadership_exp, " + pp->group_leadership_points, // " group_leadership_points, " + pp->raid_leadership_points, // " raid_leadership_points, " + pp->air_remaining, // " air_remaining, " + pp->PVPKills, // " pvp_kills, " + pp->PVPDeaths, // " pvp_deaths, " + pp->PVPCurrentPoints, // " pvp_current_points, " + pp->PVPCareerPoints, // " pvp_career_points, " + pp->PVPBestKillStreak, // " pvp_best_kill_streak, " + pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, " + pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, " + pp->aapoints_spent, // " aa_points_spent, " + pp->expAA, // " aa_exp, " + pp->aapoints, // " aa_points, " + pp->groupAutoconsent, // " group_auto_consent, " + pp->raidAutoconsent, // " raid_auto_consent, " + pp->guildAutoconsent, // " guild_auto_consent, " + pp->RestTimer // " RestTimer) " ); auto results = database.QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } @@ -1459,6 +1580,10 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru if (pp->silver_bank < 0) { pp->silver_bank = 0; } if (pp->gold_bank < 0) { pp->gold_bank = 0; } if (pp->platinum_bank < 0) { pp->platinum_bank = 0; } + if (pp->platinum_cursor < 0) { pp->platinum_cursor = 0; } + if (pp->gold_cursor < 0) { pp->gold_cursor = 0; } + if (pp->silver_cursor < 0) { pp->silver_cursor = 0; } + if (pp->copper_cursor < 0) { pp->copper_cursor = 0; } std::string query = StringFormat( "REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," "platinum_bank, gold_bank, silver_bank, copper_bank," @@ -1499,12 +1624,16 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur bool ZoneDatabase::SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot){ std::string rquery = StringFormat("UPDATE `character_spells` SET `slot_id` = %u WHERE `slot_id` = %u AND `id` = %u", to_slot, from_slot, character_id); - clock_t t = std::clock(); /* Function timer start */ + clock_t t = std::clock(); /* Function timer start */ auto results = QueryDatabase(rquery); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSpellSwap for character ID: %u, from_slot: %u to_slot: %u spell: %u time: %f seconds", character_id, from_slot, to_slot, spell_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } +bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +} + bool ZoneDatabase::SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ std::string query = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; } @@ -1513,8 +1642,12 @@ bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 spell_id, ui std::string query = StringFormat("DELETE FROM `character_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; } -bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ - std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +bool ZoneDatabase::DeleteCharacterDisc(uint32 character_id, uint32 slot_id){ + std::string query = StringFormat("DELETE FROM `character_disciplines` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::DeleteCharacterBandolier(uint32 character_id, uint32 band_id){ + std::string query = StringFormat("DELETE FROM `character_bandolier` WHERE `bandolier_id` = %u AND `id` = %u", band_id, character_id); QueryDatabase(query); return true; } bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ @@ -1715,7 +1848,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->aggroradius = (int32)atoi(row[r++]); // set defaultvalue for aggroradius if (tmpNPCType->aggroradius <= 0) - tmpNPCType->aggroradius = 70; + tmpNPCType->aggroradius = 70; tmpNPCType->assistradius = (int32)atoi(row[r++]); if (tmpNPCType->assistradius <= 0) tmpNPCType->assistradius = tmpNPCType->aggroradius; @@ -3715,4 +3848,6 @@ void ZoneDatabase::StoreCharacterLookup(uint32 char_id) { " FROM `character_` " " WHERE `id` = %i ", char_id); QueryDatabase(c_lookup); -} \ No newline at end of file +} + + diff --git a/zone/zonedb.h b/zone/zonedb.h index 705377a39..659dad673 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -6,6 +6,7 @@ #include "../common/loottable.h" #include "zonedump.h" #include "../common/faction.h" +#include //#include "doors.h" struct wplist { @@ -212,9 +213,7 @@ public: ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); virtual ~ZoneDatabase(); - /* - * Objects and World Containers - */ + /* Objects and World Containers */ void LoadWorldContainer(uint32 parentid, ItemInst* container); void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container); void DeleteWorldContainer(uint32 parent_id,uint32 zone_id); @@ -223,10 +222,7 @@ public: void DeleteObject(uint32 id); Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs); - /* - * Traders - */ - + /* Traders */ void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot); void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges); void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice); @@ -236,16 +232,13 @@ public: Trader_Struct* LoadTraderItem(uint32 char_id); TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id); - // Buyer/Barter - // + /* Buyer/Barter */ void AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char *ItemName, uint32 Quantity, uint32 Price); void RemoveBuyLine(uint32 CharID, uint32 BuySlot); void DeleteBuyLines(uint32 CharID); void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity); - /* - * General Character Related Stuff - */ + /* General Character Related Stuff */ void StoreCharacterLookup(uint32 char_id); bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs); uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs); @@ -267,28 +260,36 @@ public: bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ - bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); - bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); - bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); - bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot); - bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); + bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); + bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot); + bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); + bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); + bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); + bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); + bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); + bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); /* Character Data Deletes */ - bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); + bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); - /* - * Character Inventory - */ + /* Character Inventory */ bool NoRentExpired(const char* name); - /* - * Corpses - */ + /* Corpses */ bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes); uint32 CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); bool CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); @@ -314,9 +315,7 @@ public: uint32 GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid); uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type); - /* - * Faction - */ + /* Faction */ bool GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction = 0); bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id); //rembrant, needed for factions Dec, 16 2001 bool GetFactionName(int32 faction_id, char* name, uint32 buflen); // rembrant, needed for factions Dec, 16 2001 @@ -324,9 +323,7 @@ public: bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001 bool LoadFactionData(); - /* - * AAs - */ + /* AAs */ bool LoadAAEffects(); bool LoadAAEffects2(); bool LoadSwarmSpells(); @@ -338,9 +335,7 @@ public: uint32 CountAAEffects(); void FillAAEffects(SendAA_Struct* aa_struct); - /* - * Zone related - */ + /* Zone related */ bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename); bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd); bool LoadStaticZonePoints(LinkedList* zone_point_list,const char* zonename, uint32 version); @@ -348,9 +343,7 @@ public: uint8 GetUseCFGSafeCoords(); int getZoneShutDownDelay(uint32 zoneID, uint32 version); - /* - * Spawns and Spawn Points - */ + /* Spawns and Spawn Points */ bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list); bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list); bool PopulateZoneSpawnList(uint32 zoneid, LinkedList &spawn2_list, int16 version, uint32 repopdelay = 0); @@ -360,9 +353,7 @@ public: uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id); void UpdateSpawn2Status(uint32 id, uint8 new_status); - /* - * Grids/Paths - */ + /* Grids/Paths */ uint32 GetFreeGrid(uint16 zoneid); void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too,uint16 zoneid); void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num,uint16 zoneid); @@ -378,9 +369,7 @@ public: int GetHighestGrid(uint32 zoneid); int GetHighestWaypoint(uint32 zoneid, uint32 gridid); - /* - * NPCs - */ + /* NPCs */ const NPCType* GetNPCType(uint32 id); uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete bool SetSpecialAttkFlag(uint8 id, const char* flag); @@ -394,9 +383,7 @@ public: DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID); DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID); - /* - * Mercs - */ + /* Mercs */ const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel); void LoadMercEquipment(Merc *merc); void SaveMercBuffs(Merc *merc); @@ -408,9 +395,7 @@ public: //void LoadMercTypesForMercMerchant(NPC *merchant); //void LoadMercsForMercMerchant(NPC *merchant); - /* - * Petitions - */ + /* Petitions */ void UpdateBug(BugStruct* bug); void UpdateBug(PetitionBug_Struct* bug); void DeletePetitionFromDB(Petition* wpet); @@ -418,16 +403,11 @@ public: void InsertPetitionToDB(Petition* wpet); void RefreshPetitionsFromDB(); - - /* - * Merchants - */ + /* Merchants */ void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges); void DeleteMerchantTemp(uint32 npcid, uint32 slot); - /* - * Tradeskills - */ + /* Tradeskills */ bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */ @@ -436,14 +416,10 @@ public: bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); - /* - * Tribute - */ + /* Tribute */ bool LoadTributes(); - /* - * Doors - */ + /* Doors */ bool DoorIsOpen(uint8 door_id,const char* zone_name); void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name); bool LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version); @@ -456,64 +432,46 @@ public: int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version); void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize); - /* - * Blocked Spells - */ - + /* Blocked Spells */ int32 GetBlockedSpellsCount(uint32 zoneid); bool LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid); - /* - * Traps - */ + /* Traps */ bool LoadTraps(const char* zonename, int16 version); char* GetTrapMessage(uint32 trap_id); - /* - * Time - */ + /* Time */ uint32 GetZoneTZ(uint32 zoneid, uint32 version); bool SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz); - /* - * Group - */ + /* Group */ void RefreshGroupFromDB(Client *c); uint8 GroupCount(uint32 groupid); - /* - * Raid - */ + + /* Raid */ uint8 RaidGroupCount(uint32 raidid, uint32 groupid); - /* - * Instancing - */ + /* Instancing */ void ListAllInstances(Client* c, uint32 charid); - /* - * QGlobals - */ + /* QGlobals */ void QGlobalPurge(); - /* - * Alternate Currency - */ + /* Alternate Currency */ void LoadAltCurrencyValues(uint32 char_id, std::map ¤cy); void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value); /* - * Misc stuff. - * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD - * REALLY HAS NO BETTER SECTION + * Misc stuff. + * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD + * REALLY HAS NO BETTER SECTION */ bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid); void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0); uint32 GetKarma(uint32 acct_id); void UpdateKarma(uint32 acct_id, uint32 amount); - /* - * Things which really dont belong here... - */ + /* Things which really dont belong here... */ int16 CommandRequirement(const char* commandname); protected: diff --git a/zone/zonedbasync.cpp b/zone/zonedbasync.cpp deleted file mode 100644 index 454252ab6..000000000 --- a/zone/zonedbasync.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "../common/debug.h" -#include -#include "entity.h" -#include "masterentity.h" -#include "../common/string_util.h" -#include "../common/breakdowns.h" -#include - -extern EntityList entity_list; - -void DispatchFinishedDBAsync(DBAsyncWork* dbaw) { - uint32_breakdown workpt; - workpt = dbaw->WPT(); - switch (workpt.b4()) { - case DBA_b4_Entity: { - Entity* entity = entity_list.GetID(workpt.w2_3()); - if (!entity) - break; - entity->DBAWComplete(workpt.b1(), dbaw); - break; - } - default: { - std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4: " << (int) workpt.b4() << ", workpt=" << workpt << std::endl; - break; - } - } - safe_delete(dbaw); -} - -#define MAX_TO_DELETE 10 -#define MAX_BACKUPS 5 -bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork) { // return true means delete data - char errbuf[MYSQL_ERRMSG_SIZE] = "dbaq == 0"; - MYSQL_RES* result = 0; - MYSQL_ROW row; - char* query = 0; - uint32 i; - uint8 ToDeleteIndex = 0; - uint32 ToDelete[MAX_TO_DELETE]; - memset(ToDelete, 0, sizeof(ToDelete)); - - uint32 BackupAges[MAX_BACKUPS]; // must be sorted, highest value in lowest index - memset(BackupAges, 0, sizeof(BackupAges)); - - bool FoundBackup[MAX_BACKUPS]; - memset(FoundBackup, 0, sizeof(FoundBackup)); - - BackupAges[0] = 86400; - BackupAges[1] = 3600; - - DBAsyncQuery* dbaq = iWork->PopAnswer(); - if (dbaq && dbaq->GetAnswer(errbuf, &result)) { - while ((row = mysql_fetch_row(result))) { - for (i=0; i BackupAges[i]) - i = MAX_BACKUPS; - else if (!FoundBackup[i]) { - FoundBackup[i] = true; - break; - } - } - if (i >= MAX_BACKUPS) - ToDelete[ToDeleteIndex++] = atoi(row[0]); - if (ToDeleteIndex >= MAX_TO_DELETE) - break; - } - if (ToDelete[0]) { - uint32 len = 0, size = 0; - AppendAnyLenString(&query, &size, &len, "Delete from character_backup where id=%u", ToDelete[0]); - for (uint8 i=1; iwrite(EQEMuLog::Error, "Error in DBAsyncCB_CharacterBackup query2 '%s' %s", query, errbuf); - safe_delete_array(query); - return true; - } - safe_delete_array(query); - } - bool needtoinsert = false; - for (i=0; iWPT()), errbuf)) { - std::cout << "Error in DBAsyncCB_CharacterBackup query3 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return true; - } - safe_delete_array(query); - } - } - else { -// std::cout << "Error in DBAsyncCB_CharacterBackup query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return true; - } - return true; -} diff --git a/zone/zonedbasync.h b/zone/zonedbasync.h deleted file mode 100644 index b91389322..000000000 --- a/zone/zonedbasync.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ZONEDBASYNC_H -#define ZONEDBASYNC_H - -#include "../common/dbasync.h" -void DispatchFinishedDBAsync(DBAsyncWork* iDBAW); -bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork); - -#define DBA_b4_Main 1 -#define DBA_b4_Worldserver 2 -#define DBA_b4_Zone 3 -#define DBA_b4_Entity 4 - -#define DBA_b1_Entity_SeeQPT 0 -#define DBA_b1_Entity_Client_InfoForLogin 1 -#define DBA_b1_Entity_Client_Save 2 -#define DBA_b1_Entity_Client_Backup 3 -#define DBA_b1_Entity_Corpse_Backup 4 -#define DBA_b1_Zone_MerchantLists 5 -#define DBA_b1_Zone_MerchantListsTemp 6 - -#endif - diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 88351ee3e..0eb204d1f 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -50,10 +50,6 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { #endif ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer; - printf("INCOMING CLIENT\n\n"); - printf("%s\n", zc->char_name); - printf("%u\n", zc->zoneID); - uint16 target_zone_id = 0; uint16 target_instance_id = zc->instanceID; ZonePoint* zone_point = nullptr; @@ -568,7 +564,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z if(ReadyToZone) { zone_mode = zm; - printf("\n\n ZONE MODE %u \n\n", zm); if(zm == ZoneToBindPoint) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + iZoneNameLength); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; @@ -602,10 +597,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z gmg->instance_id = instance_id; gmg->type = 0x01; //an observed value, not sure of meaning - printf("gmg->zone_id %u \n", gmg->zone_id); - printf("gmg->x %u \n", gmg->x); - printf("gmg->y %u \n", gmg->y); - outapp->priority = 6; FastQueuePacket(&outapp); safe_delete(outapp); @@ -726,6 +717,7 @@ void Client::SetBindPoint(int to_zone, float new_x, float new_y, float new_z) { m_pp.binds[0].y = new_y; m_pp.binds[0].z = new_z; } + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); } void Client::GoToBind(uint8 bindnum) {