mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
16 Commits
chore--mak
...
crash_fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79bc6e73ff | ||
|
|
bb79528c0e | ||
|
|
b1134b340f | ||
|
|
1941679d27 | ||
|
|
85672e060a | ||
|
|
18feea5fed | ||
|
|
e54faa3820 | ||
|
|
4ecb6ae30e | ||
|
|
c708246f73 | ||
|
|
295ba628c2 | ||
|
|
d8f74f008f | ||
|
|
42a71bbeab | ||
|
|
98d2f25af2 | ||
|
|
dd9d94f75f | ||
|
|
f08df25085 | ||
|
|
a19bead268 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -122,3 +122,4 @@ docker/__pycache__
|
||||
docker-compose.override.yml
|
||||
|
||||
!*Test.bin
|
||||
!cmake/*
|
||||
|
||||
123
CMakeLists.txt
123
CMakeLists.txt
@@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.18)
|
||||
project(Darkflame)
|
||||
include(CTest)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
# Read variables from file
|
||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||
@@ -14,30 +15,26 @@ string(REPLACE "\n" ";" variables ${variables})
|
||||
foreach(variable ${variables})
|
||||
# If the string contains a #, skip it
|
||||
if(NOT "${variable}" MATCHES "#")
|
||||
|
||||
# Split the variable into name and value
|
||||
string(REPLACE "=" ";" variable ${variable})
|
||||
|
||||
# Check that the length of the variable is 2 (name and value)
|
||||
list(LENGTH variable length)
|
||||
if(${length} EQUAL 2)
|
||||
|
||||
if(${length} EQUAL 2)
|
||||
list(GET variable 0 variable_name)
|
||||
list(GET variable 1 variable_value)
|
||||
|
||||
# Set the variable
|
||||
set(${variable_name} ${variable_value})
|
||||
|
||||
# Add compiler definition
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${variable_name}=${variable_value}")
|
||||
|
||||
message(STATUS "Variable: ${variable_name} = ${variable_value}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Set the version
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(PROJECT_VERSION "\"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}\"")
|
||||
|
||||
# Echo the version
|
||||
message(STATUS "Version: ${PROJECT_VERSION}")
|
||||
@@ -53,19 +50,22 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
||||
# Disabled no-register
|
||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}")
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC -lstdc++fs")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -fPIC")
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
||||
|
||||
if(NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -lstdc++fs")
|
||||
endif()
|
||||
if (__dynamic AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
|
||||
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
||||
endif()
|
||||
if (__ggdb)
|
||||
|
||||
if(${GGDB})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
||||
elseif(MSVC)
|
||||
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
||||
@@ -98,47 +98,61 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||
# Copy resource files on first build
|
||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||
message(STATUS "Checking resource file integrity")
|
||||
foreach (resource_file ${RESOURCE_FILES})
|
||||
|
||||
include(Utils)
|
||||
|
||||
foreach(resource_file ${RESOURCE_FILES})
|
||||
set(file_size 0)
|
||||
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||
|
||||
if(EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
||||
endif()
|
||||
if (${file_size} EQUAL 0)
|
||||
|
||||
if(${file_size} EQUAL 0)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||
COPYONLY
|
||||
)
|
||||
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
||||
elseif (resource_file MATCHES ".ini")
|
||||
elseif(resource_file MATCHES ".ini")
|
||||
message(STATUS "Checking " ${resource_file} " for missing config options")
|
||||
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
||||
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||
set(parsed_current_file_contents "")
|
||||
|
||||
# Remove comment lines so they do not interfere with the variable parsing
|
||||
foreach (line ${current_file_contents})
|
||||
foreach(line ${current_file_contents})
|
||||
string(FIND ${line} "#" is_comment)
|
||||
if (NOT ${is_comment} EQUAL 0)
|
||||
|
||||
if(NOT ${is_comment} EQUAL 0)
|
||||
string(APPEND parsed_current_file_contents ${line})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
|
||||
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
|
||||
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
|
||||
set(line_to_add "")
|
||||
foreach (line ${depot_file_contents})
|
||||
|
||||
foreach(line ${depot_file_contents})
|
||||
string(FIND ${line} "#" is_comment)
|
||||
if (NOT ${is_comment} EQUAL 0)
|
||||
|
||||
if(NOT ${is_comment} EQUAL 0)
|
||||
string(REPLACE "=" ";" line_split ${line})
|
||||
list(GET line_split 0 variable_name)
|
||||
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||
|
||||
if(NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
foreach (line_to_append ${line_to_add})
|
||||
|
||||
foreach(line_to_append ${line_to_add})
|
||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
||||
endforeach()
|
||||
|
||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
||||
endif()
|
||||
|
||||
set(line_to_add "")
|
||||
else()
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
@@ -146,24 +160,23 @@ foreach (resource_file ${RESOURCE_FILES})
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message(STATUS "Resource file integrity check complete")
|
||||
|
||||
# if navmeshes directory does not exist, create it
|
||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes)
|
||||
if(NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes)
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/navmeshes)
|
||||
endif()
|
||||
|
||||
# Copy navmesh data on first build and extract it
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip
|
||||
COPYONLY
|
||||
)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip COPYONLY)
|
||||
|
||||
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PROJECT_BINARY_DIR}/navmeshes)
|
||||
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
|
||||
|
||||
# Copy vanity files on first build
|
||||
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")
|
||||
|
||||
foreach(file ${VANITY_FILES})
|
||||
configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY)
|
||||
endforeach()
|
||||
@@ -171,26 +184,18 @@ endforeach()
|
||||
# Move our migrations for MasterServer to run
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
|
||||
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
|
||||
|
||||
foreach(file ${SQL_FILES})
|
||||
get_filename_component(file ${file} NAME)
|
||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file}
|
||||
COPYONLY
|
||||
)
|
||||
endif()
|
||||
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
|
||||
endforeach()
|
||||
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/cdserver/)
|
||||
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/cdserver/*.sql)
|
||||
|
||||
foreach(file ${SQL_FILES})
|
||||
get_filename_component(file ${file} NAME)
|
||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file}
|
||||
COPYONLY
|
||||
)
|
||||
endif()
|
||||
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
|
||||
endforeach()
|
||||
|
||||
# Create our list of include directories
|
||||
@@ -198,7 +203,9 @@ set(INCLUDED_DIRECTORIES
|
||||
"dCommon"
|
||||
"dCommon/dClient"
|
||||
"dCommon/dEnums"
|
||||
|
||||
"dChatFilter"
|
||||
|
||||
"dGame"
|
||||
"dGame/dBehaviors"
|
||||
"dGame/dComponents"
|
||||
@@ -209,10 +216,14 @@ set(INCLUDED_DIRECTORIES
|
||||
"dGame/dPropertyBehaviors"
|
||||
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
|
||||
"dGame/dUtilities"
|
||||
|
||||
"dPhysics"
|
||||
|
||||
"dNavigation"
|
||||
"dNavigation/dTerrain"
|
||||
|
||||
"dZoneManager"
|
||||
|
||||
"dDatabase"
|
||||
"dDatabase/CDClientDatabase"
|
||||
"dDatabase/CDClientDatabase/CDClientTables"
|
||||
@@ -220,7 +231,9 @@ set(INCLUDED_DIRECTORIES
|
||||
"dDatabase/GameDatabase/ITables"
|
||||
"dDatabase/GameDatabase/MySQL"
|
||||
"dDatabase/GameDatabase/MySQL/Tables"
|
||||
|
||||
"dNet"
|
||||
|
||||
"dScripts"
|
||||
"dScripts/02_server"
|
||||
"dScripts/ai"
|
||||
@@ -304,28 +317,24 @@ set(INCLUDED_DIRECTORIES
|
||||
"tests/dCommonTests"
|
||||
"tests/dGameTests"
|
||||
"tests/dGameTests/dComponentsTests"
|
||||
)
|
||||
)
|
||||
|
||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||
if (APPLE)
|
||||
if(APPLE)
|
||||
include_directories("/usr/local/include/")
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include")
|
||||
elseif (UNIX)
|
||||
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt")
|
||||
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt")
|
||||
endif()
|
||||
|
||||
# Add binary directory as an include directory
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
# Actually include the directories from our list
|
||||
foreach (dir ${INCLUDED_DIRECTORIES})
|
||||
foreach(dir ${INCLUDED_DIRECTORIES})
|
||||
include_directories(${PROJECT_SOURCE_DIR}/${dir})
|
||||
endforeach()
|
||||
|
||||
if(NOT WIN32)
|
||||
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt")
|
||||
endif()
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include")
|
||||
|
||||
# Add linking directories:
|
||||
link_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
@@ -378,10 +387,10 @@ add_subdirectory(dPhysics)
|
||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum")
|
||||
|
||||
# Add platform specific common libraries
|
||||
if (UNIX)
|
||||
if(UNIX)
|
||||
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "dl" "pthread")
|
||||
|
||||
if (NOT APPLE AND __include_backtrace__)
|
||||
if(NOT APPLE AND ${INCLUDE_BACKTRACE})
|
||||
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "backtrace")
|
||||
endif()
|
||||
endif()
|
||||
@@ -419,6 +428,6 @@ target_precompile_headers(
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
|
||||
)
|
||||
|
||||
if (${__enable_testing__} MATCHES "1")
|
||||
if(${ENABLE_TESTING})
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
PROJECT_VERSION_MAJOR=1
|
||||
PROJECT_VERSION_MINOR=1
|
||||
PROJECT_VERSION_PATCH=1
|
||||
# LICENSE
|
||||
LICENSE=AGPL-3.0
|
||||
|
||||
# Debugging
|
||||
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||
__dynamic=1
|
||||
# Set __ggdb to 1 to enable the -ggdb flag for the linker, including more debug info.
|
||||
# __ggdb=1
|
||||
# Set __include_backtrace__ to 1 to includes the backtrace library for better crashlogs.
|
||||
# __include_backtrace__=1
|
||||
# Set __compile_backtrace__ to 1 to compile the backtrace library instead of using system libraries.
|
||||
# __compile_backtrace__=1
|
||||
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||
DYNAMIC=1
|
||||
|
||||
# Set GGDB to 1 to enable the -ggdb flag for the linker, including more debug info.
|
||||
# Do note, changing this will re-build the whole server
|
||||
GGDB=0
|
||||
|
||||
# Set INCLUDE_BACKTRACE to 1 to includes the backtrace library for better crashlogs.
|
||||
# Do note, changing this will re-build the whole server
|
||||
INCLUDE_BACKTRACE=0
|
||||
|
||||
# Set COMPILE_BACKTRACE to 1 to compile the backtrace library instead of using system libraries.
|
||||
# Do note, changing this will re-build the whole server
|
||||
COMPILE_BACKTRACE=0
|
||||
|
||||
# Set to the number of jobs (make -j equivalent) to compile the mariadbconn files with.
|
||||
__maria_db_connector_compile_jobs__=1
|
||||
MARIADB_CONNECTOR_COMPILE_JOBS=1
|
||||
|
||||
# When set to 1 and uncommented, compiling and linking testing folders and libraries will be done.
|
||||
__enable_testing__=1
|
||||
ENABLE_TESTING=1
|
||||
|
||||
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
||||
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
||||
# Uncomment the below line to cache the entire CDClient into memory
|
||||
# CDCLIENT_CACHE_ALL=1
|
||||
|
||||
# Whether or not to cache the entire CDClient Database into memory instead of lazy loading.
|
||||
# 0 means to lazy load, all other values mean load the entire database.
|
||||
CDCLIENT_CACHE_ALL=0
|
||||
|
||||
47
cmake/Utils.cmake
Normal file
47
cmake/Utils.cmake
Normal file
@@ -0,0 +1,47 @@
|
||||
# Parses a config file for a specific option and appends the new option if it does not exist
|
||||
# If the new option does exist, this function will do nothing.
|
||||
# file_name: The name of the file to parse
|
||||
# old_option_name: The name of the option to find
|
||||
# new_option_name: The name of the option to add
|
||||
function(UpdateConfigOption file_name old_option_name new_option_name)
|
||||
string(APPEND old_option_name "=")
|
||||
string(APPEND new_option_name "=")
|
||||
message(STATUS "Checking " ${file_name} " for " ${old_option_name} " and adding " ${new_option_name} " if it does not exist")
|
||||
file(READ ${file_name} current_file_contents)
|
||||
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||
set(parsed_current_file_contents "")
|
||||
|
||||
# Remove comment lines so they do not interfere with the variable parsing
|
||||
foreach(line ${current_file_contents})
|
||||
string(FIND ${line} "#" is_comment)
|
||||
|
||||
if(NOT ${is_comment} EQUAL 0)
|
||||
string(APPEND parsed_current_file_contents ${line})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(found_new_option -1)
|
||||
set(found_old_option -1)
|
||||
set(current_value -1)
|
||||
|
||||
foreach(line ${current_file_contents})
|
||||
string(FIND ${line} ${old_option_name} old_option_in_file)
|
||||
|
||||
if(${old_option_in_file} EQUAL 0)
|
||||
set(found_old_option 1)
|
||||
set(current_value ${line})
|
||||
endif()
|
||||
|
||||
string(FIND ${line} ${new_option_name} found_new_option_in_file)
|
||||
|
||||
if(${found_new_option_in_file} EQUAL 0)
|
||||
set(found_new_option 1)
|
||||
endif()
|
||||
endforeach(line ${current_file_contents})
|
||||
|
||||
if(${found_old_option} EQUAL 1 AND NOT ${found_new_option} EQUAL 1)
|
||||
string(REPLACE ${old_option_name} ${new_option_name} current_value ${current_value})
|
||||
file(APPEND ${file_name} "\n" ${current_value})
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <csignal>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
@@ -28,7 +29,7 @@ namespace Game {
|
||||
Logger* logger = nullptr;
|
||||
dServer* server = nullptr;
|
||||
dConfig* config = nullptr;
|
||||
bool shouldShutdown = false;
|
||||
Game::signal_t lastSignal = 0;
|
||||
std::mt19937 randomEngine;
|
||||
}
|
||||
|
||||
@@ -42,17 +43,20 @@ int main(int argc, char** argv) {
|
||||
Diagnostics::SetProcessFileName(argv[0]);
|
||||
Diagnostics::Initialize();
|
||||
|
||||
std::signal(SIGINT, Game::OnSignal);
|
||||
std::signal(SIGTERM, Game::OnSignal);
|
||||
|
||||
//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::config = new dConfig("authconfig.ini");
|
||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||
|
||||
LOG("Starting Auth server...");
|
||||
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||
LOG("Version: %s", PROJECT_VERSION);
|
||||
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||
|
||||
try {
|
||||
@@ -74,6 +78,7 @@ int main(int argc, char** argv) {
|
||||
masterIP = masterInfo->ip;
|
||||
masterPort = masterInfo->port;
|
||||
}
|
||||
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
|
||||
|
||||
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("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:
|
||||
auto t = std::chrono::high_resolution_clock::now();
|
||||
@@ -96,13 +101,16 @@ int main(int argc, char** argv) {
|
||||
|
||||
AuthPackets::LoadClaimCodes();
|
||||
|
||||
while (!Game::shouldShutdown) {
|
||||
Game::logger->Flush(); // once immediately before main loop
|
||||
while (!Game::ShouldShutdown()) {
|
||||
//Check if we're still connected to master:
|
||||
if (!Game::server->GetIsConnectedToMaster()) {
|
||||
framesSinceMasterDisconnect++;
|
||||
|
||||
if (framesSinceMasterDisconnect >= authFramerate)
|
||||
if (framesSinceMasterDisconnect >= authFramerate) {
|
||||
LOG("No connection to master!");
|
||||
break; //Exit our loop, shut down.
|
||||
}
|
||||
} else framesSinceMasterDisconnect = 0;
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
LOG("Exited Main Loop! (signal %d)", Game::lastSignal);
|
||||
//Delete our objects here:
|
||||
Database::Destroy("AuthServer");
|
||||
delete Game::server;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
add_executable(AuthServer "AuthServer.cpp")
|
||||
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
|
||||
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||
|
||||
@@ -6,6 +6,7 @@ set(DCHATSERVER_SOURCES
|
||||
|
||||
add_executable(ChatServer "ChatServer.cpp")
|
||||
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||
|
||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer)
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Game {
|
||||
dConfig* config = nullptr;
|
||||
dChatFilter* chatFilter = nullptr;
|
||||
AssetManager* assetManager = nullptr;
|
||||
bool shouldShutdown = false;
|
||||
Game::signal_t lastSignal = 0;
|
||||
std::mt19937 randomEngine;
|
||||
PlayerContainer playerContainer;
|
||||
}
|
||||
@@ -48,17 +48,20 @@ int main(int argc, char** argv) {
|
||||
Diagnostics::SetProcessFileName(argv[0]);
|
||||
Diagnostics::Initialize();
|
||||
|
||||
std::signal(SIGINT, Game::OnSignal);
|
||||
std::signal(SIGTERM, Game::OnSignal);
|
||||
|
||||
//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::config = new dConfig("chatconfig.ini");
|
||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||
|
||||
LOG("Starting Chat server...");
|
||||
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||
LOG("Version: %s", PROJECT_VERSION);
|
||||
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||
|
||||
try {
|
||||
@@ -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("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"))));
|
||||
|
||||
@@ -118,7 +121,8 @@ int main(int argc, char** argv) {
|
||||
uint32_t framesSinceMasterDisconnect = 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:
|
||||
if (!Game::server->GetIsConnectedToMaster()) {
|
||||
framesSinceMasterDisconnect++;
|
||||
|
||||
@@ -5,6 +5,7 @@ set(DCOMMON_SOURCES
|
||||
"dConfig.cpp"
|
||||
"Diagnostics.cpp"
|
||||
"Logger.cpp"
|
||||
"Game.cpp"
|
||||
"GeneralUtils.cpp"
|
||||
"LDFFormat.cpp"
|
||||
"MD5.cpp"
|
||||
|
||||
@@ -71,7 +71,7 @@ LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e) {
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
|
||||
#if defined(__include_backtrace__)
|
||||
#if defined(INCLUDE_BACKTRACE)
|
||||
#include <backtrace.h>
|
||||
|
||||
#include <backtrace-supported.h>
|
||||
@@ -115,7 +115,14 @@ void GenerateDump() {
|
||||
}
|
||||
|
||||
void CatchUnhandled(int sig) {
|
||||
#ifndef __include_backtrace__
|
||||
std::exception_ptr eptr = std::current_exception();
|
||||
try {
|
||||
if (eptr) std::rethrow_exception(eptr);
|
||||
} catch(const std::exception& e) {
|
||||
LOG("Caught exception: '%s'", e.what());
|
||||
}
|
||||
|
||||
#ifndef INCLUDE_BACKTRACE
|
||||
|
||||
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
|
||||
LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
|
||||
@@ -167,7 +174,7 @@ void CatchUnhandled(int sig) {
|
||||
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
||||
# endif // defined(__GNUG__)
|
||||
|
||||
#else // __include_backtrace__
|
||||
#else // INCLUDE_BACKTRACE
|
||||
|
||||
struct backtrace_state* state = backtrace_create_state(
|
||||
Diagnostics::GetProcessFileName().c_str(),
|
||||
@@ -178,7 +185,7 @@ void CatchUnhandled(int sig) {
|
||||
struct bt_ctx ctx = { state, 0 };
|
||||
Bt(state);
|
||||
|
||||
#endif // __include_backtrace__
|
||||
#endif // INCLUDE_BACKTRACE
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
7
dCommon/Game.cpp
Normal file
7
dCommon/Game.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "Game.h"
|
||||
|
||||
namespace Game {
|
||||
void OnSignal(int signal) {
|
||||
lastSignal = signal;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <random>
|
||||
#include <csignal>
|
||||
|
||||
class dServer;
|
||||
class Logger;
|
||||
@@ -15,6 +17,7 @@ class dZoneManager;
|
||||
class PlayerContainer;
|
||||
|
||||
namespace Game {
|
||||
using signal_t = volatile std::sig_atomic_t;
|
||||
extern Logger* logger;
|
||||
extern dServer* server;
|
||||
extern InstanceManager* im;
|
||||
@@ -24,8 +27,14 @@ namespace Game {
|
||||
extern RakPeerInterface* chatServer;
|
||||
extern AssetManager* assetManager;
|
||||
extern SystemAddress chatSysAddr;
|
||||
extern bool shouldShutdown;
|
||||
extern signal_t lastSignal;
|
||||
extern EntityManager* entityManager;
|
||||
extern dZoneManager* zoneManager;
|
||||
extern PlayerContainer playerContainer;
|
||||
extern std::string projectVersion;
|
||||
|
||||
inline bool ShouldShutdown() {
|
||||
return lastSignal != 0;
|
||||
}
|
||||
void OnSignal(int signal);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
Writer::~Writer() {
|
||||
// Flush before we close
|
||||
Flush();
|
||||
// Dont try to close stdcout...
|
||||
if (!m_Outfile || m_IsConsoleWriter) return;
|
||||
|
||||
@@ -14,7 +16,7 @@ Writer::~Writer() {
|
||||
}
|
||||
|
||||
void Writer::Log(const char* time, const char* message) {
|
||||
if (!m_Outfile) return;
|
||||
if (!m_Outfile || !m_Enabled) return;
|
||||
|
||||
fputs(time, m_Outfile);
|
||||
fputs(message, m_Outfile);
|
||||
|
||||
@@ -10,8 +10,23 @@ dConfig::dConfig(const std::string& filepath) {
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
std::filesystem::path GetConfigDir() {
|
||||
std::filesystem::path config_dir = BinaryPathFinder::GetBinaryDir();
|
||||
if (const char* env_p = std::getenv("DLU_CONFIG_DIR")) {
|
||||
config_dir /= env_p;
|
||||
}
|
||||
return config_dir;
|
||||
}
|
||||
|
||||
const bool dConfig::Exists(const std::string& filepath) {
|
||||
std::filesystem::path config_dir = GetConfigDir();
|
||||
return std::filesystem::exists(config_dir / filepath);
|
||||
}
|
||||
|
||||
void dConfig::LoadConfig() {
|
||||
std::ifstream in(BinaryPathFinder::GetBinaryDir() / m_ConfigFilePath);
|
||||
std::filesystem::path config_dir = GetConfigDir();
|
||||
|
||||
std::ifstream in(config_dir / m_ConfigFilePath);
|
||||
if (!in.good()) return;
|
||||
|
||||
std::string line{};
|
||||
@@ -19,7 +34,7 @@ void dConfig::LoadConfig() {
|
||||
if (!line.empty() && line.front() != '#') ProcessLine(line);
|
||||
}
|
||||
|
||||
std::ifstream sharedConfig(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini", std::ios::in);
|
||||
std::ifstream sharedConfig(config_dir / "sharedconfig.ini", std::ios::in);
|
||||
if (!sharedConfig.good()) return;
|
||||
|
||||
line.clear();
|
||||
@@ -34,6 +49,11 @@ void dConfig::ReloadConfig() {
|
||||
}
|
||||
|
||||
const std::string& dConfig::GetValue(std::string key) {
|
||||
std::string upper_key(key);
|
||||
std::transform(upper_key.begin(), upper_key.end(), upper_key.begin(), ::toupper);
|
||||
if (const char* env_p = std::getenv(upper_key.c_str())) {
|
||||
this->m_ConfigValues[key] = env_p;
|
||||
}
|
||||
return this->m_ConfigValues[key];
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ class dConfig {
|
||||
public:
|
||||
dConfig(const std::string& filepath);
|
||||
|
||||
/**
|
||||
* Checks whether the specified filepath exists
|
||||
*/
|
||||
static const bool Exists(const std::string& filepath);
|
||||
|
||||
/**
|
||||
* Gets the specified key from the config. Returns an empty string if the value is not found.
|
||||
*
|
||||
|
||||
@@ -39,9 +39,11 @@
|
||||
#include "CDRailActivatorComponent.h"
|
||||
#include "CDRewardCodesTable.h"
|
||||
|
||||
#ifndef CDCLIENT_CACHE_ALL
|
||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
||||
// #define CDCLIENT_CACHE_ALL
|
||||
// # define CDCLIENT_CACHE_ALL
|
||||
#endif // CDCLIENT_CACHE_ALL
|
||||
|
||||
#ifdef CDCLIENT_CACHE_ALL
|
||||
#define CDCLIENT_DONT_CACHE_TABLE(x) x
|
||||
|
||||
@@ -14,3 +14,7 @@ endforeach()
|
||||
|
||||
add_library(dDatabase STATIC ${DDATABASE_SOURCES})
|
||||
target_link_libraries(dDatabase sqlite3 mariadbConnCpp)
|
||||
|
||||
if (${CDCLIENT_CACHE_ALL})
|
||||
add_compile_definitions(dDatabase CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})
|
||||
endif()
|
||||
|
||||
@@ -193,7 +193,7 @@ void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t r
|
||||
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
|
||||
WHERE leaderboardsRanked.ranking
|
||||
BETWEEN
|
||||
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
|
||||
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), CAST(lowestRanking.lowestRank AS SIGNED) - 9)
|
||||
AND
|
||||
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
|
||||
ORDER BY ranking ASC;
|
||||
|
||||
@@ -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:
|
||||
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t objectID) {
|
||||
ObjectIDManager::Instance()->RequestPersistentID([=, this](uint32_t objectID) {
|
||||
if (Database::Get()->GetCharacterInfo(objectID)) {
|
||||
LOG("Character object id unavailable, check object_id_tracker!");
|
||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);
|
||||
|
||||
@@ -33,7 +33,7 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo
|
||||
if (activityID > 0) m_ActivityID = activityID;
|
||||
else m_ActivityID = parent->GetVar<int32_t>(u"activityID");
|
||||
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) {
|
||||
m_ActivityInfo = activity;
|
||||
@@ -93,7 +93,7 @@ void ActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIniti
|
||||
|
||||
void ActivityComponent::ReloadConfig() {
|
||||
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) {
|
||||
auto mapID = m_ActivityInfo.instanceMapID;
|
||||
if (static_cast<Leaderboard::Type>(activity.leaderboardType) == Leaderboard::Type::Racing && Game::config->GetValue("solo_racing") == "1") {
|
||||
@@ -115,6 +115,7 @@ void ActivityComponent::HandleMessageBoxResponse(Entity* player, const std::stri
|
||||
}
|
||||
|
||||
void ActivityComponent::PlayerJoin(Entity* player) {
|
||||
if (PlayerIsInQueue(player)) return;
|
||||
// If we have a lobby, queue the player and allow others to join, otherwise spin up an instance on the spot
|
||||
if (HasLobby()) {
|
||||
PlayerJoinLobby(player);
|
||||
@@ -531,7 +532,7 @@ void ActivityInstance::RewardParticipant(Entity* participant) {
|
||||
|
||||
// First, get the activity data
|
||||
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()) {
|
||||
uint32_t minCoins = 0;
|
||||
|
||||
@@ -95,10 +95,16 @@ void BuffComponent::Update(float deltaTime) {
|
||||
|
||||
if (buff.second.time <= 0.0f) {
|
||||
RemoveBuff(buff.first);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_BuffsToRemove.empty()) return;
|
||||
|
||||
for (const auto& buff : m_BuffsToRemove) {
|
||||
m_Buffs.erase(buff);
|
||||
}
|
||||
|
||||
m_BuffsToRemove.clear();
|
||||
}
|
||||
|
||||
const std::string& GetFxName(const std::string& buffname) {
|
||||
@@ -216,7 +222,7 @@ void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity
|
||||
|
||||
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
||||
|
||||
m_Buffs.erase(iter);
|
||||
m_BuffsToRemove.push_back(id);
|
||||
|
||||
RemoveBuffEffect(id);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,9 @@ private:
|
||||
*/
|
||||
std::map<int32_t, Buff> m_Buffs;
|
||||
|
||||
// Buffs to remove at the end of the update frame.
|
||||
std::vector<int32_t> m_BuffsToRemove;
|
||||
|
||||
/**
|
||||
* Parameters (=effects) for each buff
|
||||
*/
|
||||
|
||||
@@ -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...
|
||||
vehicle->AddCallbackTimer(2.0f, [=]() {
|
||||
vehicle->AddCallbackTimer(2.0f, [=, this]() {
|
||||
if (!vehicle || !this->m_Parent) return;
|
||||
GameMessages::SendRacingResetPlayerToLastReset(
|
||||
m_Parent->GetObjectID(), racingPlayer.playerID,
|
||||
|
||||
@@ -249,7 +249,7 @@ bool Item::IsEquipped() const {
|
||||
bool Item::Consume() {
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
@@ -294,21 +294,20 @@ void VanityUtilities::ParseXML(const std::string& file) {
|
||||
auto* partyPhrases = npcs->FirstChildElement("partyphrases");
|
||||
|
||||
if (partyPhrases == nullptr) {
|
||||
LOG("Failed to parse party phrases");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
|
||||
if (text == nullptr) {
|
||||
LOG("Failed to parse party phrase");
|
||||
continue;
|
||||
LOG("No party phrases found");
|
||||
} else {
|
||||
for (auto* phrase = partyPhrases->FirstChildElement("phrase"); phrase != nullptr;
|
||||
phrase = phrase->NextSiblingElement("phrase")) {
|
||||
// Get the phrase
|
||||
auto* text = phrase->GetText();
|
||||
|
||||
if (text == nullptr) {
|
||||
LOG("Failed to parse party phrase");
|
||||
continue;
|
||||
}
|
||||
|
||||
m_PartyPhrases.push_back(text);
|
||||
}
|
||||
|
||||
m_PartyPhrases.push_back(text);
|
||||
}
|
||||
|
||||
for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) {
|
||||
@@ -525,12 +524,12 @@ std::string VanityUtilities::ParseMarkdown(const std::string& file) {
|
||||
#endif
|
||||
// Replace "__TIMESTAMP__" with the __TIMESTAMP__
|
||||
GeneralUtils::ReplaceInString(line, "__TIMESTAMP__", __TIMESTAMP__);
|
||||
// Replace "__VERSION__" wit'h the PROJECT_VERSION
|
||||
GeneralUtils::ReplaceInString(line, "__VERSION__", STRINGIFY(PROJECT_VERSION));
|
||||
// Replace "__VERSION__" with the PROJECT_VERSION
|
||||
GeneralUtils::ReplaceInString(line, "__VERSION__", Game::projectVersion);
|
||||
// Replace "__SOURCE__" with SOURCE
|
||||
GeneralUtils::ReplaceInString(line, "__SOURCE__", Game::config->GetValue("source"));
|
||||
// Replace "__LICENSE__" with LICENSE
|
||||
GeneralUtils::ReplaceInString(line, "__LICENSE__", STRINGIFY(LICENSE));
|
||||
GeneralUtils::ReplaceInString(line, "__LICENSE__", "AGPL-3.0");
|
||||
|
||||
if (line.find("##") != std::string::npos) {
|
||||
// Add "<font size='18' color='#000000'>" before the header
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
set(DMASTERSERVER_SOURCES
|
||||
"InstanceManager.cpp"
|
||||
"ObjectIDManager.cpp"
|
||||
"Start.cpp"
|
||||
)
|
||||
|
||||
add_library(dMasterServer ${DMASTERSERVER_SOURCES})
|
||||
add_executable(MasterServer "MasterServer.cpp")
|
||||
add_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||
|
||||
target_link_libraries(dMasterServer ${COMMON_LIBRARIES})
|
||||
target_link_libraries(MasterServer ${COMMON_LIBRARIES} dMasterServer)
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
#include "CDZoneTableTable.h"
|
||||
#include "MasterPackets.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
|
||||
#include "Start.h"
|
||||
|
||||
InstanceManager::InstanceManager(Logger* logger, const std::string& externalIP) {
|
||||
mLogger = logger;
|
||||
mExternalIP = externalIP;
|
||||
@@ -57,33 +58,7 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW
|
||||
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers);
|
||||
|
||||
//Start the actual process:
|
||||
#ifdef _WIN32
|
||||
std::string cmd = "start " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
||||
#else
|
||||
std::string cmd;
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
|
||||
cmd = "sudo " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
} else {
|
||||
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd.append(std::to_string(mapID));
|
||||
cmd.append(" -port ");
|
||||
cmd.append(std::to_string(port));
|
||||
cmd.append(" -instance ");
|
||||
cmd.append(std::to_string(m_LastInstanceID));
|
||||
cmd.append(" -maxclients ");
|
||||
cmd.append(std::to_string(maxPlayers));
|
||||
|
||||
cmd.append(" -clone ");
|
||||
cmd.append(std::to_string(cloneID));
|
||||
|
||||
#ifndef _WIN32
|
||||
cmd.append("&"); //Sends our next process to the background on Linux
|
||||
#endif
|
||||
|
||||
auto ret = system(cmd.c_str());
|
||||
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
||||
|
||||
m_Instances.push_back(instance);
|
||||
|
||||
@@ -159,7 +134,7 @@ void InstanceManager::RemoveInstance(Instance* instance) {
|
||||
if (m_Instances[i] == instance) {
|
||||
instance->SetShutdownComplete(true);
|
||||
|
||||
if (!Game::shouldShutdown) RedirectPendingRequests(instance);
|
||||
if (!Game::ShouldShutdown()) RedirectPendingRequests(instance);
|
||||
|
||||
delete m_Instances[i];
|
||||
|
||||
@@ -318,28 +293,7 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon
|
||||
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password);
|
||||
|
||||
//Start the actual process:
|
||||
std::string cmd = "start " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
|
||||
#ifndef _WIN32
|
||||
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
#endif
|
||||
|
||||
cmd.append(std::to_string(mapID));
|
||||
cmd.append(" -port ");
|
||||
cmd.append(std::to_string(port));
|
||||
cmd.append(" -instance ");
|
||||
cmd.append(std::to_string(m_LastInstanceID));
|
||||
cmd.append(" -maxclients ");
|
||||
cmd.append(std::to_string(maxPlayers));
|
||||
|
||||
cmd.append(" -clone ");
|
||||
cmd.append(std::to_string(cloneID));
|
||||
|
||||
#ifndef WIN32
|
||||
cmd.append("&"); //Sends our next process to the background on Linux
|
||||
#endif
|
||||
|
||||
auto ret = system(cmd.c_str());
|
||||
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
||||
|
||||
m_Instances.push_back(instance);
|
||||
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <bcrypt/BCrypt.hpp>
|
||||
#else
|
||||
#include <bcrypt.h>
|
||||
#endif
|
||||
|
||||
#include <csignal>
|
||||
|
||||
@@ -43,6 +39,7 @@
|
||||
#include "PacketUtils.h"
|
||||
#include "FdbToSqlite.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "Start.h"
|
||||
|
||||
namespace Game {
|
||||
Logger* logger = nullptr;
|
||||
@@ -50,16 +47,15 @@ namespace Game {
|
||||
InstanceManager* im = nullptr;
|
||||
dConfig* config = nullptr;
|
||||
AssetManager* assetManager = nullptr;
|
||||
bool shouldShutdown = false;
|
||||
Game::signal_t lastSignal = 0;
|
||||
bool universeShutdownRequested = false;
|
||||
std::mt19937 randomEngine;
|
||||
} //namespace Game
|
||||
|
||||
bool shutdownSequenceStarted = false;
|
||||
void ShutdownSequence(int32_t signal = -1);
|
||||
int ShutdownSequence(int32_t signal = -1);
|
||||
int32_t FinalizeShutdown(int32_t signal = -1);
|
||||
Logger* SetupLogger();
|
||||
void StartAuthServer();
|
||||
void StartChatServer();
|
||||
void HandlePacket(Packet* packet);
|
||||
std::map<uint32_t, std::string> activeSessions;
|
||||
SystemAddress authServerMasterPeerSysAddr;
|
||||
@@ -78,39 +74,39 @@ int main(int argc, char** argv) {
|
||||
|
||||
//Triggers the shutdown sequence at application exit
|
||||
std::atexit([]() { ShutdownSequence(); });
|
||||
signal(SIGINT, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
|
||||
signal(SIGTERM, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
|
||||
std::signal(SIGINT, Game::OnSignal);
|
||||
std::signal(SIGTERM, Game::OnSignal);
|
||||
|
||||
//Create all the objects we need to run our service:
|
||||
Game::logger = SetupLogger();
|
||||
if (!Game::logger) return EXIT_FAILURE;
|
||||
|
||||
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "authconfig.ini")) {
|
||||
if (!dConfig::Exists("authconfig.ini")) {
|
||||
LOG("Couldnt find authconfig.ini");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "chatconfig.ini")) {
|
||||
if (!dConfig::Exists("chatconfig.ini")) {
|
||||
LOG("Couldnt find chatconfig.ini");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "masterconfig.ini")) {
|
||||
if (!dConfig::Exists("masterconfig.ini")) {
|
||||
LOG("Couldnt find masterconfig.ini");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini")) {
|
||||
if (!dConfig::Exists("sharedconfig.ini")) {
|
||||
LOG("Couldnt find sharedconfig.ini");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "worldconfig.ini")) {
|
||||
if (!dConfig::Exists("worldconfig.ini")) {
|
||||
LOG("Couldnt find worldconfig.ini");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "masterconfig.ini").string());
|
||||
Game::config = new dConfig("masterconfig.ini");
|
||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||
|
||||
@@ -126,7 +122,7 @@ int main(int argc, char** argv) {
|
||||
LOG("Using net version %s", Game::config->GetValue("client_net_version").c_str());
|
||||
|
||||
LOG("Starting Master server...");
|
||||
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||
LOG("Version: %s", PROJECT_VERSION);
|
||||
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||
|
||||
//Connect to the MySQL Database
|
||||
@@ -291,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("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"
|
||||
|
||||
@@ -326,7 +322,8 @@ int main(int argc, char** argv) {
|
||||
uint32_t framesSinceLastSQLPing = 0;
|
||||
uint32_t framesSinceKillUniverseCommand = 0;
|
||||
|
||||
while (true) {
|
||||
Game::logger->Flush();
|
||||
while (!Game::ShouldShutdown()) {
|
||||
//In world we'd update our other systems here.
|
||||
|
||||
//Check for packets here:
|
||||
@@ -360,10 +357,10 @@ int main(int argc, char** argv) {
|
||||
framesSinceLastSQLPing++;
|
||||
|
||||
//10m shutdown for universe kill command
|
||||
if (Game::shouldShutdown) {
|
||||
if (Game::universeShutdownRequested) {
|
||||
if (framesSinceKillUniverseCommand >= shutdownUniverseTime) {
|
||||
//Break main loop and exit
|
||||
break;
|
||||
Game::lastSignal = -1;
|
||||
} else
|
||||
framesSinceKillUniverseCommand++;
|
||||
}
|
||||
@@ -407,7 +404,7 @@ int main(int argc, char** argv) {
|
||||
t += std::chrono::milliseconds(masterFrameDelta);
|
||||
std::this_thread::sleep_until(t);
|
||||
}
|
||||
return FinalizeShutdown(EXIT_SUCCESS);
|
||||
return ShutdownSequence(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
Logger* SetupLogger() {
|
||||
@@ -804,7 +801,7 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
case eMasterMessageType::SHUTDOWN_UNIVERSE: {
|
||||
LOG("Received shutdown universe command, shutting down in 10 minutes.");
|
||||
Game::shouldShutdown = true;
|
||||
Game::universeShutdownRequested = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -814,46 +811,12 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void StartChatServer() {
|
||||
if (Game::shouldShutdown) {
|
||||
LOG("Currently shutting down. Chat will not be restarted.");
|
||||
return;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
//macOS doesn't need sudo to run on ports < 1024
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = 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());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartAuthServer() {
|
||||
if (Game::shouldShutdown) {
|
||||
LOG("Currently shutting down. Auth will not be restarted.");
|
||||
return;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = 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());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShutdownSequence(int32_t signal) {
|
||||
int ShutdownSequence(int32_t signal) {
|
||||
if (!Game::logger) return -1;
|
||||
LOG("Recieved Signal %d", signal);
|
||||
if (shutdownSequenceStarted) {
|
||||
return;
|
||||
LOG("Duplicate Shutdown Sequence");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Game::im) {
|
||||
@@ -862,7 +825,7 @@ void ShutdownSequence(int32_t signal) {
|
||||
|
||||
Game::im->SetIsShuttingDown(true);
|
||||
shutdownSequenceStarted = true;
|
||||
Game::shouldShutdown = true;
|
||||
Game::lastSignal = -1;
|
||||
|
||||
{
|
||||
CBITSTREAM;
|
||||
@@ -931,16 +894,20 @@ void ShutdownSequence(int32_t signal) {
|
||||
}
|
||||
}
|
||||
|
||||
FinalizeShutdown(signal);
|
||||
return FinalizeShutdown(signal);
|
||||
}
|
||||
|
||||
int32_t FinalizeShutdown(int32_t signal) {
|
||||
//Delete our objects here:
|
||||
Database::Destroy("MasterServer");
|
||||
if (Game::config) delete Game::config;
|
||||
Game::config = nullptr;
|
||||
if (Game::im) delete Game::im;
|
||||
Game::im = nullptr;
|
||||
if (Game::server) delete Game::server;
|
||||
Game::server = nullptr;
|
||||
if (Game::logger) delete Game::logger;
|
||||
Game::logger = nullptr;
|
||||
|
||||
if (signal != EXIT_SUCCESS) exit(signal);
|
||||
return signal;
|
||||
|
||||
71
dMasterServer/Start.cpp
Normal file
71
dMasterServer/Start.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "Start.h"
|
||||
#include "Logger.h"
|
||||
#include "dConfig.h"
|
||||
#include "Game.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
|
||||
void StartChatServer() {
|
||||
if (Game::ShouldShutdown()) {
|
||||
LOG("Currently shutting down. Chat will not be restarted.");
|
||||
return;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
//macOS doesn't need sudo to run on ports < 1024
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = 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());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartAuthServer() {
|
||||
if (Game::ShouldShutdown()) {
|
||||
LOG("Currently shutting down. Auth will not be restarted.");
|
||||
return;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = 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());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
|
||||
#ifdef _WIN32
|
||||
std::string cmd = "start " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
||||
#else
|
||||
std::string cmd;
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
|
||||
cmd = "sudo " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
} else {
|
||||
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd.append(std::to_string(mapID));
|
||||
cmd.append(" -port ");
|
||||
cmd.append(std::to_string(port));
|
||||
cmd.append(" -instance ");
|
||||
cmd.append(std::to_string(lastInstanceID));
|
||||
cmd.append(" -maxclients ");
|
||||
cmd.append(std::to_string(maxPlayers));
|
||||
cmd.append(" -clone ");
|
||||
cmd.append(std::to_string(cloneID));
|
||||
|
||||
#ifndef _WIN32
|
||||
cmd.append("&"); //Sends our next process to the background on Linux
|
||||
#endif
|
||||
|
||||
auto ret = system(cmd.c_str());
|
||||
}
|
||||
6
dMasterServer/Start.h
Normal file
6
dMasterServer/Start.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "dCommonVars.h"
|
||||
|
||||
void StartAuthServer();
|
||||
void StartChatServer();
|
||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
|
||||
@@ -11,11 +11,7 @@
|
||||
#include "SHA512.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <bcrypt/BCrypt.hpp>
|
||||
#else
|
||||
#include <bcrypt.h>
|
||||
#endif
|
||||
|
||||
#include <BitStream.h>
|
||||
#include <future>
|
||||
@@ -59,7 +55,9 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
}
|
||||
} 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;
|
||||
mPort = port;
|
||||
mZoneID = zoneID;
|
||||
@@ -55,7 +55,7 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
|
||||
mReplicaManager = nullptr;
|
||||
mServerType = serverType;
|
||||
mConfig = config;
|
||||
mShouldShutdown = shouldShutdown;
|
||||
mShouldShutdown = lastSignal;
|
||||
//Attempt to start our server here:
|
||||
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:
|
||||
if (serverType != ServerType::Master) {
|
||||
SetupForMasterConnection();
|
||||
ConnectToMaster();
|
||||
if (!ConnectToMaster()) {
|
||||
LOG("Failed ConnectToMaster!");
|
||||
}
|
||||
}
|
||||
|
||||
//Set up Replica if we're a world server:
|
||||
@@ -129,7 +131,7 @@ Packet* dServer::ReceiveFromMaster() {
|
||||
break;
|
||||
}
|
||||
case eMasterMessageType::SHUTDOWN:
|
||||
*mShouldShutdown = true;
|
||||
*mShouldShutdown = -2;
|
||||
break;
|
||||
|
||||
//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() {
|
||||
mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
|
||||
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() {
|
||||
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <csignal>
|
||||
#include "RakPeerInterface.h"
|
||||
#include "ReplicaManager.h"
|
||||
#include "NetworkIDManager.h"
|
||||
@@ -15,6 +16,10 @@ enum class ServerType : uint32_t {
|
||||
World
|
||||
};
|
||||
|
||||
namespace Game {
|
||||
using signal_t = volatile std::sig_atomic_t;
|
||||
}
|
||||
|
||||
class dServer {
|
||||
public:
|
||||
// Default constructor should only used for testing!
|
||||
@@ -31,7 +36,7 @@ public:
|
||||
int masterPort,
|
||||
ServerType serverType,
|
||||
dConfig* config,
|
||||
bool* shouldShutdown,
|
||||
Game::signal_t* shouldShutdown,
|
||||
unsigned int zoneID = 0);
|
||||
~dServer();
|
||||
|
||||
@@ -81,9 +86,9 @@ private:
|
||||
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;
|
||||
std::string mIP;
|
||||
int mPort;
|
||||
|
||||
@@ -5,6 +5,7 @@ set(DWORLDSERVER_SOURCES
|
||||
|
||||
add_library(dWorldServer ${DWORLDSERVER_SOURCES})
|
||||
add_executable(WorldServer "WorldServer.cpp")
|
||||
add_compile_definitions(WorldServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||
|
||||
target_link_libraries(dWorldServer ${COMMON_LIBRARIES})
|
||||
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics Detour Recast tinyxml2 dWorldServer dNavigation)
|
||||
|
||||
@@ -88,9 +88,10 @@ namespace Game {
|
||||
RakPeerInterface* chatServer = nullptr;
|
||||
std::mt19937 randomEngine;
|
||||
SystemAddress chatSysAddr;
|
||||
bool shouldShutdown = false;
|
||||
Game::signal_t lastSignal = 0;
|
||||
EntityManager* entityManager = nullptr;
|
||||
dZoneManager* zoneManager = nullptr;
|
||||
std::string projectVersion = PROJECT_VERSION;
|
||||
} // namespace Game
|
||||
|
||||
bool chatDisabled = false;
|
||||
@@ -123,8 +124,8 @@ int main(int argc, char** argv) {
|
||||
// Triggers the shutdown sequence at application exit
|
||||
std::atexit(WorldShutdownSequence);
|
||||
|
||||
signal(SIGINT, [](int) { WorldShutdownSequence(); });
|
||||
signal(SIGTERM, [](int) { WorldShutdownSequence(); });
|
||||
std::signal(SIGINT, Game::OnSignal);
|
||||
std::signal(SIGTERM, Game::OnSignal);
|
||||
|
||||
uint32_t zoneID = 1000;
|
||||
uint32_t cloneID = 0;
|
||||
@@ -147,12 +148,12 @@ int main(int argc, char** argv) {
|
||||
if (!Game::logger) return EXIT_FAILURE;
|
||||
|
||||
//Read our config:
|
||||
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "worldconfig.ini").string());
|
||||
Game::config = new dConfig("worldconfig.ini");
|
||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||
|
||||
LOG("Starting World server...");
|
||||
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||
LOG("Version: %s", Game::projectVersion.c_str());
|
||||
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||
|
||||
if (Game::config->GetValue("disable_chat") == "1") chatDisabled = true;
|
||||
@@ -211,7 +212,7 @@ int main(int argc, char** argv) {
|
||||
UserManager::Instance()->Initialize();
|
||||
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:
|
||||
uint32_t chatPort = 1501;
|
||||
@@ -312,6 +313,8 @@ int main(int argc, char** argv) {
|
||||
uint32_t saveTime = 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.
|
||||
|
||||
Game::logger->Flush(); // once immediately before the main loop
|
||||
while (true) {
|
||||
Metrics::StartMeasurement(MetricVariable::Frame);
|
||||
Metrics::StartMeasurement(MetricVariable::GameLoop);
|
||||
@@ -362,9 +365,9 @@ int main(int argc, char** argv) {
|
||||
if (!Game::server->GetIsConnectedToMaster()) {
|
||||
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);
|
||||
Game::shouldShutdown = true;
|
||||
Game::lastSignal = -1;
|
||||
}
|
||||
} else framesSinceMasterDisconnect = 0;
|
||||
|
||||
@@ -459,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 (framesSinceLastUser >= emptyShutdownTime) {
|
||||
Game::shouldShutdown = true;
|
||||
Game::lastSignal = -1;
|
||||
}
|
||||
} else {
|
||||
framesSinceLastUser = 0;
|
||||
@@ -512,7 +515,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Game::shouldShutdown && !worldShutdownSequenceComplete) {
|
||||
if (Game::ShouldShutdown() && !worldShutdownSequenceComplete) {
|
||||
WorldShutdownProcess(zoneID);
|
||||
break;
|
||||
}
|
||||
@@ -821,7 +824,7 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
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());
|
||||
break;
|
||||
}
|
||||
@@ -1288,14 +1291,17 @@ void WorldShutdownProcess(uint32_t zoneId) {
|
||||
}
|
||||
|
||||
void WorldShutdownSequence() {
|
||||
Game::shouldShutdown = true;
|
||||
bool shouldShutdown = Game::ShouldShutdown() || worldShutdownSequenceComplete;
|
||||
Game::lastSignal = -1;
|
||||
#ifndef DARKFLAME_PLATFORM_WIN32
|
||||
if (Game::shouldShutdown || worldShutdownSequenceComplete)
|
||||
if (shouldShutdown)
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Game::logger) return;
|
||||
|
||||
LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID);
|
||||
WorldShutdownProcess(Game::server->GetZoneID());
|
||||
FinalizeShutdown();
|
||||
|
||||
@@ -51,20 +51,20 @@ Spawner::Spawner(const SpawnerInfo info) {
|
||||
std::vector<Spawner*> spawnSmashSpawnersN = Game::zoneManager->GetSpawnersByName(m_Info.spawnOnSmashGroupName);
|
||||
for (Entity* ssEntity : spawnSmashEntities) {
|
||||
m_SpawnSmashFoundGroup = true;
|
||||
ssEntity->AddDieCallback([=]() {
|
||||
ssEntity->AddDieCallback([=, this]() {
|
||||
Spawn();
|
||||
});
|
||||
}
|
||||
for (Spawner* ssSpawner : spawnSmashSpawners) {
|
||||
m_SpawnSmashFoundGroup = true;
|
||||
ssSpawner->AddSpawnedEntityDieCallback([=]() {
|
||||
ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
|
||||
Spawn();
|
||||
});
|
||||
}
|
||||
for (Spawner* ssSpawner : spawnSmashSpawnersN) {
|
||||
m_SpawnSmashFoundGroup = true;
|
||||
m_SpawnOnSmash = ssSpawner;
|
||||
ssSpawner->AddSpawnedEntityDieCallback([=]() {
|
||||
ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
|
||||
Spawn();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ ARG BUILD_THREADS=1
|
||||
ARG BUILD_VERSION=171022
|
||||
|
||||
RUN echo "Build server"
|
||||
RUN sed -i -e "s/__maria_db_connector_compile_jobs__=.*/__maria_db_connector_compile_jobs__=${BUILD_THREADS}/g" CMakeVariables.txt
|
||||
RUN sed -i -e "s/MARIADB_CONNECTOR_COMPILE_JOBS=.*/MARIADB_CONNECTOR_COMPILE_JOBS=${BUILD_THREADS}/g" CMakeVariables.txt
|
||||
RUN mkdir -p cmake_build
|
||||
RUN cd cmake_build && \
|
||||
cmake .. -DCMAKE_BUILD_RPATH_USE_ORIGIN=TRUE && \
|
||||
|
||||
@@ -26,7 +26,7 @@ TEST_F(EncodingTest, TestEncodingHello) {
|
||||
};
|
||||
|
||||
TEST_F(EncodingTest, TestEncodingUmlaut) {
|
||||
originalWord = u8"Frühling";
|
||||
originalWord = reinterpret_cast<const char*>(u8"Frühling");
|
||||
originalWordSv = originalWord;
|
||||
|
||||
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'F');
|
||||
|
||||
@@ -11,4 +11,5 @@ namespace Game {
|
||||
AssetManager* assetManager = nullptr;
|
||||
SystemAddress chatSysAddr;
|
||||
EntityManager* entityManager = nullptr;
|
||||
std::string projectVersion;
|
||||
}
|
||||
|
||||
10
thirdparty/CMakeLists.txt
vendored
10
thirdparty/CMakeLists.txt
vendored
@@ -11,11 +11,17 @@ file(
|
||||
GLOB SOURCES_LIBBCRYPT
|
||||
LIST_DIRECTORIES false
|
||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c
|
||||
)
|
||||
|
||||
add_library(bcrypt ${SOURCES_LIBBCRYPT})
|
||||
|
||||
# Because we are not using the libbcrypt CMakeLists.txt, we need to include these headers for the library to use.
|
||||
# fortunately they are only needed for building the libbcrypt directory and nothing else, so these are marked private.
|
||||
|
||||
target_include_directories(bcrypt PRIVATE "libbcrypt/include")
|
||||
target_include_directories(bcrypt PRIVATE "libbcrypt/src")
|
||||
|
||||
# Source code for sqlite
|
||||
add_subdirectory(SQLite)
|
||||
|
||||
@@ -31,7 +37,7 @@ add_subdirectory(raknet)
|
||||
# Download Backtrace if configured
|
||||
if(UNIX AND NOT APPLE)
|
||||
include(FetchContent)
|
||||
if (__include_backtrace__ AND __compile_backtrace__)
|
||||
if (${INCLUDE_BACKTRACE} AND ${COMPILE_BACKTRACE})
|
||||
FetchContent_Declare(
|
||||
backtrace
|
||||
GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
|
||||
|
||||
2
thirdparty/CMakeMariaDBLists.txt
vendored
2
thirdparty/CMakeMariaDBLists.txt
vendored
@@ -93,7 +93,7 @@ else() # Build from source
|
||||
-DINSTALL_PLUGINDIR=plugin
|
||||
${MARIADB_EXTRA_CMAKE_ARGS}
|
||||
PREFIX "${PROJECT_BINARY_DIR}/mariadbcpp"
|
||||
BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${__maria_db_connector_compile_jobs__}
|
||||
BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${MARIADB_CONNECTOR_COMPILE_JOBS}
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
ExternalProject_Get_Property(mariadb_connector_cpp BINARY_DIR)
|
||||
|
||||
2
thirdparty/mariadb-connector-cpp
vendored
2
thirdparty/mariadb-connector-cpp
vendored
Submodule thirdparty/mariadb-connector-cpp updated: 3fbdf8fa33...8641b1453a
2
thirdparty/raknet/CMakeLists.txt
vendored
2
thirdparty/raknet/CMakeLists.txt
vendored
@@ -80,6 +80,8 @@ target_compile_options(raknet PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
/w>)
|
||||
|
||||
set_property(TARGET raknet PROPERTY CXX_STANDARD 17)
|
||||
|
||||
if(WIN32)
|
||||
# Link Win Sockets 2 to RakNet
|
||||
target_link_libraries(raknet ws2_32)
|
||||
|
||||
Reference in New Issue
Block a user