diff --git a/CMakeLists.txt b/CMakeLists.txt index 215a356e1..d49247268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF) OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF) +OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Inport/Export Data Programs." ON) #C++11 stuff IF(NOT MSVC) @@ -198,3 +199,7 @@ ENDIF(EQEMU_BUILD_AZONE) IF(EQEMU_BUILD_TESTS) ADD_SUBDIRECTORY(tests) ENDIF(EQEMU_BUILD_TESTS) + +IF(EQEMU_BUILD_CLIENT_FILES) + ADD_SUBDIRECTORY(client_files) +ENDIF(EQEMU_BUILD_CLIENT_FILES) diff --git a/client_files/CMakeLists.txt b/client_files/CMakeLists.txt new file mode 100644 index 000000000..93d748dc6 --- /dev/null +++ b/client_files/CMakeLists.txt @@ -0,0 +1,4 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +add_subdirectory(import) +add_subdirectory(export) diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt new file mode 100644 index 000000000..191184013 --- /dev/null +++ b/client_files/export/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(export_sources + main.cpp +) + +SET(export_headers +) + +ADD_EXECUTABLE(export_client_files ${export_sources} ${export_headers}) + +INSTALL(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) + +TARGET_LINK_LIBRARIES(export_client_files Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) + +IF(MSVC) + SET_TARGET_PROPERTIES(export_client_files PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + TARGET_LINK_LIBRARIES(export_client_files "Ws2_32.lib") +ENDIF(MSVC) + +IF(MINGW) + TARGET_LINK_LIBRARIES(export_client_files "WS2_32") +ENDIF(MINGW) + +IF(UNIX) + TARGET_LINK_LIBRARIES(export_client_files "${CMAKE_DL_LIBS}") + TARGET_LINK_LIBRARIES(export_client_files "z") + TARGET_LINK_LIBRARIES(export_client_files "m") + TARGET_LINK_LIBRARIES(export_client_files "rt") + TARGET_LINK_LIBRARIES(export_client_files "pthread") + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp new file mode 100644 index 000000000..33904f579 --- /dev/null +++ b/client_files/export/main.cpp @@ -0,0 +1,201 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include "../../common/debug.h" +#include "../../common/shareddb.h" +#include "../../common/EQEmuConfig.h" +#include "../../common/platform.h" +#include "../../common/crash.h" +#include "../../common/rulesys.h" +#include "../../common/StringUtil.h" + +void ExportSpells(SharedDatabase *db); +void ExportSkillCaps(SharedDatabase *db); +void ExportBaseData(SharedDatabase *db); + +int main(int argc, char **argv) { + RegisterExecutablePlatform(ExePlatformClientExport); + set_exception_handler(); + + LogFile->write(EQEMuLog::Status, "Client Files Export Utility"); + if(!EQEmuConfig::LoadConfig()) { + LogFile->write(EQEMuLog::Error, "Unable to load configuration file."); + return 1; + } + + const EQEmuConfig *config = EQEmuConfig::get(); + if(!load_log_settings(config->LogSettingsFile.c_str())) { + LogFile->write(EQEMuLog::Error, "Warning: unable to read %s.", config->LogSettingsFile.c_str()); + } + + SharedDatabase database; + LogFile->write(EQEMuLog::Status, "Connecting to database..."); + if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), + 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 1; + } + + ExportSpells(&database); + ExportSkillCaps(&database); + ExportBaseData(&database); + + return 0; +} + +void ExportSpells(SharedDatabase *db) { + LogFile->write(EQEMuLog::Status, "Exporting Spells..."); + + FILE *f = fopen("export/spells_us.txt", "w"); + if(!f) { + LogFile->write(EQEMuLog::Error, "Unable to open export/spells_us.txt to write, skipping."); + return; + } + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = "SELECT * FROM spells_new ORDER BY id"; + MYSQL_RES *result; + MYSQL_ROW row; + if(db->RunQuery(query, strlen(query), errbuf, &result)) { + while(row = mysql_fetch_row(result)) { + std::string line; + unsigned int fields = mysql_num_fields(result); + for(unsigned int i = 0; i < fields; ++i) { + if(i != 0) { + line.push_back('^'); + } + + line += row[i]; + } + + fprintf(f, "%s\n", line.c_str()); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ExportSpells query '%s' %s", query, errbuf); + } + + fclose(f); +} + +bool skill_usable(SharedDatabase *db, int skill_id, int class_id) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = nullptr; + MYSQL_RES *result; + MYSQL_ROW row; + bool res = false; + if(db->RunQuery(query, MakeAnyLenString(&query, "SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d", + class_id, skill_id), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + if(row[0] && atoi(row[0]) > 0) { + res = true; + } + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in skill_usable query '%s' %s", query, errbuf); + } + + safe_delete_array(query); + return res; +} + +int get_skill(SharedDatabase *db, int skill_id, int class_id, int level) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = nullptr; + MYSQL_RES *result; + MYSQL_ROW row; + int res = 0; + if(db->RunQuery(query, MakeAnyLenString(&query, "SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d", + class_id, skill_id, level), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + res = atoi(row[0]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in get_skill query '%s' %s", query, errbuf); + } + + safe_delete_array(query); + return res; +} + +void ExportSkillCaps(SharedDatabase *db) { + LogFile->write(EQEMuLog::Status, "Exporting Skill Caps..."); + + FILE *f = fopen("export/SkillCaps.txt", "w"); + if(!f) { + LogFile->write(EQEMuLog::Error, "Unable to open export/SkillCaps.txt to write, skipping."); + return; + } + + for(int cl = 1; cl <= 16; ++cl) { + for(int skill = 0; skill <= 77; ++skill) { + if(skill_usable(db, skill, cl)) { + int previous_cap = 0; + for(int level = 1; level <= 100; ++level) { + int cap = get_skill(db, skill, cl, level); + if(cap < previous_cap) { + cap = previous_cap; + } + + fprintf(f, "%d^%d^%d^%d^0\n", cl, skill, level, cap); + previous_cap = cap; + } + } + } + } + + fclose(f); +} + +void ExportBaseData(SharedDatabase *db) { + LogFile->write(EQEMuLog::Status, "Exporting Base Data..."); + + FILE *f = fopen("export/BaseData.txt", "w"); + if(!f) { + LogFile->write(EQEMuLog::Error, "Unable to open export/BaseData.txt to write, skipping."); + return; + } + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = "SELECT * FROM base_data ORDER BY level, class"; + MYSQL_RES *result; + MYSQL_ROW row; + if(db->RunQuery(query, strlen(query), errbuf, &result)) { + while(row = mysql_fetch_row(result)) { + std::string line; + unsigned int fields = mysql_num_fields(result); + for(unsigned int i = 0; i < fields; ++i) { + if(i != 0) { + line.push_back('^'); + } + + line += row[i]; + } + + fprintf(f, "%s\n", line.c_str()); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ExportBaseData query '%s' %s", query, errbuf); + } +} + diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt new file mode 100644 index 000000000..94875302d --- /dev/null +++ b/client_files/import/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(import_sources + main.cpp +) + +SET(import_headers +) + +ADD_EXECUTABLE(import_client_files ${import_sources} ${import_headers}) + +INSTALL(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) + +TARGET_LINK_LIBRARIES(import_client_files Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY}) + +IF(MSVC) + SET_TARGET_PROPERTIES(import_client_files PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + TARGET_LINK_LIBRARIES(import_client_files "Ws2_32.lib") +ENDIF(MSVC) + +IF(MINGW) + TARGET_LINK_LIBRARIES(import_client_files "WS2_32") +ENDIF(MINGW) + +IF(UNIX) + TARGET_LINK_LIBRARIES(import_client_files "${CMAKE_DL_LIBS}") + TARGET_LINK_LIBRARIES(import_client_files "z") + TARGET_LINK_LIBRARIES(import_client_files "m") + TARGET_LINK_LIBRARIES(import_client_files "rt") + TARGET_LINK_LIBRARIES(import_client_files "pthread") + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin) diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp new file mode 100644 index 000000000..a40b073bd --- /dev/null +++ b/client_files/import/main.cpp @@ -0,0 +1,68 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "../../common/debug.h" +#include "../../common/shareddb.h" +#include "../../common/EQEmuConfig.h" +#include "../../common/platform.h" +#include "../../common/crash.h" +#include "../../common/rulesys.h" + +void ImportSpells(SharedDatabase *db); +void ImportSkillCaps(SharedDatabase *db); +void ImportBaseData(SharedDatabase *db); + +int main(int argc, char **argv) { + RegisterExecutablePlatform(ExePlatformClientImport); + set_exception_handler(); + + LogFile->write(EQEMuLog::Status, "Client Files Import Utility"); + if(!EQEmuConfig::LoadConfig()) { + LogFile->write(EQEMuLog::Error, "Unable to load configuration file."); + return 1; + } + + const EQEmuConfig *config = EQEmuConfig::get(); + if(!load_log_settings(config->LogSettingsFile.c_str())) { + LogFile->write(EQEMuLog::Error, "Warning: unable to read %s.", config->LogSettingsFile.c_str()); + } + + SharedDatabase database; + LogFile->write(EQEMuLog::Status, "Connecting to database..."); + if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), + 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 1; + } + + ImportSpells(&database); + ImportSkillCaps(&database); + ImportBaseData(&database); + + return 0; +} + +void ImportSpells(SharedDatabase *db) { +} + +void ImportSkillCaps(SharedDatabase *db) { +} + +void ImportBaseData(SharedDatabase *db) { +} \ No newline at end of file diff --git a/common/debug.cpp b/common/debug.cpp index cb2b0ddf0..badd337c1 100644 --- a/common/debug.cpp +++ b/common/debug.cpp @@ -104,6 +104,10 @@ bool EQEMuLog::open(LogIDs id) { snprintf(exename, sizeof(exename), "_queryserv"); } else if(platform == ExePlatformSharedMemory) { snprintf(exename, sizeof(exename), "_shared_memory"); + } else if(platform == ExePlatformClientImport) { + snprintf(exename, sizeof(exename), "_import"); + } else if(platform == ExePlatformClientExport) { + snprintf(exename, sizeof(exename), "_export"); } char filename[200]; diff --git a/common/platform.h b/common/platform.h index f91ccb6f3..efb176ec4 100644 --- a/common/platform.h +++ b/common/platform.h @@ -10,7 +10,9 @@ enum EQEmuExePlatform ExePlatformQueryServ, ExePlatformUCS, ExePlatformLaunch, - ExePlatformSharedMemory + ExePlatformSharedMemory, + ExePlatformClientImport, + ExePlatformClientExport }; void RegisterExecutablePlatform(EQEmuExePlatform p); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index e5357000b..e048a42d9 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1759,7 +1759,7 @@ int SharedDatabase::GetMaxBaseDataLevel() { mysql_free_result(result); } } else { - _log(SPELLS__LOAD_ERR, "Error in GetMaxBaseDataLevel query '%s' %s", query, errbuf); + LogFile->write(EQEMuLog::Error, "Error in GetMaxBaseDataLevel query '%s' %s", query, errbuf); ret = -1; } return ret;