Merge branch 'main' into fix--remove-the-wacrimes-from-our-docker-config

This commit is contained in:
Aaron Kimbre 2024-01-02 08:50:57 -06:00
commit f7664ad838
22 changed files with 118 additions and 70 deletions

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.18)
project(Darkflame) project(Darkflame)
include(CTest) include(CTest)
set (CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
# Read variables from file # Read variables from file
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables) FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)

View File

@ -1,6 +1,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <ctime> #include <ctime>
#include <csignal>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
@ -28,7 +29,7 @@ namespace Game {
Logger* logger = nullptr; Logger* logger = nullptr;
dServer* server = nullptr; dServer* server = nullptr;
dConfig* config = nullptr; dConfig* config = nullptr;
bool shouldShutdown = false; Game::signal_t lastSignal = 0;
std::mt19937 randomEngine; std::mt19937 randomEngine;
} }
@ -42,6 +43,9 @@ int main(int argc, char** argv) {
Diagnostics::SetProcessFileName(argv[0]); Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize(); Diagnostics::Initialize();
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
//Create all the objects we need to run our service: //Create all the objects we need to run our service:
Game::logger = SetupLogger(); Game::logger = SetupLogger();
if (!Game::logger) return EXIT_FAILURE; if (!Game::logger) return EXIT_FAILURE;
@ -74,6 +78,7 @@ int main(int argc, char** argv) {
masterIP = masterInfo->ip; masterIP = masterInfo->ip;
masterPort = masterInfo->port; masterPort = masterInfo->port;
} }
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
@ -83,7 +88,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("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 (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::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::shouldShutdown); Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal);
//Run it until server gets a kill message from Master: //Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now(); auto t = std::chrono::high_resolution_clock::now();
@ -96,13 +101,16 @@ int main(int argc, char** argv) {
AuthPackets::LoadClaimCodes(); AuthPackets::LoadClaimCodes();
while (!Game::shouldShutdown) { Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
//Check if we're still connected to master: //Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) { if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++; framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= authFramerate) if (framesSinceMasterDisconnect >= authFramerate) {
LOG("No connection to master!");
break; //Exit our loop, shut down. break; //Exit our loop, shut down.
}
} else framesSinceMasterDisconnect = 0; } else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here. //In world we'd update our other systems here.
@ -141,6 +149,7 @@ int main(int argc, char** argv) {
std::this_thread::sleep_until(t); std::this_thread::sleep_until(t);
} }
LOG("Exited Main Loop! (signal %d)", Game::lastSignal);
//Delete our objects here: //Delete our objects here:
Database::Destroy("AuthServer"); Database::Destroy("AuthServer");
delete Game::server; delete Game::server;

View File

