From 435761f64bdf75edf717ed6a12b966624c16447c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 15 Dec 2022 04:02:38 -0800 Subject: [PATCH] Improve shutdown --- dAuthServer/AuthServer.cpp | 41 ++++++------ dChatServer/ChatServer.cpp | 49 ++++++++------- dCommon/Game.h | 3 + dMasterServer/InstanceManager.cpp | 6 +- dMasterServer/MasterServer.cpp | 88 ++++++++++---------------- dNet/dServer.cpp | 8 ++- dNet/dServer.h | 20 +++++- dWorldServer/WorldServer.cpp | 91 +++++++++++++++------------ tests/dGameTests/GameDependencies.cpp | 1 + 9 files changed, 160 insertions(+), 147 deletions(-) diff --git a/dAuthServer/AuthServer.cpp b/dAuthServer/AuthServer.cpp index aefc822b..4fffc5d0 100644 --- a/dAuthServer/AuthServer.cpp +++ b/dAuthServer/AuthServer.cpp @@ -22,9 +22,10 @@ #include "Game.h" namespace Game { - dLogger* logger = nullptr; - dServer* server = nullptr; - dConfig* config = nullptr; + dLogger* logger; + dServer* server; + dConfig* config; + bool shouldShutdown = false; } dLogger* SetupLogger(); @@ -37,22 +38,22 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(); - if (!Game::logger) return EXIT_FAILURE; - - //Read our config: - Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "authconfig.ini").string()); - Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); - Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); - + if (!Game::logger) return 0; Game::logger->Log("AuthServer", "Starting Auth server..."); Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__); + //Read our config: + dConfig config("authconfig.ini"); + Game::config = &config; + Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console")))); + Game::logger->SetLogDebugStatements(config.GetValue("log_debug_statements") == "1"); + //Connect to the MySQL Database - std::string mysql_host = Game::config->GetValue("mysql_host"); - std::string mysql_database = Game::config->GetValue("mysql_database"); - std::string mysql_username = Game::config->GetValue("mysql_username"); - std::string mysql_password = Game::config->GetValue("mysql_password"); + std::string mysql_host = config.GetValue("mysql_host"); + std::string mysql_database = config.GetValue("mysql_database"); + std::string mysql_username = config.GetValue("mysql_username"); + std::string mysql_password = config.GetValue("mysql_password"); try { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); @@ -61,7 +62,7 @@ int main(int argc, char** argv) { Database::Destroy("AuthServer"); delete Game::server; delete Game::logger; - return EXIT_FAILURE; + return 0; } //Find out the master's IP: @@ -80,10 +81,10 @@ int main(int argc, char** argv) { //It's safe to pass 'localhost' here, as the IP is only used as the external IP. int maxClients = 50; int ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default. - if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients")); - if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str()); + if (config.GetValue("max_clients") != "") maxClients = std::stoi(config.GetValue("max_clients")); + if (config.GetValue("port") != "") ourPort = std::atoi(config.GetValue("port").c_str()); - Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config); + Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, Game::shouldShutdown); //Run it until server gets a kill message from Master: auto t = std::chrono::high_resolution_clock::now(); @@ -92,7 +93,7 @@ int main(int argc, char** argv) { int framesSinceMasterDisconnect = 0; int framesSinceLastSQLPing = 0; - while (true) { + while (!Game::shouldShutdown) { //Check if we're still connected to master: if (!Game::server->GetIsConnectedToMaster()) { framesSinceMasterDisconnect++; @@ -145,8 +146,8 @@ int main(int argc, char** argv) { Database::Destroy("AuthServer"); delete Game::server; delete Game::logger; - delete Game::config; + exit(EXIT_SUCCESS); return EXIT_SUCCESS; } diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index 043e7869..d2eb7fc7 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -20,11 +20,12 @@ #include "Game.h" namespace Game { - dLogger* logger = nullptr; - dServer* server = nullptr; - dConfig* config = nullptr; - dChatFilter* chatFilter = nullptr; - AssetManager* assetManager = nullptr; + dLogger* logger; + dServer* server; + dConfig* config; + dChatFilter* chatFilter; + AssetManager* assetManager; + bool shouldShutdown = false; } //RakNet includes: @@ -42,19 +43,19 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(); - if (!Game::logger) return EXIT_FAILURE; - - //Read our config: - Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "chatconfig.ini").string()); - Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); - Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); - + if (!Game::logger) return 0; Game::logger->Log("ChatServer", "Starting Chat server..."); Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__); + //Read our config: + dConfig config("chatconfig.ini"); + Game::config = &config; + Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console")))); + Game::logger->SetLogDebugStatements(config.GetValue("log_debug_statements") == "1"); + try { - std::string clientPathStr = Game::config->GetValue("client_location"); + std::string clientPathStr = config.GetValue("client_location"); if (clientPathStr.empty()) clientPathStr = "./res"; std::filesystem::path clientPath = std::filesystem::path(clientPathStr); if (clientPath.is_relative()) { @@ -69,10 +70,10 @@ int main(int argc, char** argv) { } //Connect to the MySQL Database - std::string mysql_host = Game::config->GetValue("mysql_host"); - std::string mysql_database = Game::config->GetValue("mysql_database"); - std::string mysql_username = Game::config->GetValue("mysql_username"); - std::string mysql_password = Game::config->GetValue("mysql_password"); + std::string mysql_host = config.GetValue("mysql_host"); + std::string mysql_database = config.GetValue("mysql_database"); + std::string mysql_username = config.GetValue("mysql_username"); + std::string mysql_password = config.GetValue("mysql_password"); try { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); @@ -81,7 +82,7 @@ int main(int argc, char** argv) { Database::Destroy("ChatServer"); delete Game::server; delete Game::logger; - return EXIT_FAILURE; + return 0; } //Find out the master's IP: @@ -100,12 +101,12 @@ int main(int argc, char** argv) { //It's safe to pass 'localhost' here, as the IP is only used as the external IP. int maxClients = 50; int ourPort = 1501; - if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients")); - if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str()); + if (config.GetValue("max_clients") != "") maxClients = std::stoi(config.GetValue("max_clients")); + if (config.GetValue("port") != "") ourPort = std::atoi(config.GetValue("port").c_str()); - Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config); + Game::server = new dServer(config.GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, Game::shouldShutdown); - Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); + Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(config.GetValue("dont_generate_dcf")))); //Run it until server gets a kill message from Master: auto t = std::chrono::high_resolution_clock::now(); @@ -114,7 +115,7 @@ int main(int argc, char** argv) { int framesSinceMasterDisconnect = 0; int framesSinceLastSQLPing = 0; - while (true) { + while (!Game::shouldShutdown) { //Check if we're still connected to master: if (!Game::server->GetIsConnectedToMaster()) { framesSinceMasterDisconnect++; @@ -167,8 +168,8 @@ int main(int argc, char** argv) { Database::Destroy("ChatServer"); delete Game::server; delete Game::logger; - delete Game::config; + exit(EXIT_SUCCESS); return EXIT_SUCCESS; } diff --git a/dCommon/Game.h b/dCommon/Game.h index 38cadb70..cbddafec 100644 --- a/dCommon/Game.h +++ b/dCommon/Game.h @@ -5,6 +5,7 @@ class dServer; class dLogger; class InstanceManager; +class dpWorld; class dChatFilter; class dConfig; class RakPeerInterface; @@ -15,10 +16,12 @@ namespace Game { extern dLogger* logger; extern dServer* server; extern InstanceManager* im; + extern dpWorld* physicsWorld; extern dChatFilter* chatFilter; extern dConfig* config; extern std::mt19937 randomEngine; extern RakPeerInterface* chatServer; extern AssetManager* assetManager; extern SystemAddress chatSysAddr; + extern bool shouldShutdown; } diff --git a/dMasterServer/InstanceManager.cpp b/dMasterServer/InstanceManager.cpp index a1983dd4..327a18b9 100644 --- a/dMasterServer/InstanceManager.cpp +++ b/dMasterServer/InstanceManager.cpp @@ -74,7 +74,7 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW cmd.append("&"); //Sends our next process to the background on Linux #endif - auto ret = system(cmd.c_str()); + system(cmd.c_str()); m_Instances.push_back(instance); @@ -322,7 +322,7 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon cmd.append("&"); //Sends our next process to the background on Linux #endif - auto ret = system(cmd.c_str()); + system(cmd.c_str()); m_Instances.push_back(instance); @@ -391,5 +391,5 @@ void Instance::Shutdown() { Game::server->Send(&bitStream, this->m_SysAddr, false); - Game::logger->Log("Instance", "Triggered world shutdown"); + Game::logger->Log("Instance", "Triggered world shutdown for zone/clone/instance %i/%i/%i", GetMapID(), GetCloneID(), GetInstanceID()); } diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 4c18566e..2f54243a 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -43,11 +43,12 @@ #include "FdbToSqlite.h" namespace Game { - dLogger* logger = nullptr; - dServer* server = nullptr; - InstanceManager* im = nullptr; - dConfig* config = nullptr; - AssetManager* assetManager = nullptr; + dLogger* logger; + dServer* server; + InstanceManager* im; + dConfig* config; + AssetManager* assetManager; + bool shouldShutdown = false; } //namespace Game bool shutdownSequenceStarted = false; @@ -58,7 +59,6 @@ void StartAuthServer(); void StartChatServer(); void HandlePacket(Packet* packet); std::map activeSessions; -bool shouldShutdown = false; SystemAddress chatServerMasterPeerSysAddr; int main(int argc, char** argv) { @@ -79,39 +79,14 @@ int main(int argc, char** argv) { Game::logger = SetupLogger(); if (!Game::logger) return EXIT_FAILURE; - if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "authconfig.ini")) { - Game::logger->Log("MasterServer", "Couldnt find authconfig.ini"); - return EXIT_FAILURE; - } - - if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "chatconfig.ini")) { - Game::logger->Log("MasterServer", "Couldnt find chatconfig.ini"); - return EXIT_FAILURE; - } - - if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "masterconfig.ini")) { - Game::logger->Log("MasterServer", "Couldnt find masterconfig.ini"); - return EXIT_FAILURE; - } - - if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini")) { - Game::logger->Log("MasterServer", "Couldnt find sharedconfig.ini"); - return EXIT_FAILURE; - } - - if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "worldconfig.ini")) { - Game::logger->Log("MasterServer", "Couldnt find worldconfig.ini"); - return EXIT_FAILURE; - } - - Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "masterconfig.ini").string()); - Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); - Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); - Game::logger->Log("MasterServer", "Starting Master server..."); Game::logger->Log("MasterServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("MasterServer", "Compiled on: %s", __TIMESTAMP__); + Game::config = new dConfig("masterconfig.ini"); + Game::logger->SetLogToConsole(bool(std::stoi(Game::config->GetValue("log_to_console")))); + Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); + //Connect to the MySQL Database std::string mysql_host = Game::config->GetValue("mysql_host"); std::string mysql_database = Game::config->GetValue("mysql_database"); @@ -241,7 +216,7 @@ int main(int argc, char** argv) { if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients")); if (Game::config->GetValue("port") != "") ourPort = std::stoi(Game::config->GetValue("port")); - Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config); + Game::server = new dServer(config.GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, Game::shouldShutdown); //Query for the database for a server labeled "master" auto* masterLookupStatement = Database::CreatePreppedStmt("SELECT id FROM `servers` WHERE `name` = 'master'"); @@ -328,7 +303,7 @@ int main(int argc, char** argv) { framesSinceLastSQLPing++; //10m shutdown for universe kill command - if (shouldShutdown) { + if (Game::shouldShutdown) { if (framesSinceKillUniverseCommand >= 40000) { //Break main loop and exit break; @@ -406,7 +381,7 @@ void HandlePacket(Packet* packet) { Game::im->RemoveInstance(instance); //Delete the old } - if (packet->systemAddress == chatServerMasterPeerSysAddr && !shouldShutdown) { + if (packet->systemAddress == chatServerMasterPeerSysAddr && !Game::shouldShutdown) { StartChatServer(); } } @@ -422,7 +397,7 @@ void HandlePacket(Packet* packet) { //Game::im->GetInstance(zoneID.GetMapID(), false, 0); //Create the new } - if (packet->systemAddress == chatServerMasterPeerSysAddr && !shouldShutdown) { + if (packet->systemAddress == chatServerMasterPeerSysAddr && !Game::shouldShutdown) { StartChatServer(); } } @@ -744,7 +719,7 @@ void HandlePacket(Packet* packet) { case MSG_MASTER_SHUTDOWN_UNIVERSE: { Game::logger->Log("MasterServer", "Received shutdown universe command, shutting down in 10 minutes."); - shouldShutdown = true; + Game::shouldShutdown = true; break; } @@ -757,28 +732,28 @@ void HandlePacket(Packet* packet) { void StartChatServer() { #ifdef __APPLE__ //macOS doesn't need sudo to run on ports < 1024 - auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); + system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); #elif _WIN32 - auto result = system(("start " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str()); + system(("start " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str()); #else if (std::atoi(Game::config->GetValue("use_sudo_chat").c_str())) { - auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); + system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); } else { - auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); + system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str()); } #endif } void StartAuthServer() { #ifdef __APPLE__ - auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); + system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); #elif _WIN32 - auto result = system(("start " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str()); + system(("start " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str()); #else if (std::atoi(Game::config->GetValue("use_sudo_auth").c_str())) { - auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); + system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); } else { - auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); + system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str()); } #endif } @@ -790,14 +765,11 @@ void ShutdownSequence() { shutdownSequenceStarted = true; - if (Game::im) { - for (auto* instance : Game::im->GetInstances()) { - if (instance == nullptr) { - continue; - } - - instance->Shutdown(); - } + { + CBITSTREAM; + PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN); + Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); + Game::logger->Log("MasterServer", "Triggered master shutdown"); } auto* objIdManager = ObjectIDManager::TryInstance(); @@ -813,6 +785,10 @@ void ShutdownSequence() { exit(EXIT_SUCCESS); } + for (auto instance : Game::im->GetInstances()) { + instance->SetIsShuttingDown(true); + } + Game::logger->Log("MasterServer", "Attempting to shutdown instances, max 60 seconds..."); while (true) { diff --git a/dNet/dServer.cpp b/dNet/dServer.cpp index 481667b8..3a5ef822 100644 --- a/dNet/dServer.cpp +++ b/dNet/dServer.cpp @@ -36,7 +36,7 @@ public: } } ReceiveDownloadCompleteCB; -dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, dLogger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, unsigned int zoneID) { +dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, dLogger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, bool& shouldShutdown, unsigned int zoneID) { mIP = ip; mPort = port; mZoneID = zoneID; @@ -52,6 +52,7 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect mReplicaManager = nullptr; mServerType = serverType; mConfig = config; + mShouldShutdown = &shouldShutdown; //Attempt to start our server here: mIsOkay = Startup(); @@ -124,8 +125,11 @@ Packet* dServer::ReceiveFromMaster() { ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet); break; } + case MSG_MASTER_SHUTDOWN: + *mShouldShutdown = true; + break; - //When we handle these packets in World instead dServer, we just return the packet's pointer. + //When we handle these packets in World instead dServer, we just return the packet's pointer. default: return packet; diff --git a/dNet/dServer.h b/dNet/dServer.h index 0fbdecce..608b3b83 100644 --- a/dNet/dServer.h +++ b/dNet/dServer.h @@ -18,7 +18,20 @@ class dServer { public: // Default constructor should only used for testing! dServer() {}; - dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, dLogger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, unsigned int zoneID = 0); + dServer( + const std::string& ip, + int port, + int instanceID, + int maxConnections, + bool isInternal, + bool useEncryption, + dLogger* logger, + const std::string masterIP, + int masterPort, + ServerType serverType, + dConfig* config, + bool& shouldShutdown, + unsigned int zoneID = 0); ~dServer(); Packet* ReceiveFromMaster(); @@ -64,6 +77,11 @@ private: RakPeerInterface* mPeer = nullptr; ReplicaManager* mReplicaManager = nullptr; NetworkIDManager* mNetIDManager = nullptr; + + /** + * Whether or not to shut down the server. Pointer to Game::shouldShutdown. + */ + bool* mShouldShutdown = nullptr; SocketDescriptor mSocketDescriptor; std::string mIP; int mPort; diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 68ec0e57..2fdb373b 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -61,20 +61,23 @@ #include "ZCompression.h" namespace Game { - dLogger* logger = nullptr; - dServer* server = nullptr; - dpWorld* physicsWorld = nullptr; - dChatFilter* chatFilter = nullptr; - dConfig* config = nullptr; - AssetManager* assetManager = nullptr; - RakPeerInterface* chatServer = nullptr; + dLogger* logger; + dServer* server; + dZoneManager* zoneManager; + dpWorld* physicsWorld; + dChatFilter* chatFilter; + dConfig* config; std::mt19937 randomEngine; + + AssetManager* assetManager; + + RakPeerInterface* chatServer; SystemAddress chatSysAddr; -} + bool shouldShutdown = false; +} // namespace Game bool chatDisabled = false; bool chatConnected = false; -bool worldShutdownSequenceStarted = false; bool worldShutdownSequenceComplete = false; void WorldShutdownSequence(); void WorldShutdownProcess(uint32_t zoneId); @@ -124,21 +127,26 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(zoneID, instanceID); - if (!Game::logger) return EXIT_FAILURE; - - //Read our config: - Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "worldconfig.ini").string()); - Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0"); - Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1"); + if (!Game::logger) return 0; + Game::logger->SetLogToConsole(true); //We want this info to always be logged. Game::logger->Log("WorldServer", "Starting World server..."); Game::logger->Log("WorldServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); Game::logger->Log("WorldServer", "Compiled on: %s", __TIMESTAMP__); - if (Game::config->GetValue("disable_chat") == "1") chatDisabled = true; +#ifndef _DEBUG + Game::logger->SetLogToConsole(false); //By default, turn it back off if not in debug. +#endif + + //Read our config: + dConfig config("worldconfig.ini"); + Game::config = &config; + Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console")))); + Game::logger->SetLogDebugStatements(config.GetValue("log_debug_statements") == "1"); + if (config.GetValue("disable_chat") == "1") chatDisabled = true; try { - std::string clientPathStr = Game::config->GetValue("client_location"); + std::string clientPathStr = config.GetValue("client_location"); if (clientPathStr.empty()) clientPathStr = "./res"; std::filesystem::path clientPath = std::filesystem::path(clientPathStr); if (clientPath.is_relative()) { @@ -158,28 +166,28 @@ int main(int argc, char** argv) { Game::logger->Log("WorldServer", "Unable to connect to CDServer SQLite Database"); Game::logger->Log("WorldServer", "Error: %s", e.errorMessage()); Game::logger->Log("WorldServer", "Error Code: %i", e.errorCode()); - return EXIT_FAILURE; + return -1; } CDClientManager::Instance()->Initialize(); //Connect to the MySQL Database - std::string mysql_host = Game::config->GetValue("mysql_host"); - std::string mysql_database = Game::config->GetValue("mysql_database"); - std::string mysql_username = Game::config->GetValue("mysql_username"); - std::string mysql_password = Game::config->GetValue("mysql_password"); + std::string mysql_host = config.GetValue("mysql_host"); + std::string mysql_database = config.GetValue("mysql_database"); + std::string mysql_username = config.GetValue("mysql_username"); + std::string mysql_password = config.GetValue("mysql_password"); - Diagnostics::SetProduceMemoryDump(Game::config->GetValue("generate_dump") == "1"); + Diagnostics::SetProduceMemoryDump(config.GetValue("generate_dump") == "1"); - if (!Game::config->GetValue("dump_folder").empty()) { - Diagnostics::SetOutDirectory(Game::config->GetValue("dump_folder")); + if (!config.GetValue("dump_folder").empty()) { + Diagnostics::SetOutDirectory(config.GetValue("dump_folder")); } try { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); } catch (sql::SQLException& ex) { Game::logger->Log("WorldServer", "Got an error while connecting to the database: %s", ex.what()); - return EXIT_FAILURE; + return 0; } //Find out the master's IP: @@ -198,13 +206,13 @@ int main(int argc, char** argv) { ObjectIDManager::Instance()->Initialize(); UserManager::Instance()->Initialize(); LootGenerator::Instance(); - Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); + Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(config.GetValue("dont_generate_dcf")))); - Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, zoneID); + Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, Game::shouldShutdown, zoneID); //Connect to the chat server: int chatPort = 1501; - if (Game::config->GetValue("chat_server_port") != "") chatPort = std::atoi(Game::config->GetValue("chat_server_port").c_str()); + if (config.GetValue("chat_server_port") != "") chatPort = std::atoi(config.GetValue("chat_server_port").c_str()); auto chatSock = SocketDescriptor(uint16_t(ourPort + 2), 0); Game::chatServer = RakNetworkFactory::GetRakPeerInterface(); @@ -315,9 +323,9 @@ int main(int argc, char** argv) { framesSinceMasterDisconnect++; int framesToWaitForMaster = ready ? 10 : 200; - if (framesSinceMasterDisconnect >= framesToWaitForMaster && !worldShutdownSequenceStarted) { + if (framesSinceMasterDisconnect >= framesToWaitForMaster && !Game::shouldShutdown) { Game::logger->Log("WorldServer", "Game loop running but no connection to master for %d frames, shutting down", framesToWaitForMaster); - worldShutdownSequenceStarted = true; + Game::shouldShutdown = true; } } else framesSinceMasterDisconnect = 0; @@ -413,7 +421,7 @@ int main(int argc, char** argv) { //If we haven't had any players for a while, time out and shut down: if (framesSinceLastUser == (cloneID != 0 ? 4000 : 40000)) { - worldShutdownSequenceStarted = true; + Game::shouldShutdown = true; } } else { framesSinceLastUser = 0; @@ -470,7 +478,7 @@ int main(int argc, char** argv) { } } - if (worldShutdownSequenceStarted && !worldShutdownSequenceComplete) { + if (Game::shouldShutdown && !worldShutdownSequenceComplete) { WorldShutdownProcess(zoneID); break; } @@ -789,7 +797,7 @@ void HandlePacket(Packet* packet) { } case MSG_MASTER_SHUTDOWN: { - worldShutdownSequenceStarted = true; + Game::shouldShutdown = true; Game::logger->Log("WorldServer", "Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID()); break; } @@ -1259,11 +1267,11 @@ void WorldShutdownProcess(uint32_t zoneId) { } void WorldShutdownSequence() { - if (worldShutdownSequenceStarted || worldShutdownSequenceComplete) { + if (Game::shouldShutdown || worldShutdownSequenceComplete) { return; } - worldShutdownSequenceStarted = true; + Game::shouldShutdown = true; Game::logger->Log("WorldServer", "Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID); WorldShutdownProcess(Game::server->GetZoneID()); @@ -1271,15 +1279,16 @@ void WorldShutdownSequence() { } void FinalizeShutdown() { + //Delete our objects here: + if (Game::zoneManager) delete Game::zoneManager; + Game::logger->Log("WorldServer", "Shutdown complete, zone (%i), instance (%i)", Game::server->GetZoneID(), instanceID); - //Delete our objects here: Metrics::Clear(); Database::Destroy("WorldServer"); - if (Game::chatFilter) delete Game::chatFilter; - if (Game::server) delete Game::server; - if (Game::logger) delete Game::logger; - if (Game::config) delete Game::config; + delete Game::chatFilter; + delete Game::server; + delete Game::logger; worldShutdownSequenceComplete = true; diff --git a/tests/dGameTests/GameDependencies.cpp b/tests/dGameTests/GameDependencies.cpp index 7b0a8412..5ac3339a 100644 --- a/tests/dGameTests/GameDependencies.cpp +++ b/tests/dGameTests/GameDependencies.cpp @@ -4,6 +4,7 @@ namespace Game { dLogger* logger; dServer* server; dZoneManager* zoneManager; + dpWorld* physicsWorld; dChatFilter* chatFilter; dConfig* config; std::mt19937 randomEngine;