From 76e25f75fa5d520dc9afc03d4f458e065d4f633c Mon Sep 17 00:00:00 2001 From: j883376 Date: Fri, 21 Jun 2013 17:09:46 -0400 Subject: [PATCH 1/8] Fix a few memory leaks - Rewrite zonename_array to use std::map rather than a pointer to an array of character pointers - Properly delete ZoneConfig on Zone shutdown - Delete AdventureTemplates in AdventureManager destructor --- common/database.cpp | 73 +++++++------------------------------- common/database.h | 3 +- world/AdventureManager.cpp | 4 +++ zone/net.cpp | 3 +- 4 files changed, 20 insertions(+), 63 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 82a0ecae8..e62a33729 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -95,8 +95,6 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c void Database::DBInitVars() { - max_zonename = 0; - zonename_array = 0; varcache_array = 0; varcache_max = 0; varcache_lastupdate = 0; @@ -135,13 +133,6 @@ Close the connection to the database Database::~Database() { unsigned int x; - if (zonename_array) { - for (x=0; x<=max_zonename; x++) { - if (zonename_array[x]) - safe_delete_array(zonename_array[x]); - } - safe_delete_array(zonename_array); - } if (varcache_array) { for (x=0; x(zoneid,zonename)); } } else { @@ -1356,39 +1321,27 @@ bool Database::LoadZoneNames() { safe_delete_array(query); return false; } + mysql_free_result(result); + return true; } uint32 Database::GetZoneID(const char* zonename) { - if (zonename_array == 0) - return 0; if (zonename == 0) return 0; - for (unsigned int i=0; i<=max_zonename; i++) { - if (zonename_array[i] != 0 && strcasecmp(zonename_array[i], zonename) == 0) { - return i; + for (auto iter = zonename_array.begin(); iter != zonename_array.end(); ++iter) { + if (iter->second.compare(zonename) == 0) { + return iter->first; } } return 0; } const char* Database::GetZoneName(uint32 zoneID, bool ErrorUnknown) { - if (zonename_array == 0) { - if (ErrorUnknown) - return "UNKNOWN"; - else - return 0; - } + auto iter = zonename_array.find(zoneID); - if (zoneID <= max_zonename) { - if (zonename_array[zoneID]) - return zonename_array[zoneID]; - else { - if (ErrorUnknown) - return "UNKNOWN"; - else - return 0; - } + if (iter != zonename_array.end()) { + return iter->second.c_str(); } else { if (ErrorUnknown) diff --git a/common/database.h b/common/database.h index b194476b8..849f6f63d 100644 --- a/common/database.h +++ b/common/database.h @@ -255,8 +255,7 @@ protected: private: void DBInitVars(); - uint32 max_zonename; - char** zonename_array; + std::map zonename_array; Mutex Mvarcache; uint32 varcache_max; diff --git a/world/AdventureManager.cpp b/world/AdventureManager.cpp index 834b2b643..44ff5bf94 100644 --- a/world/AdventureManager.cpp +++ b/world/AdventureManager.cpp @@ -27,6 +27,10 @@ AdventureManager::~AdventureManager() safe_delete(process_timer); safe_delete(save_timer); safe_delete(leaderboard_info_timer); + + for (auto iter = adventure_templates.begin(); iter != adventure_templates.end(); ++iter) { + delete iter->second; + } } void AdventureManager::Process() diff --git a/zone/net.cpp b/zone/net.cpp index 4108894bc..11417ba4d 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -72,7 +72,7 @@ #undef new #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif - + #ifdef _WINDOWS #include #include @@ -475,6 +475,7 @@ int main(int argc, char** argv) { #endif safe_delete(ps); safe_delete(mmf); + safe_delete(Config); if (zone != 0) Zone::Shutdown(true); From 2a39449f6eb04234415489fa3d1602ed909bd840 Mon Sep 17 00:00:00 2001 From: j883376 Date: Fri, 21 Jun 2013 22:54:28 -0400 Subject: [PATCH 2/8] Fix exit code values - Change all exit codes to match the standard of 0 for success and 1 for error - Add empty shared folder to utils/defaults for shared_memory --- eqlaunch/eqlaunch.cpp | 6 ++-- queryserv/queryserv.cpp | 8 +++--- shared_memory/main.cpp | 14 ++++----- ucs/ucs.cpp | 8 +++--- utils/defaults/shared/.keep | 0 world/net.cpp | 57 ++++++++++++++++++++++--------------- zone/net.cpp | 16 +++++------ 7 files changed, 60 insertions(+), 49 deletions(-) create mode 100644 utils/defaults/shared/.keep diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 63484d6f2..d0239e4e7 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -44,13 +44,13 @@ int main(int argc, char *argv[]) { } if(launcher_name.length() < 1) { _log(LAUNCHER__ERROR, "You must specfify a launcher name as the first argument to this program."); - return(1); + return 1; } _log(LAUNCHER__INIT, "Loading server configuration.."); if (!EQEmuConfig::LoadConfig()) { _log(LAUNCHER__ERROR, "Loading server configuration failed."); - return(1); + return 1; } const EQEmuConfig *Config = EQEmuConfig::get(); @@ -173,7 +173,7 @@ int main(int argc, char *argv[]) { delete zone->second; } - return(0); + return 0; } diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index ce008a7f3..30dc9970e 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -69,7 +69,7 @@ int main() { _log(QUERYSERV__INIT, "Loading server configuration failed."); - return(1); + return 1; } Config = queryservconfig::get(); @@ -90,16 +90,16 @@ int main() { Config->QSDatabaseDB.c_str(), Config->QSDatabasePort)) { _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); - return(1); + return 1; } if (signal(SIGINT, CatchSignal) == SIG_ERR) { _log(QUERYSERV__ERROR, "Could not set signal handler"); - return 0; + return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { _log(QUERYSERV__ERROR, "Could not set signal handler"); - return 0; + return 1; } worldserver = new WorldServer; diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 52d85668d..fb4461d0d 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -37,7 +37,7 @@ int main(int argc, char **argv) { LogFile->write(EQEMuLog::Status, "Shared Memory Loader Program"); if(!EQEmuConfig::LoadConfig()) { LogFile->write(EQEMuLog::Error, "Unable to load configuration file."); - return 0; + return 1; } const EQEmuConfig *config = EQEmuConfig::get(); @@ -51,7 +51,7 @@ int main(int argc, char **argv) { config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { LogFile->write(EQEMuLog::Error, "Unable to connect to the database, cannot continue without a " "database connection"); - return 0; + return 1; } bool load_all = true; @@ -111,7 +111,7 @@ int main(int argc, char **argv) { LoadItems(&database); } catch(std::exception &ex) { LogFile->write(EQEMuLog::Error, "%s", ex.what()); - return 0; + return 1; } } @@ -121,7 +121,7 @@ int main(int argc, char **argv) { LoadFactions(&database); } catch(std::exception &ex) { LogFile->write(EQEMuLog::Error, "%s", ex.what()); - return 0; + return 1; } } @@ -131,7 +131,7 @@ int main(int argc, char **argv) { LoadLoot(&database); } catch(std::exception &ex) { LogFile->write(EQEMuLog::Error, "%s", ex.what()); - return 0; + return 1; } } @@ -141,7 +141,7 @@ int main(int argc, char **argv) { LoadSkillCaps(&database); } catch(std::exception &ex) { LogFile->write(EQEMuLog::Error, "%s", ex.what()); - return 0; + return 1; } } @@ -151,7 +151,7 @@ int main(int argc, char **argv) { LoadSpells(&database); } catch(std::exception &ex) { LogFile->write(EQEMuLog::Error, "%s", ex.what()); - return 0; + return 1; } } diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index bb2e483bb..322b58983 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -82,7 +82,7 @@ int main() { _log(UCS__INIT, "Loading server configuration failed."); - return(1); + return 1; } Config = ucsconfig::get(); @@ -103,7 +103,7 @@ int main() { Config->DatabaseDB.c_str(), Config->DatabasePort)) { _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); - return(1); + return 1; } char tmp[64]; @@ -137,11 +137,11 @@ int main() { if (signal(SIGINT, CatchSignal) == SIG_ERR) { _log(UCS__ERROR, "Could not set signal handler"); - return 0; + return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { _log(UCS__ERROR, "Could not set signal handler"); - return 0; + return 1; } worldserver = new WorldServer; diff --git a/utils/defaults/shared/.keep b/utils/defaults/shared/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/world/net.cpp b/world/net.cpp index 77ebfe6ea..d8b9b3357 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -126,7 +126,7 @@ int main(int argc, char** argv) { _log(WORLD__INIT, "Loading server configuration.."); if (!WorldConfig::LoadConfig()) { _log(WORLD__INIT_ERR, "Loading server configuration failed."); - return(1); + return 1; } const WorldConfig *Config=WorldConfig::get(); @@ -144,16 +144,16 @@ int main(int argc, char** argv) { if (signal(SIGINT, CatchSignal) == SIG_ERR) { _log(WORLD__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { _log(WORLD__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { _log(WORLD__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } #endif @@ -182,7 +182,7 @@ int main(int argc, char** argv) { Config->DatabaseDB.c_str(), Config->DatabasePort)) { _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); - return(1); + return 1; } dbasync = new DBAsync(&database); guild_mgr.SetDatabase(&database); @@ -204,8 +204,8 @@ int main(int argc, char** argv) { else if (database.GetVariable("disablecommandline", tmp, 2)) { if (strlen(tmp) == 1) { if (tmp[0] == '1') { - std::cout << "Command line disabled in database... exiting" << std::endl; - return 0; + std::cerr << "Command line disabled in database... exiting" << std::endl; + return 1; } } } @@ -213,11 +213,14 @@ int main(int argc, char** argv) { if (argc == 5) { if (Seperator::IsNumber(argv[4])) { if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) { - if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0) - std::cout << "database.CreateAccount failed." << std::endl; - else + if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0) { + std::cerr << "database.CreateAccount failed." << std::endl; + return 1; + } + else { std::cout << "Account created: Username='" << argv[2] << "', Password='" << argv[3] << "', status=" << argv[4] << std::endl; - return 0; + return 0; + } } } } @@ -230,11 +233,14 @@ int main(int argc, char** argv) { if (Seperator::IsNumber(argv[3])) { if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) { - if (database.SetAccountStatus(argv[2], atoi(argv[3]))) + if (database.SetAccountStatus(argv[2], atoi(argv[3]))) { std::cout << "Account flagged: Username='" << argv[2] << "', status=" << argv[3] << std::endl; - else - std::cout << "database.SetAccountStatus failed." << std::endl; - return 0; + return 0; + } + else { + std::cerr << "database.SetAccountStatus failed." << std::endl; + return 1; + } } } } @@ -245,25 +251,30 @@ int main(int argc, char** argv) { else if (strcasecmp(argv[1], "startzone") == 0) { if (argc == 3) { if (strlen(argv[2]) < 3) { - std::cout << "Error: zone name too short" << std::endl; + std::cerr << "Error: zone name too short" << std::endl; + return 1; } else if (strlen(argv[2]) > 15) { - std::cout << "Error: zone name too long" << std::endl; + std::cerr << "Error: zone name too long" << std::endl; + return 1; } else { - if (database.SetVariable("startzone", argv[2])) + if (database.SetVariable("startzone", argv[2])) { std::cout << "Starting zone changed: '" << argv[2] << "'" << std::endl; - else - std::cout << "database.SetVariable failed." << std::endl; + return 0; + } + else { + std::cerr << "database.SetVariable failed." << std::endl; + return 1; + } } - return 0; } std::cout << "Usage: world startzone zoneshortname" << std::endl; return 0; } else { - std::cout << "Error, unknown command line option" << std::endl; - return 0; + std::cerr << "Error, unknown command line option" << std::endl; + return 1; } } diff --git a/zone/net.cpp b/zone/net.cpp index 11417ba4d..227d0d43f 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -144,7 +144,7 @@ int main(int argc, char** argv) { _log(ZONE__INIT, "Loading server configuration.."); if (!ZoneConfig::LoadConfig()) { _log(ZONE__INIT_ERR, "Loading server configuration failed."); - return(1); + return 1; } const ZoneConfig *Config=ZoneConfig::get(); @@ -163,7 +163,7 @@ int main(int argc, char** argv) { Config->DatabaseDB.c_str(), Config->DatabasePort)) { _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); - return(1); + return 1; } dbasync = new DBAsync(&database); dbasync->AddFQ(&MTdbafq); @@ -182,16 +182,16 @@ int main(int argc, char** argv) { */ if (signal(SIGINT, CatchSignal) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 0; + return 1; } #endif @@ -217,19 +217,19 @@ int main(int argc, char** argv) { if (!database.LoadNPCFactionLists()) { _log(ZONE__INIT_ERR, "Loading npcs faction lists FAILED!"); CheckEQEMuErrorAndPause(); - return 0; + return 1; } _log(ZONE__INIT, "Loading loot tables"); if (!database.LoadLoot()) { _log(ZONE__INIT_ERR, "Loading loot FAILED!"); CheckEQEMuErrorAndPause(); - return 0; + return 1; } _log(ZONE__INIT, "Loading skill caps"); if (!database.LoadSkillCaps()) { _log(ZONE__INIT_ERR, "Loading skill caps FAILED!"); CheckEQEMuErrorAndPause(); - return 0; + return 1; } _log(ZONE__INIT, "Loading spells"); From 536e31d77189d48b121e1f5b7ad5eb011df0ce40 Mon Sep 17 00:00:00 2001 From: j883376 Date: Fri, 21 Jun 2013 23:21:57 -0400 Subject: [PATCH 3/8] Change binary output path to use CMake variable Tools that use CMake's EXECUTABLE_OUTPUT_PATH variable to determine which binary to launch for debugging may be confused by a relative path, so use CMake variable PROJECT_BINARY_DIR instead. --- common/CMakeLists.txt | 2 +- eqlaunch/CMakeLists.txt | 2 +- loginserver/CMakeLists.txt | 2 +- queryserv/CMakeLists.txt | 2 +- shared_memory/CMakeLists.txt | 2 +- ucs/CMakeLists.txt | 2 +- world/CMakeLists.txt | 2 +- zone/CMakeLists.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 1f613a885..286b678db 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -318,4 +318,4 @@ IF(UNIX) SET_SOURCE_FILES_PROPERTIES("patches/SoD.cpp" "patches/SoF.cpp" "patches/RoF.cpp" "patches/Underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) -SET(LIBRARY_OUTPUT_PATH ../Bin) +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index ef1c366ad..5c9ad6a60 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -37,4 +37,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index 7f2b25647..7a4272a70 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -67,4 +67,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index d63a7f814..8b8196b12 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -43,4 +43,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 01f79ec06..76c8b75bd 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -43,4 +43,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index 23ce4b781..6603470f6 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -46,4 +46,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index ee2fe0a22..a14505485 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -92,4 +92,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index ccba19144..9ff776c14 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -182,4 +182,4 @@ ENDIF(UNIX) INCLUDE_DIRECTORIES(${VLD_INCLUDE_DIR}) -SET(EXECUTABLE_OUTPUT_PATH ../Bin) +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) From 7e2806119b6686f70e4c5df7138feda0928ad190 Mon Sep 17 00:00:00 2001 From: j883376 Date: Sat, 22 Jun 2013 00:55:54 -0400 Subject: [PATCH 4/8] Fix some improper uses of printf formats --- ucs/database.cpp | 2 +- zone/client_packet.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ucs/database.cpp b/ucs/database.cpp index 508fab4a0..4e41a3180 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -402,7 +402,7 @@ void Database::SendHeaders(Client *c) { char Buf[100]; - my_ulonglong NumRows = mysql_num_rows(result); + uint32 NumRows = mysql_num_rows(result); int HeaderCountPacketLength = 0; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index dbfe3d0c1..ccba151d1 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3899,7 +3899,7 @@ void Client::Handle_OP_LDoNInspect(const EQApplicationPacket *app) void Client::Handle_OP_Dye(const EQApplicationPacket *app) { if(app->size!=sizeof(DyeStruct)) - printf("Wrong size of DyeStruct, Got: %i, Expected: %i\n",app->size,sizeof(DyeStruct)); + printf("Wrong size of DyeStruct, Got: %i, Expected: %zu\n",app->size,sizeof(DyeStruct)); else{ DyeStruct* dye = (DyeStruct*)app->pBuffer; DyeArmor(dye); @@ -3970,7 +3970,7 @@ void Client::Handle_OP_GuildPublicNote(const EQApplicationPacket *app) if (app->size < sizeof(GuildUpdate_PublicNote)) { // client calls for a motd on login even if they arent in a guild - printf("Error: app size of %i < size of OP_GuildPublicNote of %i\n",app->size,sizeof(GuildUpdate_PublicNote)); + printf("Error: app size of %i < size of OP_GuildPublicNote of %zu\n",app->size,sizeof(GuildUpdate_PublicNote)); return; } GuildUpdate_PublicNote* gpn=(GuildUpdate_PublicNote*)app->pBuffer; @@ -4028,7 +4028,7 @@ void Client::Handle_OP_SetGuildMOTD(const EQApplicationPacket *app) if (app->size != sizeof(GuildMOTD_Struct)) { // client calls for a motd on login even if they arent in a guild - printf("Error: app size of %i != size of GuildMOTD_Struct of %i\n",app->size,sizeof(GuildMOTD_Struct)); + printf("Error: app size of %i != size of GuildMOTD_Struct of %zu\n",app->size,sizeof(GuildMOTD_Struct)); return; } if(!IsInAGuild()) { @@ -6913,7 +6913,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app) void Client::Handle_OP_LoadSpellSet(const EQApplicationPacket *app) { if(app->size!=sizeof(LoadSpellSet_Struct)) { - printf("Wrong size of LoadSpellSet_Struct! Expected: %i, Got: %i\n",sizeof(LoadSpellSet_Struct),app->size); + printf("Wrong size of LoadSpellSet_Struct! Expected: %zu, Got: %i\n",sizeof(LoadSpellSet_Struct),app->size); return; } int i; @@ -6928,7 +6928,7 @@ void Client::Handle_OP_LoadSpellSet(const EQApplicationPacket *app) void Client::Handle_OP_PetitionBug(const EQApplicationPacket *app) { if(app->size!=sizeof(PetitionBug_Struct)) - printf("Wrong size of BugStruct! Expected: %i, Got: %i\n",sizeof(PetitionBug_Struct),app->size); + printf("Wrong size of BugStruct! Expected: %zu, Got: %i\n",sizeof(PetitionBug_Struct),app->size); else{ Message(0, "Petition Bugs are not supported, please use /bug."); } @@ -6938,7 +6938,7 @@ void Client::Handle_OP_PetitionBug(const EQApplicationPacket *app) void Client::Handle_OP_Bug(const EQApplicationPacket *app) { if(app->size!=sizeof(BugStruct)) - printf("Wrong size of BugStruct got %d expected %i!\n", app->size, sizeof(BugStruct)); + printf("Wrong size of BugStruct got %d expected %zu!\n", app->size, sizeof(BugStruct)); else{ BugStruct* bug=(BugStruct*)app->pBuffer; database.UpdateBug(bug); @@ -8334,7 +8334,7 @@ void Client::Handle_OP_OpenTributeMaster(const EQApplicationPacket *app) _pkt(TRIBUTE__IN, app); if(app->size != sizeof(StartTribute_Struct)) - printf("Error in OP_OpenTributeMaster. Expected size of: %i, but got: %i\n",sizeof(StartTribute_Struct),app->size); + printf("Error in OP_OpenTributeMaster. Expected size of: %zu, but got: %i\n",sizeof(StartTribute_Struct),app->size); else { //Opens the tribute master window StartTribute_Struct* st = (StartTribute_Struct*)app->pBuffer; @@ -8359,7 +8359,7 @@ void Client::Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app) _pkt(TRIBUTE__IN, app); if(app->size != sizeof(StartTribute_Struct)) - printf("Error in OP_OpenGuildTributeMaster. Expected size of: %i, but got: %i\n",sizeof(StartTribute_Struct),app->size); + printf("Error in OP_OpenGuildTributeMaster. Expected size of: %zu, but got: %i\n",sizeof(StartTribute_Struct),app->size); else { //Opens the guild tribute master window StartTribute_Struct* st = (StartTribute_Struct*)app->pBuffer; @@ -8385,7 +8385,7 @@ void Client::Handle_OP_TributeItem(const EQApplicationPacket *app) //player donates an item... if(app->size != sizeof(TributeItem_Struct)) - printf("Error in OP_TributeItem. Expected size of: %i, but got: %i\n",sizeof(StartTribute_Struct),app->size); + printf("Error in OP_TributeItem. Expected size of: %zu, but got: %i\n",sizeof(StartTribute_Struct),app->size); else { TributeItem_Struct* t = (TributeItem_Struct*)app->pBuffer; @@ -8414,7 +8414,7 @@ void Client::Handle_OP_TributeMoney(const EQApplicationPacket *app) //player donates money if(app->size != sizeof(TributeMoney_Struct)) - printf("Error in OP_TributeMoney. Expected size of: %i, but got: %i\n",sizeof(StartTribute_Struct),app->size); + printf("Error in OP_TributeMoney. Expected size of: %zu, but got: %i\n",sizeof(StartTribute_Struct),app->size); else { TributeMoney_Struct* t = (TributeMoney_Struct*)app->pBuffer; @@ -8562,7 +8562,7 @@ void Client::Handle_OP_Ignore(const EQApplicationPacket *app) void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) { if(app->size != sizeof(FindPersonRequest_Struct)) - printf("Error in FindPersonRequest_Struct. Expected size of: %i, but got: %i\n",sizeof(FindPersonRequest_Struct),app->size); + printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n",sizeof(FindPersonRequest_Struct),app->size); else { FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer; From c5e4cf35c00fbe6d5ae7aff064cc74e6b2985dac Mon Sep 17 00:00:00 2001 From: Zaela Date: Sat, 22 Jun 2013 08:35:33 -0700 Subject: [PATCH 5/8] Reworked RespawnFromHover framework to allow future customization (scripting) of respawn options. Added event_respawn to be triggered when a client respawns from hover into the current zone (may not be set up correctly!). --- zone/client.cpp | 190 ++++++++++++++++++++++++++++++------ zone/client.h | 17 ++++ zone/client_process.cpp | 209 +++++++++++++++++++++++++--------------- zone/embparser.cpp | 10 +- zone/event_codes.h | 1 + 5 files changed, 316 insertions(+), 111 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index a9212bda0..277768fb4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -319,6 +319,8 @@ Client::Client(EQStreamInterface* ieqs) MaxXTargets = 5; XTargetAutoAddHaters = true; LoadAccountFlags(); + + initial_respawn_selection = 0; } Client::~Client() { @@ -415,6 +417,8 @@ Client::~Client() { safe_delete_array(adv_requested_data); safe_delete_array(adv_data); + ClearRespawnOptions(); + numclients--; UpdateWindowTitle(); if(zone) @@ -4310,45 +4314,68 @@ void Client::SendRespawnBinds() // Client will respond with a 4 byte packet that includes the number of the selection made // + //If no options have been given, default to Bind + Rez + if (respawn_options.empty()) + { + BindStruct* b = &m_pp.binds[0]; + RespawnOption opt; + opt.name = "Bind Location"; + opt.zoneid = b->zoneId; + opt.x = b->x; + opt.y = b->y; + opt.z = b->z; + opt.heading = b->heading; + respawn_options.push_front(opt); + } + //Rez is always added at the end + RespawnOption rez; + rez.name = "Resurrect"; + rez.zoneid = zone->GetZoneID(); + rez.x = GetX(); + rez.y = GetY(); + rez.z = GetZ(); + rez.heading = GetHeading(); + respawn_options.push_back(rez); - const char* BindName = "Bind Location"; - const char* Resurrect = "Resurrect"; + int num_options = respawn_options.size(); + uint32 PacketLength = 17 + (26 * num_options); //Header size + per-option invariant size + + std::list::iterator itr; + RespawnOption* opt; - int PacketLength; + //Find string size for each option + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + opt = &(*itr); + PacketLength += opt->name.size() + 1; //+1 for cstring + } - PacketLength = 17 + (26 * 2) + strlen(BindName) + strlen(Resurrect); // SoF + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength); + char* buffer = (char*)outapp->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength); + //Packet header + VARSTRUCT_ENCODE_TYPE(uint32, buffer, initial_respawn_selection); //initial selection (from 0) + VARSTRUCT_ENCODE_TYPE(uint32, buffer, RuleI(Character, RespawnFromHoverTimer) * 1000); + VARSTRUCT_ENCODE_TYPE(uint32, buffer, 0); //unknown + VARSTRUCT_ENCODE_TYPE(uint32, buffer, num_options); //number of options to display - char *Buffer = (char *)outapp->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Unknown - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, RuleI(Character, RespawnFromHoverTimer) * 1000); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Unknown - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 2); // Two options, Bind or Rez - - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Entry 0 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, m_pp.binds[0].zoneId); - VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].x); - VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].y); - VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].z); - VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].heading); - VARSTRUCT_ENCODE_STRING(Buffer, BindName); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // Entry 1 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, zone->GetZoneID()); - VARSTRUCT_ENCODE_TYPE(float, Buffer, GetX()); - VARSTRUCT_ENCODE_TYPE(float, Buffer, GetY()); - VARSTRUCT_ENCODE_TYPE(float, Buffer, GetZ()); - VARSTRUCT_ENCODE_TYPE(float, Buffer, GetHeading()); - VARSTRUCT_ENCODE_STRING(Buffer, Resurrect); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); + //Individual options + int count = 0; + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + opt = &(*itr); + VARSTRUCT_ENCODE_TYPE(uint32, buffer, count++); //option num (from 0) + VARSTRUCT_ENCODE_TYPE(uint32, buffer, opt->zoneid); + VARSTRUCT_ENCODE_TYPE(float, buffer, opt->x); + VARSTRUCT_ENCODE_TYPE(float, buffer, opt->y); + VARSTRUCT_ENCODE_TYPE(float, buffer, opt->z); + VARSTRUCT_ENCODE_TYPE(float, buffer, opt->heading); + VARSTRUCT_ENCODE_STRING(buffer, opt->name.c_str()); + VARSTRUCT_ENCODE_TYPE(uint8, buffer, (count == num_options)); //is this one Rez (the last option)? + } QueuePacket(outapp); safe_delete(outapp); - return; } @@ -7734,3 +7761,104 @@ void Client::TryItemTick(int slot) } } } + +void Client::AddRespawnOption(std::string option_name, uint32 zoneid, float x, float y, float z, float heading, bool initial_selection, int8 position) +{ + //If respawn window is already open, any changes would create an inconsistency with the client + if (IsHoveringForRespawn()) { return; } + + if (zoneid == 0) + zoneid = zone->GetZoneID(); + + //Create respawn option + RespawnOption res_opt; + res_opt.name = option_name; + res_opt.zoneid = zoneid; + res_opt.x = x; + res_opt.y = y; + res_opt.z = z; + res_opt.heading = heading; + + if (position == -1 || position >= respawn_options.size()) + { + //No position specified, or specified beyond the end, simply append + respawn_options.push_back(res_opt); + //Make this option the initial selection for the window if desired + if (initial_selection) + initial_respawn_selection = static_cast(respawn_options.size()) - 1; + } + else if (position == 0) + { + respawn_options.push_front(res_opt); + if (initial_selection) + initial_respawn_selection = 0; + } + else + { + //Insert new option between existing options + std::list::iterator itr; + uint8 pos = 0; + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + if (pos++ == position) + { + respawn_options.insert(itr,res_opt); + //Make this option the initial selection for the window if desired + if (initial_selection) + initial_respawn_selection = pos; + return; + } + } + } +} + +bool Client::RemoveRespawnOption(std::string option_name) +{ + //If respawn window is already open, any changes would create an inconsistency with the client + if (IsHoveringForRespawn() || respawn_options.empty()) { return false; } + + bool had = false; + RespawnOption* opt; + std::list::iterator itr; + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + opt = &(*itr); + if (opt->name.compare(option_name) == 0) + { + respawn_options.erase(itr); + had = true; + //could be more with the same name, so keep going... + } + } + return had; +} + +bool Client::RemoveRespawnOption(uint8 position) +{ + //If respawn window is already open, any changes would create an inconsistency with the client + if (IsHoveringForRespawn() || respawn_options.empty()) { return false; } + + //Easy cases first... + if (position == 0) + { + respawn_options.pop_front(); + return true; + } + else if (position == (respawn_options.size() - 1)) + { + respawn_options.pop_back(); + return true; + } + + std::list::iterator itr; + uint8 pos = 0; + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + if (pos++ == position) + { + respawn_options.erase(itr); + return true; + } + } + return false; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index c4b338ed7..924580a70 100644 --- a/zone/client.h +++ b/zone/client.h @@ -179,6 +179,16 @@ struct XTarget_Struct char Name[65]; }; +struct RespawnOption +{ + std::string name; + uint32 zoneid; + float x; + float y; + float z; + float heading; +}; + const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000; @@ -1043,6 +1053,11 @@ public: bool MoveItemToInventory(ItemInst *BInst, bool UpdateClient = false); void HandleRespawnFromHover(uint32 Option); bool IsHoveringForRespawn() { return RespawnFromHoverTimer.Enabled(); } + std::list respawn_options; + void AddRespawnOption(std::string option_name, uint32 zoneid, float x, float y, float z, float h = 0, bool initial_selection = false, int8 position = -1); + bool RemoveRespawnOption(std::string option_name); + bool RemoveRespawnOption(uint8 position); + void ClearRespawnOptions() { respawn_options.clear(); } void SetPendingRezzData(int XP, uint32 DBID, uint16 SpellID, const char *CorpseName) { PendingRezzXP = XP; PendingRezzDBID = DBID; PendingRezzSpellID = SpellID; PendingRezzCorpseName = CorpseName; } bool IsRezzPending() { return PendingRezzSpellID > 0; } void ClearHover(); @@ -1449,6 +1464,8 @@ private: Timer ItemTickTimer; std::map accountflags; + + uint8 initial_respawn_selection; }; #include "parser.h" diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 31c93aa1c..290413565 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -2040,87 +2040,139 @@ void Client::HandleRespawnFromHover(uint32 Option) { RespawnFromHoverTimer.Disable(); - if(Option == 1) // Resurrect + RespawnOption* chosen = nullptr; + bool is_rez = false; + + //Find the selected option + if (Option == 0) { - if((PendingRezzXP < 0) || (PendingRezzSpellID == 0)) - { - _log(SPELLS__REZ, "Unexpected Rezz from hover request."); - return; - } - SetHP(GetMaxHP() / 5); - - Corpse* corpse = entity_list.GetCorpseByName(PendingRezzCorpseName.c_str()); - - if(corpse) - { - x_pos = corpse->GetX(); - y_pos = corpse->GetY(); - z_pos = corpse->GetZ(); - } - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10); - ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; - - gmg->bind_zone_id = zone->GetZoneID(); - gmg->bind_instance_id = zone->GetInstanceID(); - gmg->x = GetX(); - gmg->y = GetY(); - gmg->z = GetZ(); - gmg->heading = GetHeading(); - strcpy(gmg->zone_name, "Resurrect"); - - FastQueuePacket(&outapp); - - ClearHover(); - SendHPUpdate(); - OPRezzAnswer(1, PendingRezzSpellID, zone->GetZoneID(), zone->GetInstanceID(), GetX(), GetY(), GetZ()); - - if (corpse && corpse->IsCorpse()) { - _log(SPELLS__REZ, "Hover Rez in zone %s for corpse %s", - zone->GetShortName(), PendingRezzCorpseName.c_str()); - - _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); - - corpse->Rezzed(true); - corpse->CompleteRezz(); - } - return; + chosen = &respawn_options.front(); } - - // Respawn at Bind Point. - // - if(m_pp.binds[0].zoneId == zone->GetZoneID()) + else if (Option == (respawn_options.size() - 1)) { - PendingRezzSpellID = 0; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 14); - ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; - - gmg->bind_zone_id = m_pp.binds[0].zoneId; - gmg->x = m_pp.binds[0].x; - gmg->y = m_pp.binds[0].y; - gmg->z = m_pp.binds[0].z; - gmg->heading = 0; - strcpy(gmg->zone_name, "Bind Location"); - - FastQueuePacket(&outapp); - - CalcBonuses(); - SetHP(GetMaxHP()); - SetMana(GetMaxMana()); - SetEndurance(GetMaxEndurance()); - - x_pos = m_pp.binds[0].x; - y_pos = m_pp.binds[0].y; - z_pos = m_pp.binds[0].z; - - ClearHover(); - entity_list.RefreshClientXTargets(this); - SendHPUpdate(); - + chosen = &respawn_options.back(); + is_rez = true; //Rez must always be the last option } else { + std::list::iterator itr; + uint32 pos = 0; + for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) + { + if (pos++ == Option) + { + chosen = &(*itr); + break; + } + } + } + + //If they somehow chose an option they don't have, just send them to bind + RespawnOption default_to_bind; //must keep in scope! + if (!chosen) + { + /* put error logging here */ + BindStruct* b = &m_pp.binds[0]; + default_to_bind.name = "Bind Location"; + default_to_bind.zoneid = b->zoneId; + default_to_bind.x = b->x; + default_to_bind.y = b->y; + default_to_bind.z = b->z; + default_to_bind.heading = b->heading; + chosen = &default_to_bind; + is_rez = false; + } + + if (chosen->zoneid == zone->GetZoneID()) //If they should respawn in the current zone... + { + if (is_rez) + { + if (PendingRezzXP < 0 || PendingRezzSpellID == 0) + { + _log(SPELLS__REZ, "Unexpected Rezz from hover request."); + return; + } + SetHP(GetMaxHP() / 5); + + Corpse* corpse = entity_list.GetCorpseByName(PendingRezzCorpseName.c_str()); + + if (corpse) + { + x_pos = corpse->GetX(); + y_pos = corpse->GetY(); + z_pos = corpse->GetZ(); + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10); + ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; + + gmg->bind_zone_id = zone->GetZoneID(); + gmg->bind_instance_id = zone->GetInstanceID(); + gmg->x = GetX(); + gmg->y = GetY(); + gmg->z = GetZ(); + gmg->heading = GetHeading(); + strcpy(gmg->zone_name, "Resurrect"); + + FastQueuePacket(&outapp); + + ClearHover(); + SendHPUpdate(); + OPRezzAnswer(1, PendingRezzSpellID, zone->GetZoneID(), zone->GetInstanceID(), GetX(), GetY(), GetZ()); + + if (corpse && corpse->IsCorpse()) + { + _log(SPELLS__REZ, "Hover Rez in zone %s for corpse %s", + zone->GetShortName(), PendingRezzCorpseName.c_str()); + + _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); + + corpse->Rezzed(true); + corpse->CompleteRezz(); + } + } + else //Not rez + { + PendingRezzSpellID = 0; + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + chosen->name.length() + 1); + ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; + + gmg->bind_zone_id = zone->GetZoneID(); + gmg->x = chosen->x; + gmg->y = chosen->y; + gmg->z = chosen->z; + gmg->heading = chosen->heading; + strcpy(gmg->zone_name, chosen->name.c_str()); + + FastQueuePacket(&outapp); + + CalcBonuses(); + SetHP(GetMaxHP()); + SetMana(GetMaxMana()); + SetEndurance(GetMaxEndurance()); + + x_pos = chosen->x; + y_pos = chosen->y; + z_pos = chosen->z; + heading = chosen->heading; + + ClearHover(); + entity_list.RefreshClientXTargets(this); + SendHPUpdate(); + } + + //After they've respawned into the same zone, trigger EVENT_RESPAWN + parse->EventPlayer(EVENT_RESPAWN, this, static_cast(itoa(Option)), is_rez ? 1 : 0); + + //Pop Rez option from the respawn options list; + //easiest way to make sure it stays at the end and + //doesn't disrupt adding/removing scripted options + respawn_options.pop_back(); + } + else + { + //Heading to a different zone if(isgrouped) { Group *g = GetGroup(); @@ -2129,17 +2181,16 @@ void Client::HandleRespawnFromHover(uint32 Option) } Raid* r = entity_list.GetRaidByClient(this); - if(r) r->MemberZoned(this); - m_pp.zone_id = m_pp.binds[0].zoneId; + m_pp.zone_id = chosen->zoneid; m_pp.zoneInstance = 0; - database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); + database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(chosen->zoneid)); Save(); - GoToDeath(); + MovePC(chosen->zoneid,chosen->x,chosen->y,chosen->z,chosen->heading,1); } } diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 535ce880b..c4158d308 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -97,7 +97,8 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_CONNECT", "EVENT_ITEM_TICK", "EVENT_DUEL_WIN", - "EVENT_DUEL_LOSE" + "EVENT_DUEL_LOSE", + "EVENT_RESPAWN" }; extern Zone* zone; @@ -818,6 +819,13 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d break; } + case EVENT_RESPAWN: + { + ExportVar(packagename.c_str(), "respawn_option", data); + ExportVar(packagename.c_str(), "is_rez", extradata); + break; + } + //nothing special about these events case EVENT_DEATH: case EVENT_SPAWN: diff --git a/zone/event_codes.h b/zone/event_codes.h index 95bc77368..6ef0e96eb 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -61,6 +61,7 @@ typedef enum { EVENT_ITEM_TICK, EVENT_DUEL_WIN, EVENT_DUEL_LOSE, + EVENT_RESPAWN, //PC respawning from hover without changing zones _LargestEventID } QuestEventID; From f35afed89a2a58754856572d5e127233b3ee3535 Mon Sep 17 00:00:00 2001 From: Zaela Date: Tue, 25 Jun 2013 10:45:07 -0700 Subject: [PATCH 6/8] one eof newline --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 277768fb4..a561d5a84 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7861,4 +7861,4 @@ bool Client::RemoveRespawnOption(uint8 position) } } return false; -} \ No newline at end of file +} From 72ef7f6557893da699aad4eff9e1d64213c5ee17 Mon Sep 17 00:00:00 2001 From: Zaela Date: Tue, 25 Jun 2013 11:05:03 -0700 Subject: [PATCH 7/8] Made default-on-error a little less bad. --- zone/client_process.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 290413565..2c3af1a9f 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -2068,18 +2068,19 @@ void Client::HandleRespawnFromHover(uint32 Option) } //If they somehow chose an option they don't have, just send them to bind - RespawnOption default_to_bind; //must keep in scope! + RespawnOption* default_to_bind = nullptr; if (!chosen) { /* put error logging here */ BindStruct* b = &m_pp.binds[0]; - default_to_bind.name = "Bind Location"; - default_to_bind.zoneid = b->zoneId; - default_to_bind.x = b->x; - default_to_bind.y = b->y; - default_to_bind.z = b->z; - default_to_bind.heading = b->heading; - chosen = &default_to_bind; + default_to_bind = new RespawnOption; + default_to_bind->name = "Bind Location"; + default_to_bind->zoneid = b->zoneId; + default_to_bind->x = b->x; + default_to_bind->y = b->y; + default_to_bind->z = b->z; + default_to_bind->heading = b->heading; + chosen = default_to_bind; is_rez = false; } @@ -2192,6 +2193,8 @@ void Client::HandleRespawnFromHover(uint32 Option) MovePC(chosen->zoneid,chosen->x,chosen->y,chosen->z,chosen->heading,1); } + + safe_delete(default_to_bind); } void Client::ClearHover() From 488b2888a8123341767684ed7ce0cd83a774dcee Mon Sep 17 00:00:00 2001 From: j883376 Date: Tue, 25 Jun 2013 23:40:05 -0400 Subject: [PATCH 8/8] Fix uses of uninitialized variables - Replace unknown008 array with two separate variables in Object code - Fix mismatched safe_delete() of an array --- common/eq_packet_structs.h | 3 ++- common/patches/RoF.cpp | 2 -- common/patches/SoD.cpp | 2 -- common/patches/SoF.cpp | 2 -- common/patches/Underfoot.cpp | 2 -- zone/command.cpp | 40 +++++++++++++++++------------------ zone/merc.cpp | 2 +- zone/mob.cpp | 4 +++- zone/zone.cpp | 41 ++++++++++++++++++++---------------- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index f72b4c721..f5bc21a5d 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2415,7 +2415,8 @@ struct BookRequest_Struct { */ struct Object_Struct { /*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list -/*08*/ uint16 unknown008[2]; // +/*08*/ uint16 unknown008; // +/*10*/ uint16 unknown010; // /*12*/ uint32 drop_id; // Unique object id for zone /*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in /*18*/ uint16 zone_instance; // diff --git a/common/patches/RoF.cpp b/common/patches/RoF.cpp index 03893086c..905600821 100644 --- a/common/patches/RoF.cpp +++ b/common/patches/RoF.cpp @@ -3037,7 +3037,6 @@ ENCODE(OP_ZonePlayerToBind) ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; @@ -4839,7 +4838,6 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint charges = 0xFFFFFFFF; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); const Item_Struct *item = inst->GetItem(); //_log(NET__ERROR, "Serialize called for: %s", item->Name); diff --git a/common/patches/SoD.cpp b/common/patches/SoD.cpp index ce0a3566f..517479b48 100644 --- a/common/patches/SoD.cpp +++ b/common/patches/SoD.cpp @@ -1984,7 +1984,6 @@ ENCODE(OP_ZonePlayerToBind) ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; @@ -3057,7 +3056,6 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint charges = 0xFFFFFFFF; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); const Item_Struct *item = inst->GetItem(); //_log(NET__ERROR, "Serialize called for: %s", item->Name); diff --git a/common/patches/SoF.cpp b/common/patches/SoF.cpp index e5e144224..b7e1dac2f 100644 --- a/common/patches/SoF.cpp +++ b/common/patches/SoF.cpp @@ -1621,7 +1621,6 @@ ENCODE(OP_ZonePlayerToBind) ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; @@ -2376,7 +2375,6 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint charges = 0xFFFFFFFF; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); const Item_Struct *item = inst->GetItem(); //_log(NET__ERROR, "Serialize called for: %s", item->Name); diff --git a/common/patches/Underfoot.cpp b/common/patches/Underfoot.cpp index 041f483a5..2a8b57aa5 100644 --- a/common/patches/Underfoot.cpp +++ b/common/patches/Underfoot.cpp @@ -2044,7 +2044,6 @@ ENCODE(OP_ZonePlayerToBind) ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; @@ -3462,7 +3461,6 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint charges = 0xFFFFFFFF; std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - ss.clear(); const Item_Struct *item = inst->GetItem(); //_log(NET__ERROR, "Serialize called for: %s", item->Name); diff --git a/zone/command.cpp b/zone/command.cpp index b08fe3104..625278eee 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -9696,22 +9696,22 @@ void command_object(Client *c, const Seperator *sep) od.object_type = atoi(row[col++]); icon = atoi(row[col++]); - od.unknown008[0] = atoi(row[col++]); - od.unknown008[1] = atoi(row[col++]); + od.unknown008 = atoi(row[col++]); + od.unknown010 = atoi(row[col++]); od.unknown020 = atoi(row[col++]); switch (od.object_type) { case 0: // Static Object case TempStaticType: // Static Object unlocked for changes - if (od.unknown008[0] == 0) // Unknown08 field is optional Size parameter for static objects + if (od.unknown008 == 0) // Unknown08 field is optional Size parameter for static objects { - od.unknown008[0] = 100; // Static object default Size is 100% + od.unknown008 = 100; // Static object default Size is 100% } c->Message(0, "- STATIC Object (%s): id %u, x %.1f, y %.1f, z %.1f, h %.1f, model %s, size %u, solidtype %u, incline %u", - (od.object_type == 0) ? "locked" : "unlocked", id, od.x, od.y, od.z, od.heading, od.object_name, od.unknown008[0], od.unknown008[1], od.unknown020); + (od.object_type == 0) ? "locked" : "unlocked", id, od.x, od.y, od.z, od.heading, od.object_name, od.unknown008, od.unknown010, od.unknown020); break; case OT_DROPPEDITEM: // Ground Spawn c->Message(0, @@ -9777,11 +9777,11 @@ void command_object(Client *c, const Seperator *sep) case 0: // Static Object if ((sep->argnum - col) > 3) { - od.unknown008[0] = atoi(sep->arg[4 + col]); // Size specified + od.unknown008 = atoi(sep->arg[4 + col]); // Size specified if ((sep->argnum - col) > 4) { - od.unknown008[1] = atoi(sep->arg[5 + col]); // SolidType specified + od.unknown010 = atoi(sep->arg[5 + col]); // SolidType specified if ((sep->argnum - col) > 5) { @@ -10168,15 +10168,15 @@ void command_object(Client *c, const Seperator *sep) return; } - od.unknown008[0] = atoi(sep->arg[4]); + od.unknown008 = atoi(sep->arg[4]); o->SetObjectData(&od); - if (od.unknown008[0] == 0) // 0 == unspecified == 100% + if (od.unknown008 == 0) // 0 == unspecified == 100% { - od.unknown008[0] = 100; + od.unknown008 = 100; } - c->Message(0, "Static Object %u set to %u%% size. Size will take effect when you commit to the database with '#object Save', after which the object will be unchangeable until you unlock it again with '#object Edit' and zone out and back in.", id, od.unknown008[0]); + c->Message(0, "Static Object %u set to %u%% size. Size will take effect when you commit to the database with '#object Save', after which the object will be unchangeable until you unlock it again with '#object Edit' and zone out and back in.", id, od.unknown008); } else if (strcmp(sep->arg[3], "solidtype") == 0) { @@ -10194,10 +10194,10 @@ void command_object(Client *c, const Seperator *sep) return; } - od.unknown008[1] = atoi(sep->arg[4]); + od.unknown010 = atoi(sep->arg[4]); o->SetObjectData(&od); - c->Message(0, "Static Object %u set to SolidType %u. Change will take effect when you commit to the database with '#object Save'. Support for this property is on a per-model basis, mostly seen in smaller objects such as chests and tables.", id, od.unknown008[1]); + c->Message(0, "Static Object %u set to SolidType %u. Change will take effect when you commit to the database with '#object Save'. Support for this property is on a per-model basis, mostly seen in smaller objects such as chests and tables.", id, od.unknown010); } else { @@ -10548,7 +10548,7 @@ void command_object(Client *c, const Seperator *sep) zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, od.heading, od.object_name, od.object_type, icon, - od.unknown008[0], od.unknown008[1], od.unknown020); + od.unknown008, od.unknown010, od.unknown020); } else { @@ -10558,7 +10558,7 @@ void command_object(Client *c, const Seperator *sep) id, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, od.heading, od.object_name, od.object_type, icon, - od.unknown008[0], od.unknown008[1], od.unknown020); + od.unknown008, od.unknown010, od.unknown020); } } else @@ -10573,7 +10573,7 @@ void command_object(Client *c, const Seperator *sep) zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, od.heading, od.object_name, od.object_type, icon, - od.unknown008[0], od.unknown008[1], od.unknown020, + od.unknown008, od.unknown010, od.unknown020, id); } @@ -10651,12 +10651,12 @@ void command_object(Client *c, const Seperator *sep) memcpy(door.dest_zone, "NONE", 5); - if ((door.size = od.unknown008[0]) == 0) // unknown08 = optional size percentage + if ((door.size = od.unknown008) == 0) // unknown08 = optional size percentage { door.size = 100; } - switch (door.opentype = od.unknown008[1]) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) + switch (door.opentype = od.unknown010) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) { case 0: door.opentype = 31; @@ -10943,8 +10943,8 @@ void command_object(Client *c, const Seperator *sep) strn0cpy(od.object_name, row[col++], sizeof(od.object_name)); od.object_type = atoi(row[col++]); icon = atoi(row[col++]); - od.unknown008[0] = atoi(row[col++]); - od.unknown008[1] = atoi(row[col++]); + od.unknown008 = atoi(row[col++]); + od.unknown010 = atoi(row[col++]); od.unknown020 = atoi(row[col++]); if (od.object_type == 0) diff --git a/zone/merc.cpp b/zone/merc.cpp index 0e262f735..fb23cfc12 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5786,7 +5786,7 @@ bool Merc::AddMercToGroup(Merc* merc, Group* group) { void Client::InitializeMercInfo() { for(int i=0; iLoadProximities(zoneid); }