diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index c5c540f44..56b8ff989 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -20,9 +20,12 @@ #include "eqemu_config.h" #include "misc_functions.h" #include "strings.h" +#include "eqemu_logsys.h" +#include "json/json.hpp" #include #include +#include std::string EQEmuConfig::ConfigFile = "eqemu_config.json"; EQEmuConfig *EQEmuConfig::_config = nullptr; @@ -111,13 +114,12 @@ void EQEmuConfig::parse_config() DisableConfigChecks = true; } - /** - * UCS - */ - ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString(); - ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString()); - MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString(); - MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString()); + + + CheckUcsConfigConversion(); + + m_ucs_host = _root["server"]["ucs"].get("host", "eqchat.eqemulator.net").asString(); + m_ucs_port = Strings::ToUnsignedInt(_root["server"]["ucs"].get("port", "7778").asString()); /** * Database @@ -246,16 +248,16 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const return (WorldHTTPEnabled ? "true" : "false"); } if (var_name == "ChatHost") { - return (ChatHost); + return (m_ucs_host); } if (var_name == "ChatPort") { - return (itoa(ChatPort)); + return (itoa(m_ucs_port)); } if (var_name == "MailHost") { - return (MailHost); + return (m_ucs_host); } if (var_name == "MailPort") { - return (itoa(MailPort)); + return (itoa(m_ucs_port)); } if (var_name == "DatabaseHost") { return (DatabaseHost); @@ -362,10 +364,8 @@ void EQEmuConfig::Dump() const std::cout << "WorldHTTPPort = " << WorldHTTPPort << std::endl; std::cout << "WorldHTTPMimeFile = " << WorldHTTPMimeFile << std::endl; std::cout << "WorldHTTPEnabled = " << WorldHTTPEnabled << std::endl; - std::cout << "ChatHost = " << ChatHost << std::endl; - std::cout << "ChatPort = " << ChatPort << std::endl; - std::cout << "MailHost = " << MailHost << std::endl; - std::cout << "MailPort = " << MailPort << std::endl; + std::cout << "UCSHost = " << m_ucs_host << std::endl; + std::cout << "UCSPort = " << m_ucs_port << std::endl; std::cout << "DatabaseHost = " << DatabaseHost << std::endl; std::cout << "DatabaseUsername = " << DatabaseUsername << std::endl; std::cout << "DatabasePassword = " << DatabasePassword << std::endl; @@ -392,3 +392,98 @@ void EQEmuConfig::Dump() const std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl; // std::cout << "DynamicCount = " << DynamicCount << std::endl; } + +const std::string &EQEmuConfig::GetUCSHost() const +{ + return m_ucs_host; +} + +uint16 EQEmuConfig::GetUCSPort() const +{ + return m_ucs_port; +} + +void EQEmuConfig::CheckUcsConfigConversion() +{ + std::string chat_host = _root["server"]["chatserver"].get("host", "").asString(); + uint32 chat_port = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "0").asString()); + std::string mail_host = _root["server"]["mailserver"].get("host", "").asString(); + uint32 mail_port = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "0").asString()); + std::string ucs_host = _root["server"]["ucs"].get("host", "").asString(); + + // automatic ucs legacy configuration migration + // if old configuration values are set, let's backup the existing configuration + // and migrate to to use the new fields and write the new config + if ((!chat_host.empty() || !mail_host.empty()) && ucs_host.empty()) { + LogInfo("Migrating old [eqemu_config] UCS configuration to new configuration"); + + std::string config_file_path = std::filesystem::path{ + path.GetServerPath() + "/eqemu_config.json" + }.string(); + + std::string config_file_bak_path = std::filesystem::path{ + path.GetServerPath() + "/eqemu_config.ucs-migrate-json.bak" + }.string(); + + // copy eqemu_config.json to eqemu_config.json.bak + std::ifstream src(config_file_path, std::ios::binary); + std::ofstream dst(config_file_bak_path, std::ios::binary); + dst << src.rdbuf(); + src.close(); + + LogInfo("Old configuration backed up to [{}]", config_file_bak_path); + + // read eqemu_config.json, transplant new fields and write to eqemu_config.json + Json::Value root; + Json::Reader reader; + std::ifstream file(config_file_path); + if (!reader.parse(file, root)) { + LogError("Failed to parse configuration file"); + return; + } + file.close(); + + // get old fields + std::string host = !chat_host.empty() ? chat_host : mail_host; + if (host.empty()) { + host = "eqchat.eqemulator.net"; + } + std::string port = chat_port > 0 ? std::to_string(chat_port) : std::to_string(mail_port); + if (port.empty()) { + port = "7778"; + } + + // set new fields + root["server"]["ucs"]["host"] = host; + root["server"]["ucs"]["port"] = port; + + // unset old fields + root["server"].removeMember("chatserver"); + root["server"].removeMember("mailserver"); + + // get Json::Value raw string + std::string config = root.toStyledString(); + + // format using more modern json library + nlohmann::json data = nlohmann::json::parse(config); + + // write to file + std::ofstream o(config_file_path); + o << std::setw(1) << data << std::endl; + o.close(); + + // write new config + LogInfo("New configuration written to [{}]", config_file_path); + LogInfo("Migration complete, please review the new configuration file"); + + // reload config internally + try { + std::ifstream fconfig(config_file_path, std::ifstream::binary); + fconfig >> _config->_root; + _config->parse_config(); + } + catch (std::exception &) { + return; + } + } +} diff --git a/common/eqemu_config.h b/common/eqemu_config.h index ff8788f3e..6aad3d41c 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -62,14 +62,6 @@ class EQEmuConfig std::string SharedKey; bool DisableConfigChecks; - // From - std::string ChatHost; - uint16 ChatPort; - - // From - std::string MailHost; - uint16 MailPort; - // From std::string DatabaseHost; std::string DatabaseUsername; @@ -122,12 +114,18 @@ class EQEmuConfig bool auto_database_updates; + const std::string &GetUCSHost() const; + uint16 GetUCSPort() const; + // uint16 DynamicCount; // map StaticZones; protected: + std::string m_ucs_host; + uint16 m_ucs_port; + static EQEmuConfig *_config; Json::Value _root; static std::string ConfigFile; @@ -186,6 +184,7 @@ class EQEmuConfig } void Dump() const; + void CheckUcsConfigConversion(); }; #endif diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 992d5b3d0..c89c3f4fd 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -164,13 +164,7 @@ int main() { database.ExpireMail(); - if(Config->ChatPort != Config->MailPort) - { - LogInfo("MailPort and CharPort must be the same in eqemu_config.json for UCS"); - exit(1); - } - - g_Clientlist = new Clientlist(Config->ChatPort); + g_Clientlist = new Clientlist(Config->GetUCSPort()); ChannelList = new ChatChannelList(); diff --git a/world/client.cpp b/world/client.cpp index a6232bcb7..d17cab2b4 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -945,8 +945,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } buffer = fmt::format("{},{},{}.{},{}{:08X}", - config->ChatHost, - config->ChatPort, + config->GetUCSHost(), + config->GetUCSPort(), config->ShortName, GetCharName(), static_cast(connection_type), @@ -971,8 +971,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } buffer = fmt::format("{},{},{}.{},{}{:08X}", - config->MailHost, - config->MailPort, + config->GetUCSHost(), + config->GetUCSPort(), config->ShortName, GetCharName(), static_cast(connection_type), diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 5c2601dcd..99c3b9033 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -634,8 +634,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues() // ucs (public) if ( - (!config_address.empty() && c->MailHost != config_address) || - (!config_address.empty() && c->ChatHost != config_address) + (!config_address.empty() && c->GetUCSHost() != config_address) ) { LogWarning("# UCS Address Mailhost (Configuration)"); LogWarning(""); @@ -647,14 +646,9 @@ void WorldBoot::CheckForPossibleConfigurationIssues() LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]"); LogWarning(""); LogWarning( - "[server.world.address] value [{}] [server.chatserver.host] [{}]", + "[server.world.address] value [{}] [server.ucs.host] [{}]", config_address, - c->ChatHost - ); - LogWarning( - "[server.world.address] value [{}] [server.mailserver.host] [{}]", - config_address, - c->MailHost + c->GetUCSHost() ); std::cout << std::endl; } diff --git a/zone/client.cpp b/zone/client.cpp index 2d15ed877..690ce61fe 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -10883,8 +10883,8 @@ void Client::ReconnectUCS() buffer = StringFormat( "%s,%i,%s.%s,%c%s", - Config->ChatHost.c_str(), - Config->ChatPort, + Config->GetUCSHost().c_str(), + Config->GetUCSPort(), Config->ShortName.c_str(), GetName(), connection_type, @@ -10910,8 +10910,8 @@ void Client::ReconnectUCS() buffer = StringFormat( "%s,%i,%s.%s,%c%s", - Config->MailHost.c_str(), - Config->MailPort, + Config->GetUCSHost().c_str(), + Config->GetUCSPort(), Config->ShortName.c_str(), GetName(), connection_type, diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 78b8078ee..fd13b82c8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11817,8 +11817,8 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app) } buffer = StringFormat("%s,%i,%s.%s,%c%s", - Config->ChatHost.c_str(), - Config->ChatPort, + Config->GetUCSHost().c_str(), + Config->GetUCSPort(), Config->ShortName.c_str(), GetName(), ConnectionType, @@ -11843,8 +11843,8 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app) } buffer = StringFormat("%s,%i,%s.%s,%c%s", - Config->MailHost.c_str(), - Config->MailPort, + Config->GetUCSHost().c_str(), + Config->GetUCSPort(), Config->ShortName.c_str(), GetName(), ConnectionType,