[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>
This commit is contained in:
Chris Miles 2022-09-28 04:08:59 -05:00 committed by GitHub
parent 19791195e5
commit f8e7576ae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 641 additions and 502 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -26,7 +26,7 @@
#include "../strings.h"
#include "../eqemu_config.h"
#include "../database_schema.h"
#include "../file_util.h"
#include "../file.h"
#include <ctime>
@ -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()) {

View File

@ -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 <iomanip>
#include <iostream>
@ -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;
}

View File

@ -20,7 +20,9 @@
#include "json/json.h"
#include "linked_list.h"
#include "path_manager.h"
#include <fstream>
#include <fmt/format.h>
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();

View File

@ -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;
}

View File

@ -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);

View File

@ -19,7 +19,7 @@
*/
#include <fstream>
#include "file_util.h"
#include "file.h"
#ifdef _WINDOWS
#include <direct.h>
@ -35,38 +35,48 @@
#endif
#include <fmt/format.h>
#include <filesystem>
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();
}

View File

@ -18,16 +18,21 @@
*
*/
#ifndef EQEMU_FILE_UTIL_H
#define EQEMU_FILE_UTIL_H
#ifndef EQEMU_FILE_H
#define EQEMU_FILE_H
#include <filesystem>
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

View File

@ -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

View File

@ -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();

View File

@ -33,6 +33,9 @@
#include <sys/stat.h>
#endif
#include <filesystem>
namespace fs = std::filesystem;
namespace EQ {
struct MemoryMappedFile::Implementation {

View File

@ -32,6 +32,7 @@
#include "../inventory_profile.h"
#include "rof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@ -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;

View File

@ -32,6 +32,7 @@
#include "../inventory_profile.h"
#include "rof2_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@ -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;

View File

@ -32,6 +32,7 @@
#include "../item_instance.h"
#include "sod_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@ -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;

View File

@ -32,6 +32,7 @@
#include "../item_instance.h"
#include "sof_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@ -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;

View File

@ -32,6 +32,7 @@
#include "../strings.h"
#include "../item_instance.h"
#include "titanium_structs.h"
#include "../path_manager.h"
#include <sstream>
@ -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;

View File

@ -32,6 +32,7 @@
#include "../item_instance.h"
#include "uf_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include <iostream>
#include <sstream>
@ -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;

133
common/path_manager.cpp Normal file
View File

@ -0,0 +1,133 @@
#include "path_manager.h"
#include "file.h"
#include "eqemu_logsys.h"
#include "eqemu_config.h"
#include "strings.h"
#include <filesystem>
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;
}

35
common/path_manager.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef EQEMU_PATH_MANAGER_H
#define EQEMU_PATH_MANAGER_H
#include <string>
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

View File

@ -67,6 +67,8 @@ std::string GetPlatformName()
return "Launch";
case EQEmuExePlatform::ExePlatformHC:
return "HC";
case EQEmuExePlatform::ExePlatformTests:
return "Tests";
default:
return "";
}

View File

@ -36,7 +36,8 @@ enum EQEmuExePlatform
ExePlatformSharedMemory,
ExePlatformClientImport,
ExePlatformClientExport,
ExePlatformHC
ExePlatformHC,
ExePlatformTests
};
void RegisterExecutablePlatform(EQEmuExePlatform p);

View File

@ -17,6 +17,7 @@
*/
#include "rulesys.h"
#include "eqemu_logsys.h"
#include "database.h"
#include "strings.h"
#include <cstdlib>

View File

@ -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<EQ::MemoryMappedFile>(file_name);
items_hash = std::make_unique<EQ::FixedMemoryHashSet<EQ::ItemData>>(static_cast<uint8*>(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<EQ::MemoryMappedFile>(file_name);
faction_hash = std::make_unique<EQ::FixedMemoryHashSet<NPCFactionList>>(static_cast<uint8*>(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<EQ::MemoryMappedFile>(new EQ::MemoryMappedFile(file_name));
faction_associations_hash = std::unique_ptr<EQ::FixedMemoryHashSet<FactionAssociations>>(
new EQ::FixedMemoryHashSet<FactionAssociations>(reinterpret_cast<uint8 *>(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<EQ::MemoryMappedFile>(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<EQ::MemoryMappedFile>(file_name);
LogInfo("[Shared Memory] Attempting to load file [{}]", file_name);
*records = *static_cast<uint32*>(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<EQ::MemoryMappedFile>(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<EQ::MemoryMappedFile>(file_name_lt);
loot_table_hash = std::make_unique<EQ::FixedMemoryVariableHashSet<LootTable_Struct>>(
static_cast<uint8*>(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<EQ::MemoryMappedFile>(file_name_ld);
loot_drop_hash = std::make_unique<EQ::FixedMemoryVariableHashSet<LootDrop_Struct>>(
static_cast<uint8*>(loot_drop_mmf->Get()),

View File

@ -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 <time.h>
EQEmuLogSys LogSys;
PathManager path;
bool RunLoops = false;

View File

@ -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()

View File

@ -11,6 +11,7 @@
#include "loginserver_webserver.h"
#include "loginserver_command_handler.h"
#include "../common/strings.h"
#include "../common/path_manager.h"
#include <time.h>
#include <stdlib.h>
#include <string>
@ -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();
}

View File

@ -31,6 +31,7 @@
#include "queryservconfig.h"
#include "lfguild.h"
#include "worldserver.h"
#include "../common/path_manager.h"
#include <list>
#include <signal.h>
#include <thread>
@ -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();

View File

@ -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);
}
};

View File

@ -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 <direct.h>
@ -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();

View File

@ -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)

View File

@ -20,6 +20,8 @@
#include <iostream>
#include <fstream>
#include <memory>
#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<Test::Output> 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;

View File

@ -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 <list>
#include <vector>
@ -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<EQ::Net::EQStream> stream) {

View File

@ -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();

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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<EQ::Timer>(
LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
SendStatus();
}

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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

View File

@ -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";
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -78,7 +78,6 @@
#else
#include <pthread.h>
#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();

View File

@ -5,6 +5,8 @@
#include "map.h"
#include "raycast_mesh.h"
#include "zone.h"
#include "../common/file.h"
#include "../common/path_manager.h"
#include <algorithm>
#include <map>
@ -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<glm::vec3> verts;
std::vector<uint32> 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<char> 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<char> 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<char> 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;
}

View File

@ -3,15 +3,16 @@
#include "pathfinder_null.h"
#include "pathfinder_nav_mesh.h"
#include "pathfinder_waypoint.h"
#include "../common/path_manager.h"
#include <fmt/format.h>
#include <sys/stat.h>
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();
}

View File

@ -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(&current_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, &current_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(&current_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(&current_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, &current_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(&current_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 &current = 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;
}
}

View File

@ -25,7 +25,7 @@
#include "quest_interface.h"
#include "zone.h"
#include "questmgr.h"
#include "zone_config.h"
#include "../common/path_manager.h"
#include <stdio.h>
@ -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<std::any> *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<int>(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) */

View File

@ -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);

View File

@ -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 <algorithm>
#include <cctype>
#include <stdio.h>
#include <string.h>
/**
* @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;
}

View File

@ -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