@ -33,7 +33,7 @@ namespace Game {
dConfig* config = nullptr; dConfig* config = nullptr;
dChatFilter* chatFilter = nullptr; dChatFilter* chatFilter = nullptr;
AssetManager* assetManager = nullptr; AssetManager* assetManager = nullptr;
bool shouldShutdown = false; Game::signal_t lastSignal = 0;
std::mt19937 randomEngine; std::mt19937 randomEngine;
PlayerContainer playerContainer; PlayerContainer playerContainer;
} }
@ -48,6 +48,9 @@ int main(int argc, char** argv) {
Diagnostics::SetProcessFileName(argv[0]); Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize(); Diagnostics::Initialize();
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
//Create all the objects we need to run our service: //Create all the objects we need to run our service:
Game::logger = SetupLogger(); Game::logger = SetupLogger();
if (!Game::logger) return EXIT_FAILURE; if (!Game::logger) return EXIT_FAILURE;
@ -101,7 +104,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("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 (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::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::shouldShutdown); Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
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(Game::config->GetValue("dont_generate_dcf"))));
@ -118,7 +121,8 @@ int main(int argc, char** argv) {
uint32_t framesSinceMasterDisconnect = 0; uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0; uint32_t framesSinceLastSQLPing = 0;
while (!Game::shouldShutdown) { Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
//Check if we're still connected to master: //Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) { if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++; framesSinceMasterDisconnect++;

View File

@ -5,6 +5,7 @@ set(DCOMMON_SOURCES
"dConfig.cpp" "dConfig.cpp"
"Diagnostics.cpp" "Diagnostics.cpp"
"Logger.cpp" "Logger.cpp"
"Game.cpp"
"GeneralUtils.cpp" "GeneralUtils.cpp"
"LDFFormat.cpp" "LDFFormat.cpp"
"MD5.cpp" "MD5.cpp"

7
dCommon/Game.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "Game.h"
namespace Game {
void OnSignal(int signal) {
lastSignal = signal;
}
}

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <random> #include <random>
#include <csignal>
class dServer; class dServer;
class Logger; class Logger;
@ -16,6 +17,7 @@ class dZoneManager;
class PlayerContainer; class PlayerContainer;
namespace Game { namespace Game {
using signal_t = volatile std::sig_atomic_t;
extern Logger* logger; extern Logger* logger;
extern dServer* server; extern dServer* server;
extern InstanceManager* im; extern InstanceManager* im;
@ -25,9 +27,14 @@ namespace Game {
extern RakPeerInterface* chatServer; extern RakPeerInterface* chatServer;
extern AssetManager* assetManager; extern AssetManager* assetManager;
extern SystemAddress chatSysAddr; extern SystemAddress chatSysAddr;
extern bool shouldShutdown; extern signal_t lastSignal;
extern EntityManager* entityManager; extern EntityManager* entityManager;
extern dZoneManager* zoneManager; extern dZoneManager* zoneManager;
extern PlayerContainer playerContainer; extern PlayerContainer playerContainer;
extern std::string projectVersion; extern std::string projectVersion;
inline bool ShouldShutdown() {
return lastSignal != 0;
}
void OnSignal(int signal);
} }

View File

@ -6,6 +6,8 @@
#include <stdarg.h> #include <stdarg.h>
Writer::~Writer() { Writer::~Writer() {
// Flush before we close
Flush();
// Dont try to close stdcout... // Dont try to close stdcout...
if (!m_Outfile || m_IsConsoleWriter) return; if (!m_Outfile || m_IsConsoleWriter) return;

View File

@ -263,7 +263,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
} }
//Now that the name is ok, we can get an objectID from Master: //Now that the name is ok, we can get an objectID from Master:
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t objectID) { ObjectIDManager::Instance()->RequestPersistentID([=, this](uint32_t objectID) {
if (Database::Get()->GetCharacterInfo(objectID)) { if (Database::Get()->GetCharacterInfo(objectID)) {
LOG("Character object id unavailable, check object_id_tracker!"); LOG("Character object id unavailable, check object_id_tracker!");
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE); WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);

View File

@ -33,7 +33,7 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo
if (activityID > 0) m_ActivityID = activityID; if (activityID > 0) m_ActivityID = activityID;
else m_ActivityID = parent->GetVar<int32_t>(u"activityID"); else m_ActivityID = parent->GetVar<int32_t>(u"activityID");
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>(); CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); }); std::vector<CDActivities> activities = activitiesTable->Query([this](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
for (CDActivities activity : activities) { for (CDActivities activity : activities) {
m_ActivityInfo = activity; m_ActivityInfo = activity;
@ -93,7 +93,7 @@ void ActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIniti
void ActivityComponent::ReloadConfig() { void ActivityComponent::ReloadConfig() {
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>(); CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); }); std::vector<CDActivities> activities = activitiesTable->Query([this](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
for (auto activity : activities) { for (auto activity : activities) {
auto mapID = m_ActivityInfo.instanceMapID; auto mapID = m_ActivityInfo.instanceMapID;
if (static_cast<Leaderboard::Type>(activity.leaderboardType) == Leaderboard::Type::Racing && Game::config->GetValue("solo_racing") == "1") { if (static_cast<Leaderboard::Type>(activity.leaderboardType) == Leaderboard::Type::Racing && Game::config->GetValue("solo_racing") == "1") {
@ -532,7 +532,7 @@ void ActivityInstance::RewardParticipant(Entity* participant) {
// First, get the activity data // First, get the activity data
auto* activityRewardsTable = CDClientManager::Instance().GetTable<CDActivityRewardsTable>(); auto* activityRewardsTable = CDClientManager::Instance().GetTable<CDActivityRewardsTable>();
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([=](CDActivityRewards entry) { return (entry.objectTemplate == m_ActivityInfo.ActivityID); }); std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([this](CDActivityRewards entry) { return (entry.objectTemplate == m_ActivityInfo.ActivityID); });
if (!activityRewards.empty()) { if (!activityRewards.empty()) {
uint32_t minCoins = 0; uint32_t minCoins = 0;

View File

@ -312,7 +312,7 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
} }
// Respawn the player in 2 seconds, as was done in live. Not sure if this value is in a setting somewhere else... // Respawn the player in 2 seconds, as was done in live. Not sure if this value is in a setting somewhere else...
vehicle->AddCallbackTimer(2.0f, [=]() { vehicle->AddCallbackTimer(2.0f, [=, this]() {
if (!vehicle || !this->m_Parent) return; if (!vehicle || !this->m_Parent) return;
GameMessages::SendRacingResetPlayerToLastReset( GameMessages::SendRacingResetPlayerToLastReset(
m_Parent->GetObjectID(), racingPlayer.playerID, m_Parent->GetObjectID(), racingPlayer.playerID,

View File

@ -249,7 +249,7 @@ bool Item::IsEquipped() const {
bool Item::Consume() { bool Item::Consume() {
auto* skillsTable = CDClientManager::Instance().GetTable<CDObjectSkillsTable>(); auto* skillsTable = CDClientManager::Instance().GetTable<CDObjectSkillsTable>();
auto skills = skillsTable->Query([=](const CDObjectSkills entry) { auto skills = skillsTable->Query([this](const CDObjectSkills entry) {
return entry.objectTemplate == static_cast<uint32_t>(lot); return entry.objectTemplate == static_cast<uint32_t>(lot);
}); });

View File

@ -294,10 +294,8 @@ void VanityUtilities::ParseXML(const std::string& file) {
auto* partyPhrases = npcs->FirstChildElement("partyphrases"); auto* partyPhrases = npcs->FirstChildElement("partyphrases");
if (partyPhrases == nullptr) { if (partyPhrases == nullptr) {
LOG("Failed to parse party phrases"); LOG("No party phrases found");
return; } else {
}
for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr; for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr;
phrase = phrase->NextSiblingElement("phrase")) { phrase = phrase->NextSiblingElement("phrase")) {
// Get the phrase // Get the phrase
@ -310,6 +308,7 @@ void VanityUtilities::ParseXML(const std::string& file) {
m_PartyPhrases.push_back(text); m_PartyPhrases.push_back(text);
} }
}
for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) { for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) {
// Get the NPC name // Get the NPC name

View File

@ -134,7 +134,7 @@ void InstanceManager::RemoveInstance(Instance* instance) {
if (m_Instances[i] == instance) { if (m_Instances[i] == instance) {
instance->SetShutdownComplete(true); instance->SetShutdownComplete(true);
if (!Game::shouldShutdown) RedirectPendingRequests(instance); if (!Game::ShouldShutdown()) RedirectPendingRequests(instance);
delete m_Instances[i]; delete m_Instances[i];

View File

@ -47,12 +47,13 @@ namespace Game {
InstanceManager* im = nullptr; InstanceManager* im = nullptr;
dConfig* config = nullptr; dConfig* config = nullptr;
AssetManager* assetManager = nullptr; AssetManager* assetManager = nullptr;
bool shouldShutdown = false; Game::signal_t lastSignal = 0;
bool universeShutdownRequested = false;
std::mt19937 randomEngine; std::mt19937 randomEngine;
} //namespace Game } //namespace Game
bool shutdownSequenceStarted = false; bool shutdownSequenceStarted = false;
void ShutdownSequence(int32_t signal = -1); int ShutdownSequence(int32_t signal = -1);
int32_t FinalizeShutdown(int32_t signal = -1); int32_t FinalizeShutdown(int32_t signal = -1);
Logger* SetupLogger(); Logger* SetupLogger();
void HandlePacket(Packet* packet); void HandlePacket(Packet* packet);
@ -73,8 +74,8 @@ int main(int argc, char** argv) {
//Triggers the shutdown sequence at application exit //Triggers the shutdown sequence at application exit
std::atexit([]() { ShutdownSequence(); }); std::atexit([]() { ShutdownSequence(); });
signal(SIGINT, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); }); std::signal(SIGINT, Game::OnSignal);
signal(SIGTERM, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); }); std::signal(SIGTERM, Game::OnSignal);
//Create all the objects we need to run our service: //Create all the objects we need to run our service:
Game::logger = SetupLogger(); Game::logger = SetupLogger();
@ -286,7 +287,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("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
if (Game::config->GetValue("port") != "") ourPort = std::stoi(Game::config->GetValue("port")); 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::shouldShutdown); Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal);
//Query for the database for a server labeled "master" //Query for the database for a server labeled "master"
@ -321,7 +322,8 @@ int main(int argc, char** argv) {
uint32_t framesSinceLastSQLPing = 0; uint32_t framesSinceLastSQLPing = 0;
uint32_t framesSinceKillUniverseCommand = 0; uint32_t framesSinceKillUniverseCommand = 0;
while (true) { Game::logger->Flush();
while (!Game::ShouldShutdown()) {
//In world we'd update our other systems here. //In world we'd update our other systems here.
//Check for packets here: //Check for packets here:
@ -355,10 +357,10 @@ int main(int argc, char** argv) {
framesSinceLastSQLPing++; framesSinceLastSQLPing++;
//10m shutdown for universe kill command //10m shutdown for universe kill command
if (Game::shouldShutdown) { if (Game::universeShutdownRequested) {
if (framesSinceKillUniverseCommand >= shutdownUniverseTime) { if (framesSinceKillUniverseCommand >= shutdownUniverseTime) {
//Break main loop and exit //Break main loop and exit
break; Game::lastSignal = -1;
} else } else
framesSinceKillUniverseCommand++; framesSinceKillUniverseCommand++;
} }
@ -402,7 +404,7 @@ int main(int argc, char** argv) {
t += std::chrono::milliseconds(masterFrameDelta); t += std::chrono::milliseconds(masterFrameDelta);
std::this_thread::sleep_until(t); std::this_thread::sleep_until(t);
} }
return FinalizeShutdown(EXIT_SUCCESS); return ShutdownSequence(EXIT_SUCCESS);
} }
Logger* SetupLogger() { Logger* SetupLogger() {
@ -799,7 +801,7 @@ void HandlePacket(Packet* packet) {
case eMasterMessageType::SHUTDOWN_UNIVERSE: { case eMasterMessageType::SHUTDOWN_UNIVERSE: {
LOG("Received shutdown universe command, shutting down in 10 minutes."); LOG("Received shutdown universe command, shutting down in 10 minutes.");
Game::shouldShutdown = true; Game::universeShutdownRequested = true;
break; break;
} }
@ -809,9 +811,11 @@ void HandlePacket(Packet* packet) {
} }
} }
void ShutdownSequence(int32_t signal) { int ShutdownSequence(int32_t signal) {
LOG("Recieved Signal %d", signal);
if (shutdownSequenceStarted) { if (shutdownSequenceStarted) {
return; LOG("Duplicate Shutdown Sequence");
return -1;
} }
if (!Game::im) { if (!Game::im) {
@ -820,7 +824,7 @@ void ShutdownSequence(int32_t signal) {
Game::im->SetIsShuttingDown(true); Game::im->SetIsShuttingDown(true);
shutdownSequenceStarted = true; shutdownSequenceStarted = true;
Game::shouldShutdown = true; Game::lastSignal = -1;
{ {
CBITSTREAM; CBITSTREAM;
@ -889,7 +893,7 @@ void ShutdownSequence(int32_t signal) {
} }
} }
FinalizeShutdown(signal); return FinalizeShutdown(signal);
} }
int32_t FinalizeShutdown(int32_t signal) { int32_t FinalizeShutdown(int32_t signal) {

View File

@ -5,7 +5,7 @@
#include "BinaryPathFinder.h" #include "BinaryPathFinder.h"
void StartChatServer() { void StartChatServer() {
if (Game::shouldShutdown) { if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Chat will not be restarted."); LOG("Currently shutting down. Chat will not be restarted.");
return; return;
} }
@ -24,7 +24,7 @@ void StartChatServer() {
} }
void StartAuthServer() { void StartAuthServer() {
if (Game::shouldShutdown) { if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Auth will not be restarted."); LOG("Currently shutting down. Auth will not be restarted.");
return; return;
} }

View File

@ -55,7 +55,9 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c
RakNet::BitStream bitStream; RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM); BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM);
uint32_t netVersion; uint32_t netVersion;
if (!GeneralUtils::TryParse(Game::config->GetValue("client_net_version"), netVersion)) { const std::string& expectedVersion = Game::config->GetValue("client_net_version");
LOG("Expected Version: '%s'", expectedVersion.c_str());
if (!GeneralUtils::TryParse(expectedVersion, netVersion)) {
LOG("Failed to parse client_net_version. Cannot authenticate to %s:%i", nextServerIP.c_str(), nextServerPort); LOG("Failed to parse client_net_version. Cannot authenticate to %s:%i", nextServerIP.c_str(), nextServerPort);
return; return;
} }

View File

@ -39,7 +39,7 @@ public:
} }
} ReceiveDownloadCompleteCB; } ReceiveDownloadCompleteCB;
dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, bool* shouldShutdown, unsigned int zoneID) { dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
mIP = ip; mIP = ip;
mPort = port; mPort = port;
mZoneID = zoneID; mZoneID = zoneID;
@ -55,7 +55,7 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
mReplicaManager = nullptr; mReplicaManager = nullptr;
mServerType = serverType; mServerType = serverType;
mConfig = config; mConfig = config;
mShouldShutdown = shouldShutdown; mShouldShutdown = lastSignal;
//Attempt to start our server here: //Attempt to start our server here:
mIsOkay = Startup(); mIsOkay = Startup();
@ -75,7 +75,9 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
//Connect to master if we are not master: //Connect to master if we are not master:
if (serverType != ServerType::Master) { if (serverType != ServerType::Master) {
SetupForMasterConnection(); SetupForMasterConnection();
ConnectToMaster(); if (!ConnectToMaster()) {
LOG("Failed ConnectToMaster!");
}
} }
//Set up Replica if we're a world server: //Set up Replica if we're a world server:
@ -129,7 +131,7 @@ Packet* dServer::ReceiveFromMaster() {
break; break;
} }
case eMasterMessageType::SHUTDOWN: case eMasterMessageType::SHUTDOWN:
*mShouldShutdown = true; *mShouldShutdown = -2;
break; 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.
@ -236,10 +238,12 @@ void dServer::Shutdown() {
void dServer::SetupForMasterConnection() { void dServer::SetupForMasterConnection() {
mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0); mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
mMasterPeer = RakNetworkFactory::GetRakPeerInterface(); mMasterPeer = RakNetworkFactory::GetRakPeerInterface();
mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1); bool ret = mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1);
if (!ret) LOG("Failed MasterPeer Startup!");
} }
bool dServer::ConnectToMaster() { bool dServer::ConnectToMaster() {
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15); return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <string> #include <string>
#include <csignal>
#include "RakPeerInterface.h" #include "RakPeerInterface.h"
#include "ReplicaManager.h" #include "ReplicaManager.h"
#include "NetworkIDManager.h" #include "NetworkIDManager.h"
@ -15,6 +16,10 @@ enum class ServerType : uint32_t {
World World
}; };
namespace Game {
using signal_t = volatile std::sig_atomic_t;
}
class dServer { class dServer {
public: public:
// Default constructor should only used for testing! // Default constructor should only used for testing!
@ -31,7 +36,7 @@ public:
int masterPort, int masterPort,
ServerType serverType, ServerType serverType,
dConfig* config, dConfig* config,
bool* shouldShutdown, Game::signal_t* shouldShutdown,
unsigned int zoneID = 0); unsigned int zoneID = 0);
~dServer(); ~dServer();
@ -81,9 +86,9 @@ private:
NetworkIDManager* mNetIDManager = nullptr; NetworkIDManager* mNetIDManager = nullptr;
/** /**
* Whether or not to shut down the server. Pointer to Game::shouldShutdown. * Whether or not to shut down the server. Pointer to Game::lastSignal.
*/ */
bool* mShouldShutdown = nullptr; Game::signal_t* mShouldShutdown = nullptr;
SocketDescriptor mSocketDescriptor; SocketDescriptor mSocketDescriptor;
std::string mIP; std::string mIP;
int mPort; int mPort;

View File

@ -88,7 +88,7 @@ namespace Game {
RakPeerInterface* chatServer = nullptr; RakPeerInterface* chatServer = nullptr;
std::mt19937 randomEngine; std::mt19937 randomEngine;
SystemAddress chatSysAddr; SystemAddress chatSysAddr;
bool shouldShutdown = false; Game::signal_t lastSignal = 0;
EntityManager* entityManager = nullptr; EntityManager* entityManager = nullptr;
dZoneManager* zoneManager = nullptr; dZoneManager* zoneManager = nullptr;
std::string projectVersion = PROJECT_VERSION; std::string projectVersion = PROJECT_VERSION;
@ -124,8 +124,8 @@ int main(int argc, char** argv) {
// Triggers the shutdown sequence at application exit // Triggers the shutdown sequence at application exit
std::atexit(WorldShutdownSequence); std::atexit(WorldShutdownSequence);
signal(SIGINT, [](int) { WorldShutdownSequence(); }); std::signal(SIGINT, Game::OnSignal);
signal(SIGTERM, [](int) { WorldShutdownSequence(); }); std::signal(SIGTERM, Game::OnSignal);
uint32_t zoneID = 1000; uint32_t zoneID = 1000;
uint32_t cloneID = 0; uint32_t cloneID = 0;
@ -212,7 +212,7 @@ int main(int argc, char** argv) {
UserManager::Instance()->Initialize(); UserManager::Instance()->Initialize();
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(Game::config->GetValue("dont_generate_dcf"))));
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::shouldShutdown, zoneID); Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, zoneID);
//Connect to the chat server: //Connect to the chat server:
uint32_t chatPort = 1501; uint32_t chatPort = 1501;
@ -313,6 +313,8 @@ int main(int argc, char** argv) {
uint32_t saveTime = 10 * 60 * currentFramerate; // 10 minutes in frames uint32_t saveTime = 10 * 60 * currentFramerate; // 10 minutes in frames
uint32_t sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames uint32_t sqlPingTime = 10 * 60 * currentFramerate; // 10 minutes in frames
uint32_t emptyShutdownTime = (cloneID == 0 ? 30 : 5) * 60 * currentFramerate; // 30 minutes for main worlds, 5 for all others. uint32_t emptyShutdownTime = (cloneID == 0 ? 30 : 5) * 60 * currentFramerate; // 30 minutes for main worlds, 5 for all others.
Game::logger->Flush(); // once immediately before the main loop
while (true) { while (true) {
Metrics::StartMeasurement(MetricVariable::Frame); Metrics::StartMeasurement(MetricVariable::Frame);
Metrics::StartMeasurement(MetricVariable::GameLoop); Metrics::StartMeasurement(MetricVariable::GameLoop);
@ -363,9 +365,9 @@ int main(int argc, char** argv) {
if (!Game::server->GetIsConnectedToMaster()) { if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++; framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= noMasterConnectionTimeout && !Game::shouldShutdown) { if (framesSinceMasterDisconnect >= noMasterConnectionTimeout && !Game::ShouldShutdown()) {
LOG("Game loop running but no connection to master for %d frames, shutting down", noMasterConnectionTimeout); LOG("Game loop running but no connection to master for %d frames, shutting down", noMasterConnectionTimeout);
Game::shouldShutdown = true; Game::lastSignal = -1;
} }
} else framesSinceMasterDisconnect = 0; } else framesSinceMasterDisconnect = 0;
@ -460,7 +462,7 @@ int main(int argc, char** argv) {
//If we haven't had any players for a while, time out and shut down: //If we haven't had any players for a while, time out and shut down:
if (framesSinceLastUser >= emptyShutdownTime) { if (framesSinceLastUser >= emptyShutdownTime) {
Game::shouldShutdown = true; Game::lastSignal = -1;
} }
} else { } else {
framesSinceLastUser = 0; framesSinceLastUser = 0;
@ -513,7 +515,7 @@ int main(int argc, char** argv) {
} }
} }
if (Game::shouldShutdown && !worldShutdownSequenceComplete) { if (Game::ShouldShutdown() && !worldShutdownSequenceComplete) {
WorldShutdownProcess(zoneID); WorldShutdownProcess(zoneID);
break; break;
} }
@ -822,7 +824,7 @@ void HandlePacket(Packet* packet) {
} }
case eMasterMessageType::SHUTDOWN: { case eMasterMessageType::SHUTDOWN: {
Game::shouldShutdown = true; Game::lastSignal = -1;
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID()); LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
break; break;
} }
@ -1289,9 +1291,9 @@ void WorldShutdownProcess(uint32_t zoneId) {
} }
void WorldShutdownSequence() { void WorldShutdownSequence() {
Game::shouldShutdown = true; Game::lastSignal = -1;
#ifndef DARKFLAME_PLATFORM_WIN32 #ifndef DARKFLAME_PLATFORM_WIN32
if (Game::shouldShutdown || worldShutdownSequenceComplete) if (Game::ShouldShutdown() || worldShutdownSequenceComplete)
#endif #endif
{ {
return; return;

View File

@ -51,20 +51,20 @@ Spawner::Spawner(const SpawnerInfo info) {
std::vector<Spawner*> spawnSmashSpawnersN = Game::zoneManager->GetSpawnersByName(m_Info.spawnOnSmashGroupName); std::vector<Spawner*> spawnSmashSpawnersN = Game::zoneManager->GetSpawnersByName(m_Info.spawnOnSmashGroupName);
for (Entity* ssEntity : spawnSmashEntities) { for (Entity* ssEntity : spawnSmashEntities) {
m_SpawnSmashFoundGroup = true; m_SpawnSmashFoundGroup = true;
ssEntity->AddDieCallback([=]() { ssEntity->AddDieCallback([=, this]() {
Spawn(); Spawn();
}); });
} }
for (Spawner* ssSpawner : spawnSmashSpawners) { for (Spawner* ssSpawner : spawnSmashSpawners) {
m_SpawnSmashFoundGroup = true; m_SpawnSmashFoundGroup = true;
ssSpawner->AddSpawnedEntityDieCallback([=]() { ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
Spawn(); Spawn();
}); });
} }
for (Spawner* ssSpawner : spawnSmashSpawnersN) { for (Spawner* ssSpawner : spawnSmashSpawnersN) {
m_SpawnSmashFoundGroup = true; m_SpawnSmashFoundGroup = true;
m_SpawnOnSmash = ssSpawner; m_SpawnOnSmash = ssSpawner;
ssSpawner->AddSpawnedEntityDieCallback([=]() { ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
Spawn(); Spawn();
}); });
} }

View File

@ -26,7 +26,7 @@ TEST_F(EncodingTest, TestEncodingHello) {
}; };
TEST_F(EncodingTest, TestEncodingUmlaut) { TEST_F(EncodingTest, TestEncodingUmlaut) {
originalWord = u8"Frühling"; originalWord = reinterpret_cast<const char*>(u8"Frühling");
originalWordSv = originalWord; originalWordSv = originalWord;
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'F'); GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'F');

View File

@ -80,6 +80,8 @@ target_compile_options(raknet PRIVATE
$<$<CXX_COMPILER_ID:MSVC>: $<$<CXX_COMPILER_ID:MSVC>:
/w>) /w>)
set_property(TARGET raknet PROPERTY CXX_STANDARD 17)
if(WIN32) if(WIN32)
# Link Win Sockets 2 to RakNet # Link Win Sockets 2 to RakNet
target_link_libraries(raknet ws2_32) target_link_libraries(raknet ws2_32)