From f8e7576ae7d7e59116e3ac6ea5f96da8c8c64385 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 28 Sep 2022 04:08:59 -0500 Subject: [PATCH] [File Paths] Implement Path Manager (#2440) * Push up branch for testing * Path manager * Tweaks * Changes * More path work * Update paths for eqemu_server.pl * More path work * Import and export client files * Path remove * More path work * Update eqemu_config.h * Fix tests * Tests disable temp * Update eqemu_config.h * Update .drone.yml * Hook tests back up * Update main.cpp * Platform tests * Fix include * Use std::filesystem on windows * Fix IPCMutex name on windows * std::filesystem changes * Update path_manager.cpp * Explicit string cast * Explicit string cast * Update path_manager.cpp * Windows fixes * Mapped files * Relative fixes * Use relative paths off of cwd * Update Debian image to Debian 11 (updates GCC) Co-authored-by: hg <4683435+hgtw@users.noreply.github.com> --- .drone.yml | 2 +- client_files/export/main.cpp | 17 ++- client_files/import/main.cpp | 25 ++- common/CMakeLists.txt | 6 +- common/database/database_dump_service.cpp | 6 +- common/database_conversions.cpp | 5 +- common/eqemu_config.h | 20 ++- common/eqemu_logsys.cpp | 39 ++--- common/eqemu_logsys.h | 4 + common/{file_util.cpp => file.cpp} | 50 +++--- common/{file_util.h => file.h} | 19 ++- common/ipc_mutex.cpp | 10 +- common/ipc_mutex.h | 2 +- common/memory_mapped_file.cpp | 3 + common/patches/rof.cpp | 16 +- common/patches/rof2.cpp | 17 +-- common/patches/sod.cpp | 15 +- common/patches/sof.cpp | 15 +- common/patches/titanium.cpp | 14 +- common/patches/uf.cpp | 15 +- common/path_manager.cpp | 133 ++++++++++++++++ common/path_manager.h | 35 +++++ common/platform.cpp | 2 + common/platform.h | 3 +- common/rulesys.cpp | 1 + common/shareddb.cpp | 18 ++- eqlaunch/eqlaunch.cpp | 2 + loginserver/client_manager.cpp | 30 ++-- loginserver/main.cpp | 9 +- queryserv/queryserv.cpp | 5 + queryserv/queryservconfig.h | 4 +- shared_memory/main.cpp | 5 + tests/CMakeLists.txt | 2 +- tests/main.cpp | 20 ++- ucs/clientlist.cpp | 8 +- ucs/ucs.cpp | 5 + ucs/ucsconfig.h | 4 +- utils/scripts/eqemu_server.pl | 24 +-- world/login_server.cpp | 3 +- world/main.cpp | 5 + world/world_boot.cpp | 17 ++- world/world_config.h | 4 +- zone/command.cpp | 6 +- zone/embperl.cpp | 8 +- zone/lua_parser.cpp | 57 ++++--- zone/main.cpp | 39 +++-- zone/map.cpp | 79 ++++------ zone/pathfinder_interface.cpp | 5 +- zone/pathfinder_nav_mesh.cpp | 96 ++++++------ zone/quest_parser_collection.cpp | 176 +++++++--------------- zone/questmgr.cpp | 2 +- zone/water_map.cpp | 32 +--- zone/zone_config.h | 4 +- 53 files changed, 641 insertions(+), 502 deletions(-) rename common/{file_util.cpp => file.cpp} (56%) rename common/{file_util.h => file.h} (73%) create mode 100644 common/path_manager.cpp create mode 100644 common/path_manager.h diff --git a/.drone.yml b/.drone.yml index 7d99581ad..f202582c6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,7 +15,7 @@ volumes: steps: - name: server-build # Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20 - image: akkadius/eqemu-server:latest + image: akkadius/eqemu-server:v11 commands: - sudo chown eqemu:eqemu /drone/src/ * -R - sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 491f23761..505a4ac05 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -28,10 +28,12 @@ #include "../../common/strings.h" #include "../../common/content/world_content_service.h" #include "../../common/zone_store.h" +#include "../../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; ZoneStore zone_store; +PathManager path; void ExportSpells(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db); @@ -44,6 +46,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Client Files Export Utility"); if (!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file"); @@ -86,6 +90,7 @@ int main(int argc, char **argv) } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -126,7 +131,8 @@ void ExportSpells(SharedDatabase *db) { LogInfo("Exporting Spells"); - FILE *f = fopen("export/spells_us.txt", "w"); + std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/spells_us.txt to write, skipping."); return; @@ -208,7 +214,8 @@ void ExportSkillCaps(SharedDatabase *db) { LogInfo("Exporting Skill Caps"); - FILE *f = fopen("export/SkillCaps.txt", "w"); + std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/SkillCaps.txt to write, skipping."); return; @@ -238,7 +245,8 @@ void ExportBaseData(SharedDatabase *db) { LogInfo("Exporting Base Data"); - FILE *f = fopen("export/BaseData.txt", "w"); + std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/BaseData.txt to write, skipping."); return; @@ -271,7 +279,8 @@ void ExportDBStrings(SharedDatabase *db) { LogInfo("Exporting DB Strings"); - FILE *f = fopen("export/dbstr_us.txt", "w"); + std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "w"); if (!f) { LogError("Unable to open export/dbstr_us.txt to write, skipping."); return; diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index da230d73b..c80ed8194 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -26,10 +26,12 @@ #include "../../common/strings.h" #include "../../common/content/world_content_service.h" #include "../../common/zone_store.h" +#include "../../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; ZoneStore zone_store; +PathManager path; void ImportSpells(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db); @@ -41,6 +43,8 @@ int main(int argc, char **argv) { LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Client Files Import Utility"); if(!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file."); @@ -83,6 +87,7 @@ int main(int argc, char **argv) { } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); @@ -127,9 +132,10 @@ bool IsStringField(int i) { void ImportSpells(SharedDatabase *db) { LogInfo("Importing Spells"); - FILE *f = fopen("import/spells_us.txt", "r"); + std::string file = fmt::format("{}/import/spells_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/spells_us.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -216,9 +222,10 @@ void ImportSpells(SharedDatabase *db) { void ImportSkillCaps(SharedDatabase *db) { LogInfo("Importing Skill Caps"); - FILE *f = fopen("import/SkillCaps.txt", "r"); + std::string file = fmt::format("{}/import/SkillCaps.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/SkillCaps.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -251,9 +258,10 @@ void ImportSkillCaps(SharedDatabase *db) { void ImportBaseData(SharedDatabase *db) { LogInfo("Importing Base Data"); - FILE *f = fopen("import/BaseData.txt", "r"); + std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/BaseData.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } @@ -296,9 +304,10 @@ void ImportBaseData(SharedDatabase *db) { void ImportDBStrings(SharedDatabase *db) { LogInfo("Importing DB Strings"); - FILE *f = fopen("import/dbstr_us.txt", "r"); + std::string file = fmt::format("{}/import/dbstr_us.txt", path.GetServerPath()); + FILE *f = fopen(file.c_str(), "r"); if(!f) { - LogError("Unable to open import/dbstr_us.txt to read, skipping."); + LogError("Unable to open {} to read, skipping.", file); return; } diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index eb5a6bc4d..e8b2986c4 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -37,7 +37,7 @@ SET(common_sources extprofile.cpp discord_manager.cpp faction.cpp - file_util.cpp + file.cpp guild_base.cpp guilds.cpp inventory_profile.cpp @@ -61,6 +61,7 @@ SET(common_sources packet_dump.cpp packet_dump_file.cpp packet_functions.cpp + path_manager.cpp perl_eqdb.cpp perl_eqdb_res.cpp proc_launcher.cpp @@ -529,7 +530,7 @@ SET(common_headers expedition_lockout_timer.h extprofile.h faction.h - file_util.h + file.h features.h fixed_memory_hash_set.h fixed_memory_variable_hash_set.h @@ -565,6 +566,7 @@ SET(common_headers packet_dump.h packet_dump_file.h packet_functions.h + path_manager.cpp platform.h proc_launcher.h profanity_manager.h diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index e2ba39d81..b0385664b 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -26,7 +26,7 @@ #include "../strings.h" #include "../eqemu_config.h" #include "../database_schema.h" -#include "../file_util.h" +#include "../file.h" #include @@ -383,8 +383,8 @@ void DatabaseDumpService::Dump() pipe_file ); - if (!FileUtil::exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { - FileUtil::mkdir(GetSetDumpPath()); + if (!File::Exists(GetSetDumpPath()) && !IsDumpOutputToConsole()) { + File::Makedir(GetSetDumpPath()); } if (IsDumpDropTableSyntaxOnly()) { diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 15bc1fd23..a62138284 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "database.h" #include "extprofile.h" +#include "path_manager.h" #include #include @@ -476,7 +477,9 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertCorpseDeblob(); /* Run EQEmu Server script (Checks for database updates) */ - system("perl eqemu_server.pl ran_from_world"); + + const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); + system(fmt::format("perl {} ran_from_world", file).c_str()); return true; } diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 215586fd0..d0434399a 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -20,7 +20,9 @@ #include "json/json.h" #include "linked_list.h" +#include "path_manager.h" #include +#include struct LoginConfig { std::string LoginHost; @@ -152,23 +154,31 @@ class EQEmuConfig } // Load the config - static bool LoadConfig() + static bool LoadConfig(const std::string& path = "") { if (_config != nullptr) { return true; } _config = new EQEmuConfig; - return parseFile(); + return parseFile(path); } // Load config file and parse data - static bool parseFile() { + static bool parseFile(const std::string& file_path = ".") + { if (_config == nullptr) { - return LoadConfig(); + return LoadConfig(file_path); } - std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary); + std::string file = fmt::format( + "{}/{}", + (file_path.empty() ? path.GetServerPath() : file_path), + EQEmuConfig::ConfigFile + ); + + std::ifstream fconfig(file, std::ifstream::binary); + try { fconfig >> _config->_root; _config->parse_config(); diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 7db167dba..89a099324 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -521,37 +521,29 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name) return; } - LogInfo("Starting File Log [logs/{}_{}.log]", m_platform_file_name.c_str(), getpid()); + LogInfo("Starting File Log [{}/zone/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); - /** - * Make directory if not exists - */ - EQEmuLogSys::MakeDirectory("logs/zone"); + // Make directory if not exists + EQEmuLogSys::MakeDirectory(fmt::format("{}/zone", GetLogPath())); - /** - * Open file pointer - */ + // Open file pointer process_log.open( - StringFormat("logs/zone/%s_%i.log", m_platform_file_name.c_str(), getpid()), + fmt::format("{}/zone/{}_{}.log", GetLogPath(), m_platform_file_name, getpid()), std::ios_base::app | std::ios_base::out ); } else { - /** - * All other processes - */ + // All other processes if (m_platform_file_name.empty()) { return; } - LogInfo("Starting File Log [logs/{}_{}.log]", m_platform_file_name.c_str(), getpid()); + LogInfo("Starting File Log [{}/{}_{}.log]", GetLogPath(), m_platform_file_name.c_str(), getpid()); - /** - * Open file pointer - */ + // Open file pointer process_log.open( - StringFormat("logs/%s_%i.log", m_platform_file_name.c_str(), getpid()), + fmt::format("{}/{}_{}.log", GetLogPath(), m_platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out ); } @@ -756,3 +748,16 @@ bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 { return GetLogsEnabled(debug_level, log_category).log_enabled; } + +const std::string &EQEmuLogSys::GetLogPath() const +{ + return m_log_path; +} + +EQEmuLogSys * EQEmuLogSys::SetLogPath(const std::string &log_path) +{ + EQEmuLogSys::m_log_path = log_path; + + return this; +} + diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 223155d96..de26f3a48 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -366,6 +366,9 @@ public: // database EQEmuLogSys *SetDatabase(Database *db); + [[nodiscard]] const std::string &GetLogPath() const; + EQEmuLogSys * SetLogPath(const std::string &log_path); + private: // reference to database @@ -377,6 +380,7 @@ private: bool m_file_logs_enabled = false; int m_log_platform = 0; std::string m_platform_file_name; + std::string m_log_path; std::string GetLinuxConsoleColorFromCategory(uint16 log_category); uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); diff --git a/common/file_util.cpp b/common/file.cpp similarity index 56% rename from common/file_util.cpp rename to common/file.cpp index 7e2535512..2e478aa5b 100644 --- a/common/file_util.cpp +++ b/common/file.cpp @@ -19,7 +19,7 @@ */ #include -#include "file_util.h" +#include "file.h" #ifdef _WINDOWS #include @@ -35,38 +35,48 @@ #endif +#include +#include + +namespace fs = std::filesystem; + /** * @param name * @return */ -bool FileUtil::exists(const std::string &name) +bool File::Exists(const std::string &name) { - std::ifstream f(name.c_str()); - - return f.good(); + return fs::exists(fs::path{name}); } /** * @param directory_name */ -void FileUtil::mkdir(const std::string& directory_name) +void File::Makedir(const std::string &directory_name) { + fs::create_directory(directory_name); + fs::permissions(directory_name, fs::perms::owner_all); +} -#ifdef _WINDOWS - struct _stat st; - if (_stat(directory_name.c_str(), &st) == 0) // exists - return; - _mkdir(directory_name.c_str()); -#else - struct stat st{}; - if (stat(directory_name.c_str(), &st) == 0) { // exists - return; +std::string File::FindEqemuConfigPath() +{ + if (File::Exists(fs::path{File::GetCwd() + "/eqemu_config.json"}.string())) { + return File::GetCwd(); } - ::mkdir(directory_name.c_str(), 0755); -#endif + else if (File::Exists(fs::path{File::GetCwd() + "/../eqemu_config.json"}.string())) { + return canonical(fs::path{File::GetCwd() + "/../"}).string(); + } + else if (File::Exists(fs::path{File::GetCwd() + "/login.json"}.string())) { + return File::GetCwd(); + } + else if (File::Exists(fs::path{File::GetCwd() + "/../login.json"}.string())) { + return canonical(fs::path{File::GetCwd() + "/../"}).string(); + } + + return {}; } -bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); +std::string File::GetCwd() +{ + return fs::current_path().string(); } diff --git a/common/file_util.h b/common/file.h similarity index 73% rename from common/file_util.h rename to common/file.h index 02e47d198..c420b4c78 100644 --- a/common/file_util.h +++ b/common/file.h @@ -18,16 +18,21 @@ * */ -#ifndef EQEMU_FILE_UTIL_H -#define EQEMU_FILE_UTIL_H +#ifndef EQEMU_FILE_H +#define EQEMU_FILE_H +#include -class FileUtil { +namespace fs = std::filesystem; + +class File { public: - static bool exists(const std::string &name); - static void mkdir(const std::string& directory_name); + static bool Exists(const std::string &name); + static void Makedir(const std::string& directory_name); + static std::string FindEqemuConfigPath(); + static std::string GetCwd(); }; -bool file_exists(const std::string& name); +bool Exists(const std::string& name); -#endif //EQEMU_FILE_UTIL_H +#endif //EQEMU_FILE_H diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 5eb4eedfc..e2c123f22 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -30,6 +30,7 @@ #include "types.h" #include "eqemu_exception.h" #include "eqemu_config.h" +#include "path_manager.h" namespace EQ { struct IPCMutex::Implementation { @@ -40,12 +41,11 @@ namespace EQ { #endif }; - IPCMutex::IPCMutex(std::string name) : locked_(false) { + IPCMutex::IPCMutex(const std::string& name) : locked_(false) { imp_ = new Implementation; #ifdef _WINDOWS auto Config = EQEmuConfig::get(); - std::string final_name = Config->SharedMemDir + "EQEmuMutex_"; - final_name += name; + std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name); imp_->mut_ = CreateMutex(nullptr, FALSE, @@ -55,9 +55,7 @@ namespace EQ { EQ_EXCEPT("IPC Mutex", "Could not create mutex."); } #else - auto Config = EQEmuConfig::get(); - std::string final_name = Config->SharedMemDir + name; - final_name += ".lock"; + std::string final_name = fmt::format("{}/{}.lock", path.GetSharedMemoryPath(), name); #ifdef __DARWIN #if __DARWIN_C_LEVEL < 200809L diff --git a/common/ipc_mutex.h b/common/ipc_mutex.h index a8f2fd13c..4418f9189 100644 --- a/common/ipc_mutex.h +++ b/common/ipc_mutex.h @@ -37,7 +37,7 @@ namespace EQ { Creates a named binary semaphore, basically a semaphore that is init S <- 1 \param name The name of this mutex. */ - IPCMutex(std::string name); + IPCMutex(const std::string& name); //! Destructor ~IPCMutex(); diff --git a/common/memory_mapped_file.cpp b/common/memory_mapped_file.cpp index a11b3c5db..a1a16d5db 100644 --- a/common/memory_mapped_file.cpp +++ b/common/memory_mapped_file.cpp @@ -33,6 +33,9 @@ #include #endif +#include +namespace fs = std::filesystem; + namespace EQ { struct MemoryMappedFile::Implementation { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index e86fcf340..dd4c808f3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -32,6 +32,7 @@ #include "../inventory_profile.h" #include "rof_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -75,12 +76,8 @@ namespace RoF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); + //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -118,12 +115,7 @@ namespace RoF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 828452171..2da694f91 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -32,6 +32,7 @@ #include "../inventory_profile.h" #include "rof2_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -76,12 +77,9 @@ namespace RoF2 { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); + //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -122,12 +120,7 @@ namespace RoF2 //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 0a3c5e159..91aafeff8 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -32,6 +32,7 @@ #include "../item_instance.h" #include "sod_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -69,12 +70,7 @@ namespace SoD { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -115,12 +111,7 @@ namespace SoD //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7a3198d6d..c7851084b 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -32,6 +32,7 @@ #include "../item_instance.h" #include "sof_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -69,12 +70,7 @@ namespace SoF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -113,12 +109,7 @@ namespace SoF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 542bf7282..e5d0cb59b 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -32,6 +32,7 @@ #include "../strings.h" #include "../item_instance.h" #include "titanium_structs.h" +#include "../path_manager.h" #include @@ -69,11 +70,7 @@ namespace Titanium auto Config = EQEmuConfig::get(); //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -114,12 +111,7 @@ namespace Titanium //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 8d23df49f..bd5d6e105 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -32,6 +32,7 @@ #include "../item_instance.h" #include "uf_structs.h" #include "../rulesys.h" +#include "../path_manager.h" #include #include @@ -69,12 +70,7 @@ namespace UF { //create our opcode manager if we havent already if (opcodes == nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); //load up the opcode manager. //TODO: figure out how to support shared memory with multiple patches... opcodes = new RegularOpcodeManager(); @@ -115,12 +111,7 @@ namespace UF //we need to go to every stream and replace it's manager. if (opcodes != nullptr) { - //TODO: get this file name from the config file - auto Config = EQEmuConfig::get(); - std::string opfile = Config->PatchDir; - opfile += "patch_"; - opfile += name; - opfile += ".conf"; + std::string opfile = fmt::format("{}/patch_{}.conf", path.GetPatchPath(), name); if (!opcodes->ReloadOpcodes(opfile.c_str())) { LogNetcode("[OPCODES] Error reloading opcodes file [{}] for patch [{}]", opfile.c_str(), name); return; diff --git a/common/path_manager.cpp b/common/path_manager.cpp new file mode 100644 index 000000000..eaac4ca91 --- /dev/null +++ b/common/path_manager.cpp @@ -0,0 +1,133 @@ +#include "path_manager.h" +#include "file.h" +#include "eqemu_logsys.h" +#include "eqemu_config.h" +#include "strings.h" + +#include +namespace fs = std::filesystem; + +inline std::string striptrailingslash(const std::string &file_path) +{ + if (file_path.back() == '/' || file_path.back() == '\\') { + return file_path.substr(0, file_path.length() - 1); + } + + return file_path; +} + +void PathManager::LoadPaths() +{ + m_server_path = File::FindEqemuConfigPath(); + + std::filesystem::current_path(m_server_path); + + LogInfo("[PathManager] server [{}]", m_server_path); + + if (!EQEmuConfig::LoadConfig()) { + LogError("[PathManager] Failed to load eqemu config"); + return; + } + + const auto c = EQEmuConfig::get(); + + // maps + if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string(); + } + else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string(); + } + else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) { + m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string(); + } + + // quests + if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) { + m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string(); + } + + // plugins + if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) { + m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string(); + } + + // lua_modules + if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) { + m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string(); + } + + // lua mods + if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) { + m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string(); + } + + // patches + if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) { + m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string(); + } + + // shared_memory_path + if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) { + m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string(); + } + + // logging path + if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) { + m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string(); + } + + LogInfo("[PathManager] logs [{}]", m_log_path); + LogInfo("[PathManager] lua mods [{}]", m_lua_mods_path); + LogInfo("[PathManager] lua_modules [{}]", m_lua_modules_path); + LogInfo("[PathManager] maps [{}]", m_maps_path); + LogInfo("[PathManager] patches [{}]", m_patch_path); + LogInfo("[PathManager] plugins [{}]", m_plugins_path); + LogInfo("[PathManager] quests [{}]", m_quests_path); + LogInfo("[PathManager] shared_memory [{}]", m_shared_memory_path); +} + +const std::string &PathManager::GetServerPath() const +{ + return m_server_path; +} + +const std::string &PathManager::GetMapsPath() const +{ + return m_maps_path; +} + +const std::string &PathManager::GetQuestsPath() const +{ + return m_quests_path; +} + +const std::string &PathManager::GetPluginsPath() const +{ + return m_plugins_path; +} + +const std::string &PathManager::GetSharedMemoryPath() const +{ + return m_shared_memory_path; +} + +const std::string &PathManager::GetLogPath() const +{ + return m_log_path; +} + +const std::string &PathManager::GetPatchPath() const +{ + return m_patch_path; +} + +const std::string &PathManager::GetLuaModulesPath() const +{ + return m_lua_modules_path; +} + +const std::string &PathManager::GetLuaModsPath() const +{ + return m_lua_mods_path; +} diff --git a/common/path_manager.h b/common/path_manager.h new file mode 100644 index 000000000..4283dbf64 --- /dev/null +++ b/common/path_manager.h @@ -0,0 +1,35 @@ +#ifndef EQEMU_PATH_MANAGER_H +#define EQEMU_PATH_MANAGER_H + + +#include + +class PathManager { +public: + void LoadPaths(); + + [[nodiscard]] const std::string &GetLogPath() const; + [[nodiscard]] const std::string &GetLuaModsPath() const; + [[nodiscard]] const std::string &GetLuaModulesPath() const; + [[nodiscard]] const std::string &GetMapsPath() const; + [[nodiscard]] const std::string &GetPatchPath() const; + [[nodiscard]] const std::string &GetPluginsPath() const; + [[nodiscard]] const std::string &GetQuestsPath() const; + [[nodiscard]] const std::string &GetServerPath() const; + [[nodiscard]] const std::string &GetSharedMemoryPath() const; + +private: + std::string m_log_path; + std::string m_lua_mods_path; + std::string m_lua_modules_path; + std::string m_maps_path; + std::string m_patch_path; + std::string m_plugins_path; + std::string m_quests_path; + std::string m_server_path; + std::string m_shared_memory_path; +}; + +extern PathManager path; + +#endif //EQEMU_PATH_MANAGER_H diff --git a/common/platform.cpp b/common/platform.cpp index e5481c339..83906c60b 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -67,6 +67,8 @@ std::string GetPlatformName() return "Launch"; case EQEmuExePlatform::ExePlatformHC: return "HC"; + case EQEmuExePlatform::ExePlatformTests: + return "Tests"; default: return ""; } diff --git a/common/platform.h b/common/platform.h index bd24a1493..a69738ff6 100644 --- a/common/platform.h +++ b/common/platform.h @@ -36,7 +36,8 @@ enum EQEmuExePlatform ExePlatformSharedMemory, ExePlatformClientImport, ExePlatformClientExport, - ExePlatformHC + ExePlatformHC, + ExePlatformTests }; void RegisterExecutablePlatform(EQEmuExePlatform p); diff --git a/common/rulesys.cpp b/common/rulesys.cpp index e8ad26d3e..c5806613a 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -17,6 +17,7 @@ */ #include "rulesys.h" +#include "eqemu_logsys.h" #include "database.h" #include "strings.h" #include diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 21aebf495..49d3ccf33 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -41,6 +41,7 @@ #include "repositories/criteria/content_filter_criteria.h" #include "repositories/account_repository.h" #include "repositories/faction_association_repository.h" +#include "path_manager.h" namespace ItemField { @@ -940,7 +941,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("items"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("items"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("items")); LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); items_mmf = std::make_unique(file_name); items_hash = std::make_unique>(static_cast(items_mmf->Get()), items_mmf->Size()); @@ -1436,7 +1437,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("faction"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("faction")); LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); faction_mmf = std::make_unique(file_name); faction_hash = std::make_unique>(static_cast(faction_mmf->Get()), faction_mmf->Size()); @@ -1509,7 +1510,7 @@ bool SharedDatabase::LoadFactionAssociation(const std::string &prefix) auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("factionassociations"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("factionassociations"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("factionassociations")); faction_associations_mmf = std::unique_ptr(new EQ::MemoryMappedFile(file_name)); faction_associations_hash = std::unique_ptr>( new EQ::FixedMemoryHashSet(reinterpret_cast(faction_associations_mmf->Get()), @@ -1704,7 +1705,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("skill_caps"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("skill_caps")); LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); skill_caps_mmf = std::make_unique(file_name); mutex.Unlock(); @@ -1863,7 +1864,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const EQ::IPCMutex mutex("spells"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("spells"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("spells")); spells_mmf = std::make_unique(file_name); LogInfo("[Shared Memory] Attempting to load file [{}]", file_name); *records = *static_cast(spells_mmf->Get()); @@ -2077,7 +2078,7 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) { EQ::IPCMutex mutex("base_data"); mutex.Lock(); - std::string file_name = Config->SharedMemDir + prefix + std::string("base_data"); + std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("base_data")); base_data_mmf = std::make_unique(file_name); mutex.Unlock(); } catch(std::exception& ex) { @@ -2398,12 +2399,13 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) { const auto Config = EQEmuConfig::get(); EQ::IPCMutex mutex("loot"); mutex.Lock(); - std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); + std::string file_name_lt = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("loot_table")); + loot_table_mmf = std::make_unique(file_name_lt); loot_table_hash = std::make_unique>( static_cast(loot_table_mmf->Get()), loot_table_mmf->Size()); - std::string file_name_ld = Config->SharedMemDir + prefix + std::string("loot_drop"); + std::string file_name_ld = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("loot_drop")); loot_drop_mmf = std::make_unique(file_name_ld); loot_drop_hash = std::make_unique>( static_cast(loot_drop_mmf->Get()), diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 4cb7f7b9c..3f97f8ae5 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -21,6 +21,7 @@ #include "../common/proc_launcher.h" #include "../common/eqemu_config.h" #include "../common/servertalk.h" +#include "../common/path_manager.h" #include "../common/platform.h" #include "../common/crash.h" #include "../common/unix.h" @@ -33,6 +34,7 @@ #include EQEmuLogSys LogSys; +PathManager path; bool RunLoops = false; diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 6b3fc0bce..7bb352929 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -6,6 +6,7 @@ extern bool run_server; #include "../common/eqemu_logsys.h" #include "../common/misc.h" +#include "../common/path_manager.h" ClientManager::ClientManager() { @@ -15,13 +16,18 @@ ClientManager::ClientManager() titanium_stream = new EQ::Net::EQStreamManager(titanium_opts); titanium_ops = new RegularOpcodeManager; - if (!titanium_ops->LoadOpcodes( + + std::string opcodes_path = fmt::format( + "{}/{}", + path.GetServerPath(), server.config.GetVariableString( "client_configuration", "titanium_opcodes", "login_opcodes.conf" - ).c_str())) { + ) + ); + if (!titanium_ops->LoadOpcodes(opcodes_path.c_str())) { LogError( "ClientManager fatal error: couldn't load opcodes for Titanium file [{0}]", server.config.GetVariableString("client_configuration", "titanium_opcodes", "login_opcodes.conf") @@ -49,14 +55,18 @@ ClientManager::ClientManager() EQStreamManagerInterfaceOptions sod_opts(sod_port, false, false); sod_stream = new EQ::Net::EQStreamManager(sod_opts); sod_ops = new RegularOpcodeManager; - if ( - !sod_ops->LoadOpcodes( - server.config.GetVariableString( - "client_configuration", - "sod_opcodes", - "login_opcodes.conf" - ).c_str() - )) { + + opcodes_path = fmt::format( + "{}/{}", + path.GetServerPath(), + server.config.GetVariableString( + "client_configuration", + "sod_opcodes", + "login_opcodes.conf" + ) + ); + + if (!sod_ops->LoadOpcodes(opcodes_path.c_str())) { LogError( "ClientManager fatal error: couldn't load opcodes for SoD file {0}", server.config.GetVariableString("client_configuration", "sod_opcodes", "login_opcodes.conf").c_str() diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 0a547cef1..12390392f 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -11,6 +11,7 @@ #include "loginserver_webserver.h" #include "loginserver_command_handler.h" #include "../common/strings.h" +#include "../common/path_manager.h" #include #include #include @@ -20,6 +21,7 @@ LoginServer server; EQEmuLogSys LogSys; bool run_server = true; +PathManager path; void ResolveAddresses(); void CatchSignal(int sig_num) @@ -42,7 +44,9 @@ void LoadDatabaseConnection() void LoadServerConfig() { - server.config = EQ::JsonConfigFile::Load("login.json"); + server.config = EQ::JsonConfigFile::Load( + fmt::format("{}/login.json", path.GetServerPath()) + ); LogInfo("Config System Init"); /** @@ -172,6 +176,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); } + path.LoadPaths(); + /** * Command handler */ @@ -197,6 +203,7 @@ int main(int argc, char **argv) if (argc == 1) { LogSys.SetDatabase(server.db) + ->SetLogPath("logs") ->LoadLogDatabaseSettings() ->StartFileLogs(); } diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index 81c299fb4..74c6bf607 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -31,6 +31,7 @@ #include "queryservconfig.h" #include "lfguild.h" #include "worldserver.h" +#include "../common/path_manager.h" #include #include #include @@ -43,6 +44,7 @@ std::string WorldShortName; const queryservconfig *Config; WorldServer *worldserver = 0; EQEmuLogSys LogSys; +PathManager path; void CatchSignal(int sig_num) { @@ -56,6 +58,8 @@ int main() set_exception_handler(); Timer LFGuildExpireTimer(60000); + path.LoadPaths(); + LogInfo("Starting EQEmu QueryServ"); if (!queryservconfig::LoadConfig()) { LogInfo("Loading server configuration failed"); @@ -80,6 +84,7 @@ int main() } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); diff --git a/queryserv/queryservconfig.h b/queryserv/queryservconfig.h index 9878493f7..5c9d63bd6 100644 --- a/queryserv/queryservconfig.h +++ b/queryserv/queryservconfig.h @@ -40,13 +40,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_chat_config != nullptr) delete _chat_config; _chat_config=new queryservconfig; _config=_chat_config; - return _config->parseFile(); + return _config->parseFile(path); } }; diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 24d6be661..e29e77e32 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -36,10 +36,12 @@ #include "base_data.h" #include "../common/content/world_content_service.h" #include "../common/zone_store.h" +#include "../common/path_manager.h" EQEmuLogSys LogSys; WorldContentService content_service; ZoneStore zone_store; +PathManager path; #ifdef _WINDOWS #include @@ -83,6 +85,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + LogInfo("Shared Memory Loader Program"); if (!EQEmuConfig::LoadConfig()) { LogError("Unable to load configuration file"); @@ -124,6 +128,7 @@ int main(int argc, char **argv) } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 811890bb7..6ed82f5b8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,7 +21,7 @@ SET(tests_headers ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) -TARGET_LINK_LIBRARIES(tests common cppunit fmt) +TARGET_LINK_LIBRARIES(tests common cppunit fmt ${SERVER_LIBS}) INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/main.cpp b/tests/main.cpp index 13f49f238..2f32c2840 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -20,6 +20,8 @@ #include #include #include +#include "../common/platform.h" +#include "../common/path_manager.h" #include "memory_mapped_file_test.h" #include "ipc_mutex_test.h" #include "fixed_memory_test.h" @@ -30,17 +32,23 @@ #include "data_verification_test.h" #include "skills_util_test.h" #include "task_state_test.h" -#include "../common/eqemu_config.h" const EQEmuConfig *Config; +EQEmuLogSys LogSys; +PathManager path; + +int main() +{ + RegisterExecutablePlatform(ExePlatformClientImport); + LogSys.LoadLogSettingsDefaults(); + path.LoadPaths(); -int main() { auto ConfigLoadResult = EQEmuConfig::LoadConfig(); - Config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); try { - std::ofstream outfile("test_output.txt"); + std::ofstream outfile("test_output.txt"); std::unique_ptr output(new Test::TextOutput(Test::TextOutput::Verbose, outfile)); - Test::Suite tests; + Test::Suite tests; tests.add(new MemoryMappedFileTest()); tests.add(new IPCMutexTest()); tests.add(new FixedMemoryHashTest()); @@ -52,7 +60,7 @@ int main() { tests.add(new SkillsUtilsTest()); tests.add(new TaskStateTest()); tests.run(*output, true); - } catch(...) { + } catch (...) { return -1; } return 0; diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index af3b5978c..0d54f22c3 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "clientlist.h" #include "database.h" #include "chatchannel.h" +#include "../common/path_manager.h" #include #include @@ -478,8 +479,11 @@ Clientlist::Clientlist(int ChatPort) { const ucsconfig *Config = ucsconfig::get(); - LogInfo("Loading [{}]", Config->MailOpCodesFile.c_str()); - if (!ChatOpMgr->LoadOpcodes(Config->MailOpCodesFile.c_str())) + + std::string opcodes_file = fmt::format("{}/{}", path.GetServerPath(), Config->MailOpCodesFile); + + LogInfo("Loading [{}]", opcodes_file); + if (!ChatOpMgr->LoadOpcodes(opcodes_file.c_str())) exit(1); chatsf->OnNewConnection([this](std::shared_ptr stream) { diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 986a2df7c..e99cac5ec 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -38,6 +38,7 @@ #include "../common/net/tcp_server.h" #include "../common/net/servertalk_client_connection.h" #include "../common/discord_manager.h" +#include "../common/path_manager.h" ChatChannelList *ChannelList; Clientlist *g_Clientlist; @@ -45,6 +46,7 @@ EQEmuLogSys LogSys; Database database; WorldServer *worldserver = nullptr; DiscordManager discord_manager; +PathManager path; const ucsconfig *Config; @@ -101,6 +103,8 @@ int main() { LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + // Check every minute for unused channels we can delete // Timer ChannelListProcessTimer(60000); @@ -132,6 +136,7 @@ int main() { } LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->StartFileLogs(); diff --git a/ucs/ucsconfig.h b/ucs/ucsconfig.h index 5424dfeb5..887ff821b 100644 --- a/ucs/ucsconfig.h +++ b/ucs/ucsconfig.h @@ -40,13 +40,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_chat_config != nullptr) delete _chat_config; _chat_config=new ucsconfig; _config=_chat_config; - return _config->parseFile(); + return _config->parseFile(path); } }; diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 4112431bf..a96167a04 100755 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -50,6 +50,11 @@ if ($Config{osname} =~ /Win|MS/i) { $OS = "Windows"; } +if (-e "../eqemu_config.json") { + print "[Info] Config is up one level, let's set current directory up one level...\n"; + chdir("../"); +} + ############################################# # internet check ############################################# @@ -83,6 +88,8 @@ if (-d "bin") { $bin_dir = "bin/"; } +my $world_path = get_world_path(); + ############################################# # run routines ############################################# @@ -540,14 +547,6 @@ sub do_installer_routines print `"$path" --host $host --user $root_user --password="$root_password" -N -B -e "FLUSH PRIVILEGES"`; } - my $world_path = "world"; - if (-e "bin/world") { - $world_path = "bin/world"; - } - elsif (-e "bin/world.exe") { - $world_path = "bin/world.exe"; - } - #::: Get Binary DB version if ($OS eq "Windows") { @db_version = split(': ', `"$world_path" db_version`); @@ -592,15 +591,6 @@ sub check_for_input sub check_for_world_bootup_database_update { - - my $world_path = "world"; - if (-e "bin/world") { - $world_path = "bin/world"; - } - elsif (-e "bin/world.exe") { - $world_path = "bin/world.exe"; - } - $binary_database_version = 0; $local_database_version = 0; diff --git a/world/login_server.cpp b/world/login_server.cpp index b4ab5b61f..aed471ce2 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -490,7 +490,7 @@ bool LoginServer::Connect() [this](EQ::Net::ServertalkClient *client) { if (client) { LogInfo( - "Connected to Loginserver: [{0}:{1}]", + "Connected to Loginserver [{0}:{1}]", m_loginserver_address, m_loginserver_port ); @@ -499,7 +499,6 @@ bool LoginServer::Connect() zoneserver_list.SendLSZones(); m_statusupdate_timer = std::make_unique( - LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) { SendStatus(); } diff --git a/world/main.cpp b/world/main.cpp index b7e297b76..51b3baff7 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -95,6 +95,8 @@ union semun { #include "world_event_scheduler.h" #include "shared_task_manager.h" #include "world_boot.h" +#include "../common/path_manager.h" + ZoneStore zone_store; ClientList client_list; @@ -115,6 +117,7 @@ const WorldConfig *Config; EQEmuLogSys LogSys; WorldContentService content_service; WebInterfaceList web_interface; +PathManager path; void CatchSignal(int sig_num); @@ -138,6 +141,8 @@ int main(int argc, char **argv) LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + path.LoadPaths(); + if (WorldBoot::HandleCommandInput(argc, argv)) { return 0; } diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 546789d3e..a6df2ead1 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -25,6 +25,7 @@ #include "zoneserver.h" #include "../common/ip_util.h" #include "../common/zone_store.h" +#include "../common/path_manager.h" extern ZSList zoneserver_list; extern WorldConfig Config; @@ -169,14 +170,14 @@ int get_file_size(const std::string &filename) // path to file void WorldBoot::CheckForServerScript(bool force_download) { - const std::string file = "eqemu_server.pl"; + const std::string file = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); std::ifstream f(file); /* Fetch EQEmu Server script */ if (!f || get_file_size(file) < 100 || force_download) { if (force_download) { - std::remove("eqemu_server.pl"); + std::remove(fmt::format("{}/eqemu_server.pl", path.GetServerPath()).c_str()); } /* Delete local before fetch */ std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl; @@ -199,13 +200,15 @@ void WorldBoot::CheckForServerScript(bool force_download) if (auto res = r.Get(u.get_path().c_str())) { if (res->status == 200) { // write file - std::ofstream out("eqemu_server.pl"); + + std::string script = fmt::format("{}/eqemu_server.pl", path.GetServerPath()); + std::ofstream out(script); out << res->body; out.close(); #ifdef _WIN32 #else - system("chmod 755 eqemu_server.pl"); - system("chmod +x eqemu_server.pl"); + system(fmt::format("chmod 755 {}", script).c_str()); + system(fmt::format("chmod +x {}", script).c_str()); #endif } } @@ -216,7 +219,8 @@ void WorldBoot::CheckForXMLConfigUpgrade() { if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) { CheckForServerScript(true); - if (system("perl eqemu_server.pl convert_xml")) {} + std::string command = fmt::format("perl {}/eqemu_server.pl convert_xml", path.GetServerPath()); + if (system(command.c_str())) {} } else { CheckForServerScript(); @@ -291,6 +295,7 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv) // logging system init auto logging = LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings(); if (RuleB(Logging, WorldGMSayLogging)) { diff --git a/world/world_config.h b/world/world_config.h index 2a274ed29..73b618b74 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -46,13 +46,13 @@ public: } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_world_config != nullptr) delete _world_config; _world_config=new WorldConfig; _config=_world_config; - return _config->parseFile(); + return _config->parseFile(path); } // Accessors for the static private object diff --git a/zone/command.cpp b/zone/command.cpp index 12120329d..6b16f0021 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -19,7 +19,7 @@ #include "../common/strings.h" #include "../common/say_link.h" #include "../common/net/eqstream.h" -#include "../common/file_util.h" +#include "../common/file.h" #include "../common/repositories/dynamic_zones_repository.h" #include "data_bucket.h" @@ -811,7 +811,7 @@ void command_hotfix(Client *c, const Seperator *sep) #ifdef WIN32 shared_memory_path = "shared_memory"; - if (file_exists("bin/shared_memory.exe")) { + if (File::Exists("bin/shared_memory.exe")) { shared_memory_path = "bin\\shared_memory.exe"; } @@ -827,7 +827,7 @@ void command_hotfix(Client *c, const Seperator *sep) if (system(hotfix_command.c_str())) {} #else shared_memory_path = "./shared_memory"; - if (file_exists("./bin/shared_memory")) { + if (File::Exists("./bin/shared_memory")) { shared_memory_path = "./bin/shared_memory"; } diff --git a/zone/embperl.cpp b/zone/embperl.cpp index e71854ced..3fd0f7bd9 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -18,6 +18,8 @@ Eglin #include "embperl.h" #include "embxs.h" #include "../common/features.h" +#include "../common/path_manager.h" + #ifndef GvCV_set #define GvCV_set(gv,cv) (GvCV(gv) = (cv)) #endif @@ -79,7 +81,7 @@ void Embperl::DoInit() { perl_run(my_perl); //a little routine we use a lot. - eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error + eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error //ruin the perl exit and command: eval_pv("sub my_exit {}",TRUE); @@ -146,11 +148,11 @@ void Embperl::DoInit() { //should probably read the directory in c, instead, so that //I can echo filenames as I do it, but c'mon... I'm lazy and this 1 line reads in all the plugins std::string perl_command = - "if(opendir(D,'" + Config->PluginDir +"')) { " + "if(opendir(D,'" + path.GetPluginsPath() +"')) { " " my @d = readdir(D);" " closedir(D);" " foreach(@d){ " - " main::eval_file('plugin','" + Config->PluginDir + "/'.$_)if/\\.pl$/;" + " main::eval_file('plugin','" + path.GetPluginsPath() + "/'.$_)if/\\.pl$/;" " }" "}"; eval_pv(perl_command.c_str(),FALSE); diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index cbbb69ece..b29150712 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -39,6 +39,7 @@ #include "lua_general.h" #include "lua_encounter.h" #include "lua_stat_bonuses.h" +#include "../common/path_manager.h" #ifdef BOTS #include "lua_bot.h" @@ -927,11 +928,11 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string module_path = lua_tostring(L,-1); - module_path += ";./" + Config->LuaModuleDir + "?.lua;./" + Config->LuaModuleDir + "?/init.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/?.lua;" + path.GetLuaModulesPath() + "/?/init.lua"; // luarock paths using lua_modules as tree // to path it adds foo/share/lua/5.1/?.lua and foo/share/lua/5.1/?/init.lua - module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?.lua"; - module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?/init.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/share/lua/" + lua_version + "/?.lua"; + module_path += ";" + path.GetLuaModulesPath() + "/share/lua/" + lua_version + "/?/init.lua"; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "path"); @@ -940,10 +941,10 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "cpath"); module_path = lua_tostring(L, -1); - module_path += ";./" + Config->LuaModuleDir + "?" + libext; + module_path += ";" + path.GetLuaModulesPath() + "/?" + libext; // luarock paths using lua_modules as tree // luarocks adds foo/lib/lua/5.1/?.so for cpath - module_path += ";./" + Config->LuaModuleDir + "lib/lua/" + lua_version + "/?" + libext; + module_path += ";" + path.GetLuaModulesPath() + "/lib/lua/" + lua_version + "/?" + libext; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "cpath"); @@ -951,17 +952,14 @@ void LuaParser::ReloadQuests() { MapFunctions(L); - //load init - std::string path = Config->QuestDir; - path += "/"; - path += QUEST_GLOBAL_DIRECTORY; - path += "/script_init.lua"; + // load init + std::string filename = fmt::format("{}/{}/script_init.lua", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); - FILE *f = fopen(path.c_str(), "r"); + FILE *f = fopen(filename.c_str(), "r"); if(f) { fclose(f); - if(luaL_dofile(L, path.c_str())) { + if(luaL_dofile(L, filename.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); } @@ -969,12 +967,13 @@ void LuaParser::ReloadQuests() { //zone init - always loads after global if(zone) { - std::string zone_script = Config->QuestDir; - zone_script += "/"; - zone_script += zone->GetShortName(); - zone_script += "/script_init_v"; - zone_script += std::to_string(zone->GetInstanceVersion()); - zone_script += ".lua"; + std::string zone_script = fmt::format( + "{}/{}/script_init_v{}.lua", + path.GetQuestsPath(), + zone->GetShortName(), + zone->GetInstanceVersion() + ); + f = fopen(zone_script.c_str(), "r"); if(f) { fclose(f); @@ -985,10 +984,8 @@ void LuaParser::ReloadQuests() { } } else { - zone_script = Config->QuestDir; - zone_script += "/"; - zone_script += zone->GetShortName(); - zone_script += "/script_init.lua"; + zone_script = fmt::format("{}/{}/script_init.lua", path.GetQuestsPath(), zone->GetShortName()); + f = fopen(zone_script.c_str(), "r"); if (f) { fclose(f); @@ -1001,20 +998,20 @@ void LuaParser::ReloadQuests() { } } - FILE *load_order = fopen("mods/load_order.txt", "r"); + FILE *load_order = fopen(fmt::format("{}/load_order.txt", path.GetLuaModsPath()).c_str(), "r"); if (load_order) { char file_name[256] = { 0 }; while (fgets(file_name, 256, load_order) != nullptr) { - for (int i = 0; i < 256; ++i) { - auto c = file_name[i]; + for (char & i : file_name) { + auto c = i; if (c == '\n' || c == '\r' || c == ' ') { - file_name[i] = 0; + i = 0; break; } } - LoadScript("mods/" + std::string(file_name), file_name); - mods_.push_back(LuaMod(L, this, file_name)); + LoadScript(fmt::format("{}{}", path.GetLuaModsPath(), std::string(file_name)), file_name); + mods_.emplace_back(L, this, file_name); } fclose(load_order); @@ -1107,8 +1104,8 @@ bool LuaParser::HasEncounterSub(const std::string& package_name, QuestEventID ev { auto it = lua_encounter_events_registered.find(package_name); if (it != lua_encounter_events_registered.end()) { - for (auto riter = it->second.begin(); riter != it->second.end(); ++riter) { - if (riter->event_id == evt) { + for (auto & riter : it->second) { + if (riter.event_id == evt) { return true; } } diff --git a/zone/main.cpp b/zone/main.cpp index 471b994af..b2ef07076 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -78,7 +78,6 @@ #else #include #include "../common/unix.h" -#include "zone_event_scheduler.h" #endif @@ -89,21 +88,28 @@ volatile bool RunLoops = true; extern volatile bool is_zone_loaded; -EntityList entity_list; +#include "zone_event_scheduler.h" +#include "../common/file.h" +#include "../common/path_manager.h" + +EntityList entity_list; WorldServer worldserver; -ZoneStore zone_store; -uint32 numclients = 0; -char errorname[32]; -extern Zone* zone; -npcDecayTimes_Struct npcCorpseDecayTimes[100]; -TitleManager title_manager; -QueryServ *QServ = 0; -TaskManager *task_manager = 0; -NpcScaleManager *npc_scale_manager; -QuestParserCollection *parse = 0; -EQEmuLogSys LogSys; -ZoneEventScheduler event_scheduler; -WorldContentService content_service; +ZoneStore zone_store; +uint32 numclients = 0; +char errorname[32]; +extern Zone *zone; + +npcDecayTimes_Struct npcCorpseDecayTimes[100]; +TitleManager title_manager; +QueryServ *QServ = 0; +TaskManager *task_manager = 0; +NpcScaleManager *npc_scale_manager; +QuestParserCollection *parse = 0; +EQEmuLogSys LogSys; +ZoneEventScheduler event_scheduler; +WorldContentService content_service; +PathManager path; + const SPDat_Spell_Struct* spells; int32 SPDAT_RECORDS = -1; const ZoneConfig *Config; @@ -121,6 +127,8 @@ int main(int argc, char** argv) { set_exception_handler(); + path.LoadPaths(); + #ifdef USE_MAP_MMFS if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) { if (!ZoneConfig::LoadConfig()) @@ -255,6 +263,7 @@ int main(int argc, char** argv) { /* Register Log System and Settings */ LogSys.SetDatabase(&database) + ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings() ->SetGMSayHandler(&Zone::GMSayHookCallBackProcess) ->StartFileLogs(); diff --git a/zone/map.cpp b/zone/map.cpp index 3d35aeabc..c92710fa8 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -5,6 +5,8 @@ #include "map.h" #include "raycast_mesh.h" #include "zone.h" +#include "../common/file.h" +#include "../common/path_manager.h" #include #include @@ -46,16 +48,16 @@ float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const { if(hit) { return result->z; } - + // Find nearest Z above us - + to.z = -BEST_Z_INVALID; hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); if (hit) { return result->z; } - + return BEST_Z_INVALID; } @@ -64,25 +66,25 @@ float Map::FindClosestZ(glm::vec3 &start, glm::vec3 *result) const { // if (!imp) return false; - + float ClosestZ = BEST_Z_INVALID; - + glm::vec3 tmp; if (!result) result = &tmp; - + glm::vec3 from(start.x, start.y, start.z); glm::vec3 to(start.x, start.y, BEST_Z_INVALID); float hit_distance; bool hit = false; - + // first check is below us hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); if (hit) { ClosestZ = result->z; - + } - + // Find nearest Z above us to.z = -BEST_Z_INVALID; hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); @@ -103,7 +105,7 @@ bool Map::LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::ve bool Map::LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const { if (!imp) return false; - + float z = BEST_Z_INVALID; glm::vec3 step; glm::vec3 cur; @@ -200,28 +202,9 @@ bool Map::DoCollisionCheck(glm::vec3 myloc, glm::vec3 oloc, glm::vec3 &outnorm, return imp->rm->raycast((const RmReal*)&myloc, (const RmReal*)&oloc, nullptr, (RmReal *)&outnorm, (RmReal *)&distance); } -inline bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); -} - Map *Map::LoadMapFile(std::string file) { - - std::string filename = ""; - if (file_exists("maps")) { - filename = "maps"; - } - else if (file_exists("Maps")) { - filename = "Maps"; - } - else { - filename = Config->MapDir; - } - std::transform(file.begin(), file.end(), file.begin(), ::tolower); - filename += "/base/"; - filename += file; - filename += ".map"; + std::string filename = fmt::format("{}/base/{}.map", path.GetMapsPath(), file); LogInfo("Attempting to load Map File [{}]", filename.c_str()); @@ -308,19 +291,19 @@ bool Map::LoadV1(FILE *f) { uint32 face_count; uint16 node_count; uint32 facelist_count; - + if(fread(&face_count, sizeof(face_count), 1, f) != 1) { return false; } - + if(fread(&node_count, sizeof(node_count), 1, f) != 1) { return false; } - + if(fread(&facelist_count, sizeof(facelist_count), 1, f) != 1) { return false; } - + std::vector verts; std::vector indices; for(uint32 i = 0; i < face_count; ++i) { @@ -354,22 +337,22 @@ bool Map::LoadV1(FILE *f) { verts.push_back(c); indices.push_back((uint32)sz + 2); } - + if(imp) { imp->rm->release(); imp->rm = nullptr; } else { imp = new impl; } - + imp->rm = createRaycastMesh((RmUint32)verts.size(), (const RmReal*)&verts[0], face_count, &indices[0]); - + if(!imp->rm) { delete imp; imp = nullptr; return false; } - + return true; } @@ -978,7 +961,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to load Map MMF file: [{}] - f@file_version", mmf_file_name.c_str()); return false; } - + uint32 rm_buffer_size; if (fread(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { fclose(f); @@ -1011,7 +994,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to load Map MMF file: [{}] - f@mmf_buffer", mmf_file_name.c_str()); return false; } - + fclose(f); std::vector rm_buffer(rm_buffer_size); @@ -1055,14 +1038,14 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}]", mmf_file_name.c_str()); return false; } - + FILE* f = fopen(mmf_file_name.c_str(), "rb"); if (f) { fclose(f); if (!force_mmf_overwrite) return true; } - + std::vector rm_buffer; // size set in MyRaycastMesh::serialize() serializeRaycastMesh(imp->rm, rm_buffer); if (rm_buffer.empty()) { @@ -1074,19 +1057,19 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size()); std::vector mmf_buffer(mmf_buffer_size); - + mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); if (!mmf_buffer_size) { LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str()); return false; } - + f = fopen(mmf_file_name.c_str(), "wb"); if (!f) { LogInfo("Failed to save Map MMF file: [{}] - could not open file", mmf_file_name.c_str()); return false; } - + uint32 file_version = 0; if (fwrite(&file_version, sizeof(uint32), 1, f) != 1) { fclose(f); @@ -1094,7 +1077,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}] - f@file_version", mmf_file_name.c_str()); return false; } - + if (fwrite(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { fclose(f); std::remove(mmf_file_name.c_str()); @@ -1116,7 +1099,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) LogInfo("Failed to save Map MMF file: [{}] - f@mmf_buffer_size", mmf_file_name.c_str()); return false; } - + if (fwrite(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) { fclose(f); std::remove(mmf_file_name.c_str()); @@ -1125,7 +1108,7 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) } fclose(f); - + return true; } diff --git a/zone/pathfinder_interface.cpp b/zone/pathfinder_interface.cpp index 68696b9d6..3a5c07506 100644 --- a/zone/pathfinder_interface.cpp +++ b/zone/pathfinder_interface.cpp @@ -3,15 +3,16 @@ #include "pathfinder_null.h" #include "pathfinder_nav_mesh.h" #include "pathfinder_waypoint.h" +#include "../common/path_manager.h" #include #include IPathfinder *IPathfinder::Load(const std::string &zone) { struct stat statbuffer; - std::string navmesh_path = fmt::format("maps/nav/{0}.nav", zone); + std::string navmesh_path = fmt::format("{}/maps/nav/{}.nav", path.GetServerPath(), zone); if (stat(navmesh_path.c_str(), &statbuffer) == 0) { return new PathfinderNavmesh(navmesh_path); } - + return new PathfinderNull(); } diff --git a/zone/pathfinder_nav_mesh.cpp b/zone/pathfinder_nav_mesh.cpp index c644a45e0..9877b8323 100644 --- a/zone/pathfinder_nav_mesh.cpp +++ b/zone/pathfinder_nav_mesh.cpp @@ -34,19 +34,19 @@ PathfinderNavmesh::~PathfinderNavmesh() IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags) { partial = false; - + if (!m_impl->nav_mesh) { return IPath(); } - + if (!m_impl->query) { m_impl->query = dtAllocNavMeshQuery(); } - + m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes)); glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 dest_location(end.x, end.z, end.y); - + dtQueryFilter filter; filter.setIncludeFlags(flags); filter.setAreaCost(0, 1.0f); //Normal @@ -59,48 +59,48 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl filter.setAreaCost(8, 1.0f); //General Area filter.setAreaCost(9, 0.1f); //Portal filter.setAreaCost(10, 0.1f); //Prefer - + dtPolyRef start_ref; dtPolyRef end_ref; glm::vec3 ext(5.0f, 100.0f, 5.0f); - + m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0); - + if (!start_ref || !end_ref) { return IPath(); } - + int npoly = 0; dtPolyRef path[1024] = { 0 }; auto status = m_impl->query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, 1024); - + if (npoly) { glm::vec3 epos = dest_location; if (path[npoly - 1] != end_ref) { m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0); partial = true; - + auto dist = DistanceSquared(epos, current_location); if (dist < 10000.0f) { stuck = true; } } - + float straight_path[2048 * 3]; unsigned char straight_path_flags[2048]; - + int n_straight_polys; dtPolyRef straight_path_polys[2048]; - + status = m_impl->query->findStraightPath(¤t_location[0], &epos[0], path, npoly, straight_path, straight_path_flags, straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS); - + if (dtStatusFailed(status)) { return IPath(); } - + if (n_straight_polys) { IPath Route; for (int i = 0; i < n_straight_polys; ++i) @@ -109,9 +109,9 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl node.x = straight_path[i * 3]; node.z = straight_path[i * 3 + 1]; node.y = straight_path[i * 3 + 2]; - + Route.push_back(node); - + unsigned short flag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (flag & 512) { @@ -119,11 +119,11 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl } } } - + return Route; } } - + IPath Route; Route.push_back(end); return Route; @@ -132,19 +132,19 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts) { partial = false; - + if (!m_impl->nav_mesh) { return IPath(); } - + if (!m_impl->query) { m_impl->query = dtAllocNavMeshQuery(); } - + m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes)); glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 dest_location(end.x, end.z, end.y); - + dtQueryFilter filter; filter.setIncludeFlags(opts.flags); filter.setAreaCost(0, opts.flag_cost[0]); //Normal @@ -157,83 +157,83 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm filter.setAreaCost(8, opts.flag_cost[7]); //General Area filter.setAreaCost(9, opts.flag_cost[8]); //Portal filter.setAreaCost(10, opts.flag_cost[9]); //Prefer - + static const int max_polys = 256; dtPolyRef start_ref; dtPolyRef end_ref; glm::vec3 ext(10.0f, 200.0f, 10.0f); - + m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0); - + if (!start_ref || !end_ref) { return IPath(); } - + int npoly = 0; dtPolyRef path[max_polys] = { 0 }; auto status = m_impl->query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, max_polys); - + if (npoly) { glm::vec3 epos = dest_location; if (path[npoly - 1] != end_ref) { m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0); partial = true; - + auto dist = DistanceSquared(epos, current_location); if (dist < 10000.0f) { stuck = true; } } - + int n_straight_polys; glm::vec3 straight_path[max_polys]; unsigned char straight_path_flags[max_polys]; dtPolyRef straight_path_polys[max_polys]; - + auto status = m_impl->query->findStraightPath(¤t_location[0], &epos[0], path, npoly, (float*)&straight_path[0], straight_path_flags, straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS); - + if (dtStatusFailed(status)) { return IPath(); } - + if (n_straight_polys) { if (opts.smooth_path) { IPath Route; - + //Add the first point { auto &flag = straight_path_flags[0]; if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { auto &p = straight_path[0]; - + Route.push_back(glm::vec3(p.x, p.z, p.y)); } else { auto &p = straight_path[0]; - + float h = 0.0f; if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, p, &h))) { p.y = h + opts.offset; } - + Route.push_back(glm::vec3(p.x, p.z, p.y)); } } - + for (int i = 0; i < n_straight_polys - 1; ++i) { auto &flag = straight_path_flags[i]; - + if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { auto &poly = straight_path_polys[i]; - + auto &p2 = straight_path[i + 1]; glm::vec3 node(p2.x, p2.z, p2.y); Route.push_back(node); - + unsigned short pflag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &pflag))) { if (pflag & 512) { @@ -248,12 +248,12 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm auto dir = glm::normalize(p2 - p1); float total = 0.0f; glm::vec3 previous_pt = p1; - + while (total < dist) { glm::vec3 current_pt; float dist_to_move = opts.step_size; float ff = opts.step_size / 2.0f; - + if (total + dist_to_move + ff >= dist) { current_pt = p2; total = dist; @@ -262,18 +262,18 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm total += dist_to_move; current_pt = p1 + dir * total; } - + float h = 0.0f; if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, current_pt, &h))) { current_pt.y = h + opts.offset; } - + Route.push_back(glm::vec3(current_pt.x, current_pt.z, current_pt.y)); previous_pt = current_pt; } } } - + return Route; } else { @@ -283,7 +283,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm auto ¤t = straight_path[i]; glm::vec3 node(current.x, current.z, current.y); Route.push_back(node); - + unsigned short flag = 0; if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (flag & 512) { @@ -291,7 +291,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm } } } - + return Route; } } diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index a9f55df7b..a6b3f775c 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -25,7 +25,7 @@ #include "quest_interface.h" #include "zone.h" #include "questmgr.h" -#include "zone_config.h" +#include "../common/path_manager.h" #include @@ -166,7 +166,7 @@ bool QuestParserCollection::PlayerHasEncounterSub(QuestEventID evt) { bool QuestParserCollection::PlayerHasQuestSubLocal(QuestEventID evt) { if(_player_quest_status == QuestUnloaded) { - std::string filename; + std::string filename; QuestInterface *qi = GetQIByPlayerQuest(filename); if(qi) { _player_quest_status = qi->GetIdentifier(); @@ -182,7 +182,7 @@ bool QuestParserCollection::PlayerHasQuestSubLocal(QuestEventID evt) { bool QuestParserCollection::PlayerHasQuestSubGlobal(QuestEventID evt) { if(_global_player_quest_status == QuestUnloaded) { - std::string filename; + std::string filename; QuestInterface *qi = GetQIByGlobalPlayerQuest(filename); if(qi) { _global_player_quest_status = qi->GetIdentifier(); @@ -292,7 +292,7 @@ int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std:: int rd = DispatchEventNPC(evt, npc, init, data, extra_data, extra_pointers); int rl = EventNPCLocal(evt, npc, init, data, extra_data, extra_pointers); int rg = EventNPCGlobal(evt, npc, init, data, extra_data, extra_pointers); - + //Local quests returning non-default values have priority over global quests if(rl != 0) { return rl; @@ -301,7 +301,7 @@ int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std:: } else if(rd != 0) { return rd; } - + return 0; } @@ -333,7 +333,7 @@ int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, if(_global_npc_quest_status != QuestUnloaded && _global_npc_quest_status != QuestFailedToLoad) { auto qiter = _interfaces.find(_global_npc_quest_status); return qiter->second->EventGlobalNPC(evt, npc, init, data, extra_data, extra_pointers); - } + } else if(_global_npc_quest_status != QuestFailedToLoad){ std::string filename; QuestInterface *qi = GetQIByGlobalNPCQuest(filename); @@ -353,7 +353,7 @@ int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::st int rd = DispatchEventPlayer(evt, client, data, extra_data, extra_pointers); int rl = EventPlayerLocal(evt, client, data, extra_data, extra_pointers); int rg = EventPlayerGlobal(evt, client, data, extra_data, extra_pointers); - + //Local quests returning non-default values have priority over global quests if(rl != 0) { return rl; @@ -362,7 +362,7 @@ int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::st } else if(rd != 0) { return rd; } - + return 0; } @@ -376,7 +376,7 @@ int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, st qi->LoadPlayerScript(filename); return qi->EventPlayer(evt, client, data, extra_data, extra_pointers); } - } else { + } else { if(_player_quest_status != QuestFailedToLoad) { auto iter = _interfaces.find(_player_quest_status); return iter->second->EventPlayer(evt, client, data, extra_data, extra_pointers); @@ -395,7 +395,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s qi->LoadGlobalPlayerScript(filename); return qi->EventGlobalPlayer(evt, client, data, extra_data, extra_pointers); } - } else { + } else { if(_global_player_quest_status != QuestFailedToLoad) { auto iter = _interfaces.find(_global_player_quest_status); return iter->second->EventGlobalPlayer(evt, client, data, extra_data, extra_pointers); @@ -407,7 +407,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s int QuestParserCollection::EventItem(QuestEventID evt, Client *client, EQ::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { // needs pointer validation check on 'item' argument - + std::string item_script; if(item->GetItem()->ScriptFileID != 0) { item_script = "script_"; @@ -467,7 +467,7 @@ int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client return ret; } return DispatchEventSpell(evt, npc, client, spell_id, data, extra_data, extra_pointers); - } + } else if (_spell_quest_status[spell_id] != QuestFailedToLoad) { std::string filename; QuestInterface *qi = GetQIBySpellQuest(spell_id, filename); @@ -513,11 +513,9 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte } QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string &filename) { - //first look for /quests/zone/npcid.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += itoa(npcid); + // first look for /quests/zone/npcid.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), zone->GetShortName(), npcid); + std::string tmp; FILE *f = nullptr; @@ -549,7 +547,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } else{ npc_name = npc_type->name; - } + } int sz = static_cast(npc_name.length()); for(int i = 0; i < sz; ++i) { if(npc_name[i] == '`') { @@ -557,10 +555,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } } - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += npc_name; + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), zone->GetShortName(), npc_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -578,11 +573,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //third look for /quests/global/npcid.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += itoa(npcid); + // third look for /quests/global/npcid.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, npcid); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -599,11 +591,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //fourth look for /quests/global/npcname.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += npc_name; + // fourth look for /quests/global/npcname.ext (precedence) + filename = fmt::format("{}/{}/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, npc_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -620,11 +609,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //fifth look for /quests/zone/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "default"; + // fifth look for /quests/zone/default.ext (precedence) + filename = fmt::format("{}/{}/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -641,11 +627,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string ++iter; } - //last look for /quests/global/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "default"; + // last look for /quests/global/default.ext (precedence) + filename = fmt::format("{}/{}/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -669,12 +652,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) if(!zone || !zone->IsLoaded()) return nullptr; - //first look for /quests/zone/player_v[instance_version].ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "player_v"; - filename += itoa(zone->GetInstanceVersion()); + // first look for /quests/zone/player_v[instance_version].ext (precedence) + filename = fmt::format("{}/{}/player_v{}", path.GetQuestsPath(), zone->GetShortName(), zone->GetInstanceVersion()); std::string tmp; FILE *f = nullptr; @@ -694,11 +673,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) ++iter; } - //second look for /quests/zone/player.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/"; - filename += "player"; + // second look for /quests/zone/player.ext (precedence) + filename = fmt::format("{}/{}/player", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -716,11 +692,8 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) ++iter; } - //third look for /quests/global/player.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "player"; + // third look for /quests/global/player.ext (precedence) + filename = fmt::format("{}/{}/player", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -742,15 +715,11 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filename) { // simply look for /quests/global/global_npc.ext - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "global_npc"; + filename = fmt::format("{}/{}/global_npc", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); + std::string tmp; FILE *f = nullptr; - - auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -772,11 +741,8 @@ QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filena } QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &filename) { - //first look for /quests/global/player.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/"; - filename += "global_player"; + // first look for /quests/global/player.ext (precedence) + filename = fmt::format("{}/{}/global_player", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); std::string tmp; FILE *f = nullptr; @@ -801,10 +767,7 @@ QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &fil QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::string &filename) { //first look for /quests/zone/spells/spell_id.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/spells/"; - filename += itoa(spell_id); + filename = fmt::format("{}/{}/spells/{}", path.GetQuestsPath(), zone->GetShortName(), spell_id); std::string tmp; FILE *f = nullptr; @@ -824,11 +787,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //second look for /quests/global/spells/spell_id.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/spells/"; - filename += itoa(spell_id); + // second look for /quests/global/spells/spell_id.ext (precedence) + filename = fmt::format("{}/{}/spells/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, spell_id); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -846,10 +806,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //third look for /quests/zone/spells/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/spells/default"; + // third look for /quests/zone/spells/default.ext (precedence) + filename = fmt::format("{}/{}/spells/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -867,10 +825,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s ++iter; } - //last look for /quests/global/spells/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/spells/default"; + // last look for /quests/global/spells/default.ext (precedence) + filename = fmt::format("{}/{}/spells/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -892,11 +848,8 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s } QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, std::string &filename) { - //first look for /quests/zone/items/item_script.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/items/"; - filename += item_script; + // first look for /quests/zone/items/item_script.ext (precedence) + filename = fmt::format("{}/{}/items/{}", path.GetQuestsPath(), zone->GetShortName(), item_script); std::string tmp; FILE *f = nullptr; @@ -915,12 +868,9 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - - //second look for /quests/global/items/item_script.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/items/"; - filename += item_script; + + // second look for /quests/global/items/item_script.ext (precedence) + filename = fmt::format("{}/{}/items/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, item_script); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -938,11 +888,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - //third look for /quests/zone/items/default.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/items/default"; - + // third look for /quests/zone/items/default.ext (precedence) + filename = fmt::format("{}/{}/items/default", path.GetQuestsPath(), zone->GetShortName()); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -959,11 +906,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, ++iter; } - //last look for /quests/global/items/default.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/items/default"; - + // last look for /quests/global/items/default.ext (precedence) + filename = fmt::format("{}/{}/items/default", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; @@ -984,11 +928,8 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, } QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encounter_name, std::string &filename) { - //first look for /quests/zone/encounters/encounter_name.ext (precedence) - filename = Config->QuestDir; - filename += zone->GetShortName(); - filename += "/encounters/"; - filename += encounter_name; + // first look for /quests/zone/encounters/encounter_name.ext (precedence) + filename = fmt::format("{}/{}/encounters/{}", path.GetQuestsPath(), zone->GetShortName(), encounter_name); std::string tmp; FILE *f = nullptr; @@ -1007,12 +948,9 @@ QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encount ++iter; } - - //second look for /quests/global/encounters/encounter_name.ext (precedence) - filename = Config->QuestDir; - filename += QUEST_GLOBAL_DIRECTORY; - filename += "/encounters/"; - filename += encounter_name; + + // second look for /quests/global/encounters/encounter_name.ext (precedence) + filename = fmt::format("{}/{}/encounters/{}", path.GetQuestsPath(), QUEST_GLOBAL_DIRECTORY, encounter_name); iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { @@ -1099,7 +1037,7 @@ int QuestParserCollection::DispatchEventSpell(QuestEventID evt, NPC* npc, Client } void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings) { - + LogInfo("Loading Perl Event Export Settings..."); /* Write Defaults First (All Enabled) */ diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index acf7d38f2..e72c527ef 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -192,7 +192,7 @@ void QuestManager::summonitem(uint32 itemid, int16 charges) { void QuestManager::write(const char *file, const char *str) { FILE * pFile; - pFile = fopen (file, "a"); + pFile = fopen (fmt::format("{}/{}", path.GetServerPath(), file).c_str(), "a"); if(!pFile) return; fprintf(pFile, "%s\n", str); diff --git a/zone/water_map.cpp b/zone/water_map.cpp index ec5575f24..b7d367c47 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -4,21 +4,14 @@ #include "water_map_v1.h" #include "water_map_v2.h" #include "../common/eqemu_logsys.h" +#include "../common/file.h" +#include "../common/path_manager.h" #include #include #include #include -/** - * @param name - * @return - */ -inline bool file_exists(const std::string& name) { - std::ifstream f(name.c_str()); - return f.good(); -} - /** * @param zone_name * @return @@ -26,18 +19,7 @@ inline bool file_exists(const std::string& name) { WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { std::transform(zone_name.begin(), zone_name.end(), zone_name.begin(), ::tolower); - std::string filename; - if (file_exists("maps")) { - filename = "maps"; - } - else if (file_exists("Maps")) { - filename = "Maps"; - } - else { - filename = Config->MapDir; - } - - std::string file_path = filename + "/water/" + zone_name + std::string(".wtr"); + std::string file_path = fmt::format("{}/water/{}.wtr", path.GetMapsPath(), zone_name); LogDebug("Attempting to load water map with path [{}]", file_path.c_str()); FILE *f = fopen(file_path.c_str(), "rb"); if(f) { @@ -48,19 +30,19 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { fclose(f); return nullptr; } - + if(strncmp(magic, "EQEMUWATER", 10)) { LogDebug("Failed to load water map, bad magic string in header"); fclose(f); return nullptr; } - + if(fread(&version, sizeof(version), 1, f) != 1) { LogDebug("Failed to load water map, error reading version"); fclose(f); return nullptr; } - + LogDebug("Attempting to V[{}] load water map [{}]", version, file_path.c_str()); if(version == 1) { auto wm = new WaterMapV1(); @@ -90,7 +72,7 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { return nullptr; } } - + LogDebug("Failed to load water map, could not open file for reading [{}]", file_path.c_str()); return nullptr; } diff --git a/zone/zone_config.h b/zone/zone_config.h index 43f5b723c..a8e7401b6 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -43,13 +43,13 @@ class ZoneConfig : public EQEmuConfig { } // Load the config - static bool LoadConfig() { + static bool LoadConfig(const std::string& path = "") { if (_zone_config != nullptr) delete _zone_config; _zone_config=new ZoneConfig; _config=_zone_config; - return _config->parseFile(); + return _config->parseFile(path); } // Accessors for the static private object