Compare commits

..

2 Commits

Author SHA1 Message Date
05466f924d this work. but engi turret is weird 2023-12-29 01:07:58 -06:00
e5bea0a5ef Consilidating 2023-12-28 23:19:28 -06:00
55 changed files with 409 additions and 710 deletions

1
.gitignore vendored
View File

@@ -122,4 +122,3 @@ docker/__pycache__
docker-compose.override.yml
!*Test.bin
!cmake/*

View File

@@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 3.18)
project(Darkflame)
include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set (CMAKE_CXX_STANDARD 17)
# Read variables from file
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
@@ -15,26 +14,30 @@ 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)
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}")
@@ -50,22 +53,19 @@ 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)
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")
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")
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,61 +98,47 @@ 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")
include(Utils)
foreach(resource_file ${RESOURCE_FILES})
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})
@@ -160,23 +146,24 @@ 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()
@@ -184,18 +171,26 @@ 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)
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
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()
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)
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
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()
endforeach()
# Create our list of include directories
@@ -203,9 +198,7 @@ set(INCLUDED_DIRECTORIES
"dCommon"
"dCommon/dClient"
"dCommon/dEnums"
"dChatFilter"
"dGame"
"dGame/dBehaviors"
"dGame/dComponents"
@@ -216,14 +209,10 @@ set(INCLUDED_DIRECTORIES
"dGame/dPropertyBehaviors"
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
"dGame/dUtilities"
"dPhysics"
"dNavigation"
"dNavigation/dTerrain"
"dZoneManager"
"dDatabase"
"dDatabase/CDClientDatabase"
"dDatabase/CDClientDatabase/CDClientTables"
@@ -231,9 +220,7 @@ set(INCLUDED_DIRECTORIES
"dDatabase/GameDatabase/ITables"
"dDatabase/GameDatabase/MySQL"
"dDatabase/GameDatabase/MySQL/Tables"
"dNet"
"dScripts"
"dScripts/02_server"
"dScripts/ai"
@@ -317,23 +304,27 @@ 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()
# Actually include the directories from our list
foreach(dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
if(NOT WIN32)
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt")
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()
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include")
# Add binary directory as an include directory
include_directories(${PROJECT_BINARY_DIR})
# Actually include the directories from our list
foreach (dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
# Add linking directories:
link_directories(${PROJECT_BINARY_DIR})
@@ -387,10 +378,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()
@@ -428,6 +419,6 @@ target_precompile_headers(
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
)
if(${ENABLE_TESTING})
if (${__enable_testing__} MATCHES "1")
add_subdirectory(tests)
endif()

View File

@@ -1,32 +1,22 @@
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.
# 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 __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 to the number of jobs (make -j equivalent) to compile the mariadbconn files with.
MARIADB_CONNECTOR_COMPILE_JOBS=1
__maria_db_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/
# 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
# Uncomment the below line to cache the entire CDClient into memory
# CDCLIENT_CACHE_ALL=1

View File

@@ -1,47 +0,0 @@
# 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()

View File

@@ -1,7 +1,6 @@
#include <iostream>
#include <string>
#include <ctime>
#include <csignal>
#include <chrono>
#include <thread>
@@ -29,7 +28,7 @@ namespace Game {
Logger* logger = nullptr;
dServer* server = nullptr;
dConfig* config = nullptr;
Game::signal_t lastSignal = 0;
bool shouldShutdown = false;
std::mt19937 randomEngine;
}
@@ -43,20 +42,17 @@ 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("authconfig.ini");
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "authconfig.ini").string());
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
LOG("Starting Auth server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
@@ -78,7 +74,6 @@ 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));
@@ -88,7 +83,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::lastSignal);
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::shouldShutdown);
//Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now();
@@ -101,16 +96,13 @@ int main(int argc, char** argv) {
AuthPackets::LoadClaimCodes();
Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
while (!Game::shouldShutdown) {
//Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= authFramerate) {
LOG("No connection to master!");
if (framesSinceMasterDisconnect >= authFramerate)
break; //Exit our loop, shut down.
}
} else framesSinceMasterDisconnect = 0;
//In world we'd update our other systems here.
@@ -149,7 +141,6 @@ 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;

View File

@@ -1,3 +1,2 @@
add_executable(AuthServer "AuthServer.cpp")
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")

View File

@@ -6,7 +6,6 @@ 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)

View File

@@ -33,7 +33,7 @@ namespace Game {
dConfig* config = nullptr;
dChatFilter* chatFilter = nullptr;
AssetManager* assetManager = nullptr;
Game::signal_t lastSignal = 0;
bool shouldShutdown = false;
std::mt19937 randomEngine;
PlayerContainer playerContainer;
}
@@ -48,20 +48,17 @@ 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("chatconfig.ini");
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "chatconfig.ini").string());
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
LOG("Starting Chat server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
@@ -104,7 +101,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::lastSignal);
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::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
@@ -121,8 +118,7 @@ int main(int argc, char** argv) {
uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0;
Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
while (!Game::shouldShutdown) {
//Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++;

View File

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

View File

@@ -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,14 +115,7 @@ void GenerateDump() {
}
void CatchUnhandled(int sig) {
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
#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());
@@ -174,7 +167,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(),
@@ -185,7 +178,7 @@ void CatchUnhandled(int sig) {
struct bt_ctx ctx = { state, 0 };
Bt(state);
#endif // INCLUDE_BACKTRACE
#endif // __include_backtrace__
exit(EXIT_FAILURE);
}

View File

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

View File

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

View File

@@ -6,8 +6,6 @@
#include <stdarg.h>
Writer::~Writer() {
// Flush before we close
Flush();
// Dont try to close stdcout...
if (!m_Outfile || m_IsConsoleWriter) return;
@@ -16,7 +14,7 @@ Writer::~Writer() {
}
void Writer::Log(const char* time, const char* message) {
if (!m_Outfile || !m_Enabled) return;
if (!m_Outfile) return;
fputs(time, m_Outfile);
fputs(message, m_Outfile);

View File

@@ -10,23 +10,8 @@ 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::filesystem::path config_dir = GetConfigDir();
std::ifstream in(config_dir / m_ConfigFilePath);
std::ifstream in(BinaryPathFinder::GetBinaryDir() / m_ConfigFilePath);
if (!in.good()) return;
std::string line{};
@@ -34,7 +19,7 @@ void dConfig::LoadConfig() {
if (!line.empty() && line.front() != '#') ProcessLine(line);
}
std::ifstream sharedConfig(config_dir / "sharedconfig.ini", std::ios::in);
std::ifstream sharedConfig(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini", std::ios::in);
if (!sharedConfig.good()) return;
line.clear();
@@ -49,11 +34,6 @@ 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];
}

View File

@@ -7,11 +7,6 @@ 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.
*

View File

@@ -39,11 +39,9 @@
#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
#endif // CDCLIENT_CACHE_ALL
// #define CDCLIENT_CACHE_ALL
#ifdef CDCLIENT_CACHE_ALL
#define CDCLIENT_DONT_CACHE_TABLE(x) x

View File

@@ -14,7 +14,3 @@ 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()

View File

@@ -521,52 +521,7 @@ void Entity::Initialize() {
}
if (int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) {
auto* quickBuildComponent = AddComponent<QuickBuildComponent>();
CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == quickBuildComponentID); });
if (rebCompData.size() > 0) {
quickBuildComponent->SetResetTime(rebCompData[0].reset_time);
quickBuildComponent->SetCompleteTime(rebCompData[0].complete_time);
quickBuildComponent->SetTakeImagination(rebCompData[0].take_imagination);
quickBuildComponent->SetInterruptible(rebCompData[0].interruptible);
quickBuildComponent->SetSelfActivator(rebCompData[0].self_activator);
quickBuildComponent->SetActivityId(rebCompData[0].activityID);
quickBuildComponent->SetPostImaginationCost(rebCompData[0].post_imagination_cost);
quickBuildComponent->SetTimeBeforeSmash(rebCompData[0].time_before_smash);
const auto rebuildResetTime = GetVar<float>(u"rebuild_reset_time");
if (rebuildResetTime != 0.0f) {
quickBuildComponent->SetResetTime(rebuildResetTime);
// Known bug with moving platform in FV that casues it to build at the end instead of the start.
// This extends the smash time so players can ride up the lift.
if (m_TemplateID == 9483) {
quickBuildComponent->SetResetTime(quickBuildComponent->GetResetTime() + 25);
}
}
const auto activityID = GetVar<int32_t>(u"activityID");
if (activityID > 0) {
quickBuildComponent->SetActivityId(activityID);
Loot::CacheMatrix(activityID);
}
const auto timeBeforeSmash = GetVar<float>(u"tmeSmsh");
if (timeBeforeSmash > 0) {
quickBuildComponent->SetTimeBeforeSmash(timeBeforeSmash);
}
const auto compTime = GetVar<float>(u"compTime");
if (compTime > 0) {
quickBuildComponent->SetCompleteTime(compTime);
}
}
auto* quickBuildComponent = AddComponent<QuickBuildComponent>(componentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) {
@@ -2023,6 +1978,10 @@ LDFBaseData* Entity::GetVarData(const std::u16string& name) const {
return nullptr;
}
bool Entity::CheckIfVarExists(const std::u16string& name) const {
return GetVarData(name) != nullptr;
}
std::string Entity::GetVarAsString(const std::u16string& name) const {
auto* data = GetVarData(name);

View File

@@ -282,6 +282,12 @@ public:
*/
LDFBaseData* GetVarData(const std::u16string& name) const;
/**
* Returns if a var exists
*/
bool CheckIfVarExists(const std::u16string& name) const;
/**
* Get the LDF value and convert it to a string.
*/

View File

@@ -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), CAST(lowestRanking.lowestRank AS SIGNED) - 9)
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
AND
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
ORDER BY ranking ASC;

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:
ObjectIDManager::Instance()->RequestPersistentID([=, this](uint32_t objectID) {
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t objectID) {
if (Database::Get()->GetCharacterInfo(objectID)) {
LOG("Character object id unavailable, check object_id_tracker!");
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);

View File

@@ -7,7 +7,6 @@
#include "Logger.h"
#include "BehaviorBranchContext.h"
#include "BehaviorContext.h"
#include "QuickBuildComponent.h"
#include "DestroyableComponent.h"
#include "Game.h"
#include "Logger.h"

View File

@@ -6,7 +6,6 @@
#include "BehaviorContext.h"
#include "BaseCombatAIComponent.h"
#include "EntityManager.h"
#include "QuickBuildComponent.h"
#include "DestroyableComponent.h"
#include <vector>

View File

@@ -30,10 +30,16 @@
#include "LeaderboardManager.h"
ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) {
m_Parent = parent;
if (activityID == -1) return;
SetupActivity(activityID);
}
void ActivityComponent::SetupActivity(int32_t activityID){
if (activityID > 0) m_ActivityID = activityID;
else m_ActivityID = parent->GetVar<int32_t>(u"activityID");
else m_ActivityID = m_Parent->GetVar<int32_t>(u"activityID");
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([this](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
for (CDActivities activity : activities) {
m_ActivityInfo = activity;
@@ -42,7 +48,7 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo
m_ActivityInfo.minTeams = 1;
}
if (m_ActivityInfo.instanceMapID == -1) {
const auto& transferOverride = parent->GetVarAsString(u"transferZoneID");
const auto& transferOverride = m_Parent->GetVarAsString(u"transferZoneID");
if (!transferOverride.empty()) {
GeneralUtils::TryParse(transferOverride, m_ActivityInfo.instanceMapID);
}
@@ -93,7 +99,7 @@ void ActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIniti
void ActivityComponent::ReloadConfig() {
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([this](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
std::vector<CDActivities> activities = activitiesTable->Query([=](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,7 +121,6 @@ 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);
@@ -532,7 +537,7 @@ void ActivityInstance::RewardParticipant(Entity* participant) {
// First, get the activity data
auto* activityRewardsTable = CDClientManager::Instance().GetTable<CDActivityRewardsTable>();
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([this](CDActivityRewards entry) { return (entry.objectTemplate == m_ActivityInfo.ActivityID); });
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([=](CDActivityRewards entry) { return (entry.objectTemplate == m_ActivityInfo.ActivityID); });
if (!activityRewards.empty()) {
uint32_t minCoins = 0;

View File

@@ -150,7 +150,7 @@ struct ActivityPlayer {
*/
class ActivityComponent : public Component {
public:
ActivityComponent(Entity* parent, int32_t activityID);
ActivityComponent(Entity* parent, int32_t activityID = -1);
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
@@ -205,6 +205,12 @@ public:
*/
int GetActivityID() { return m_ActivityInfo.ActivityID; }
/**
* Sets the ID of this activity
*/
void SetActivityID(int32_t activityID) { m_ActivityID = activityID; }
/**
* Returns if this activity has a lobby, e.g. if it needs to instance players to some other map
* @return true if this activity has a lobby, false otherwise
@@ -280,7 +286,7 @@ public:
* Returns all the score for the players that are currently playing this activity
* @return
*/
std::vector<ActivityPlayer*> GetActivityPlayers() { return m_ActivityPlayers; };
std::vector<ActivityPlayer*> GetActivityPlayers() const { return m_ActivityPlayers; };
/**
* Returns activity data for a specific entity (e.g. score and such).
@@ -330,6 +336,13 @@ public:
* @return the LMI that this activity points to for a team size
*/
uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; }
/**
* Sets up the activity data for a gievn activity
*/
void SetupActivity(int32_t activityID);
void ClearActivityPlayerData() { m_ActivityPlayers.clear(); m_DirtyActivityInfo = true;};
private:
/**

View File

@@ -95,16 +95,10 @@ 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) {
@@ -222,7 +216,7 @@ void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
m_BuffsToRemove.push_back(id);
m_Buffs.erase(iter);
RemoveBuffEffect(id);
}

View File

@@ -140,9 +140,6 @@ 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
*/

View File

@@ -725,7 +725,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
const auto isPlayer = m_Parent->IsPlayer();
GameMessages::SendDie(m_Parent, source, source, true, killType, deathType, 0, 0, 0, isPlayer, false, 1);
GameMessages::SendDie(m_Parent, source, source, true, killType, deathType, 0, 0, 0, isPlayer, false);
//NANI?!
if (!isPlayer) {

View File

@@ -21,16 +21,46 @@
#include "Loot.h"
#include "TeamManager.h"
#include "RenderComponent.h"
#include "CDRebuildComponentTable.h"
#include "CppScripts.h"
QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) {
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
QuickBuildComponent::QuickBuildComponent(Entity* parent, uint32_t id) : ActivityComponent(parent) {
m_Parent = parent;
CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == id); });
if (rebCompData.size() > 0) {
SetResetTime(rebCompData[0].reset_time);
SetCompleteTime(rebCompData[0].complete_time);
SetTakeImagination(rebCompData[0].take_imagination);
SetActivityID(rebCompData[0].activityID);
SetInterruptible(rebCompData[0].interruptible);
SetSelfActivator(rebCompData[0].self_activator);
SetPostImaginationCost(rebCompData[0].post_imagination_cost);
SetTimeBeforeSmash(rebCompData[0].time_before_smash);
const auto compTime = m_Parent->GetVar<float>(u"compTime");
if (m_Parent->HasVar(u"compTime") && compTime > 0) SetCompleteTime(compTime);
}
std::u16string checkPreconditions = m_Parent->GetVar<std::u16string>(u"CheckPrecondition");
if (!checkPreconditions.empty()) {
m_Precondition = new PreconditionExpression(GeneralUtils::UTF16ToWTF8(checkPreconditions));
}
const auto activityID = m_Parent->GetVar<int32_t>(u"activityID");
if (activityID > 0) SetActivityID(activityID);
SetupActivity(GetActivityID());
const auto rebuildResetTime = m_Parent->GetVar<float>(u"rebuild_reset_time");
if (rebuildResetTime != 0.0f) {
SetResetTime(rebuildResetTime);
// Known bug with moving platform in FV that casues it to build at the end instead of the start.
// This extends the smash time so players can ride up the lift.
if (m_Parent->GetLOT() == 9483) SetResetTime(GetResetTime() + 25);
}
// Should a setting that has the build activator position exist, fetch that setting here and parse it for position.
// It is assumed that the user who sets this setting uses the correct character delimiter (character 31 or in hex 0x1F)
auto positionAsVector = GeneralUtils::SplitString(m_Parent->GetVarAsString(u"rebuild_activators"), 0x1F);
@@ -38,11 +68,22 @@ QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) {
GeneralUtils::TryParse(positionAsVector[0], m_ActivatorPosition.x) &&
GeneralUtils::TryParse(positionAsVector[1], m_ActivatorPosition.y) &&
GeneralUtils::TryParse(positionAsVector[2], m_ActivatorPosition.z)) {
} else if (
m_Parent->CheckIfVarExists(u"position.x") &&
m_Parent->CheckIfVarExists(u"position.y") &&
m_Parent->CheckIfVarExists(u"position.z")) {
m_ActivatorPosition.x = m_Parent->GetVar<float>(u"position.x");
m_ActivatorPosition.y = m_Parent->GetVar<float>(u"position.y");
m_ActivatorPosition.x = m_Parent->GetVar<float>(u"position.z");
} else {
LOG("Failed to find activator position for lot %i. Defaulting to parents position.", m_Parent->GetLOT());
m_ActivatorPosition = m_Parent->GetPosition();
}
const auto timeBeforeSmash = m_Parent->GetVar<float>(u"tmeSmsh");
if (timeBeforeSmash > 0) SetTimeBeforeSmash(timeBeforeSmash);
m_IsChoiceBuild = m_Parent->GetBoolean(u"is_ChoiceBuild");
SpawnActivator();
}
@@ -58,71 +99,25 @@ QuickBuildComponent::~QuickBuildComponent() {
}
void QuickBuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
if (m_Parent->GetComponent(eReplicaComponentType::DESTROYABLE) == nullptr) {
ActivityComponent::Serialize(outBitStream, bIsInitialUpdate);
outBitStream->Write(m_StateDirty);
if (m_StateDirty) {
outBitStream->Write(m_State);
outBitStream->Write(m_ShowResetEffect);
outBitStream->Write(m_Activator != nullptr);
outBitStream->Write(m_Timer);
outBitStream->Write(m_TimerIncomplete);
if (bIsInitialUpdate) {
outBitStream->Write(false);
outBitStream->Write(m_IsChoiceBuild);
if (m_IsChoiceBuild) outBitStream->Write(m_ResetTime);
outBitStream->Write(m_ActivatorPosition);
outBitStream->Write(m_RepositionPlayer);
}
outBitStream->Write(false);
outBitStream->Write(false);
if (!bIsInitialUpdate) m_StateDirty = false;
}
// If build state is completed and we've already serialized once in the completed state,
// don't serializing this component anymore as this will cause the build to jump again.
// If state changes, serialization will begin again.
if (!m_StateDirty && m_State == eQuickBuildState::COMPLETED) {
outBitStream->Write0();
outBitStream->Write0();
return;
}
// BEGIN Scripted Activity
outBitStream->Write1();
Entity* builder = GetBuilder();
if (builder) {
outBitStream->Write<uint32_t>(1);
outBitStream->Write(builder->GetObjectID());
for (int i = 0; i < 10; i++) {
outBitStream->Write(0.0f);
}
} else {
outBitStream->Write<uint32_t>(0);
}
// END Scripted Activity
outBitStream->Write1();
outBitStream->Write(m_State);
outBitStream->Write(m_ShowResetEffect);
outBitStream->Write(m_Activator != nullptr);
outBitStream->Write(m_Timer);
outBitStream->Write(m_TimerIncomplete);
if (bIsInitialUpdate) {
outBitStream->Write(false);
outBitStream->Write(m_ActivatorPosition);
outBitStream->Write(m_RepositionPlayer);
}
m_StateDirty = false;
}
void QuickBuildComponent::Update(float deltaTime) {
m_Activator = GetActivator();
// Serialize the quickbuild every so often, fixes the odd bug where the quickbuild is not buildable
/*if (m_SoftTimer > 0.0f) {
m_SoftTimer -= deltaTime;
}
else {
m_SoftTimer = 5.0f;
Game::entityManager->SerializeEntity(m_Parent);
}*/
switch (m_State) {
case eQuickBuildState::OPEN: {
SpawnActivator();
@@ -138,15 +133,13 @@ void QuickBuildComponent::Update(float deltaTime) {
if (m_TimeBeforeSmash > 0) {
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
m_ShowResetEffect = true;
m_StateDirty = true;
Game::entityManager->SerializeEntity(m_Parent);
}
if (m_TimerIncomplete >= m_TimeBeforeSmash) {
m_Builder = LWOOBJID_EMPTY;
GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
ClearActivityPlayerData();
GameMessages::SendDie(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
ResetQuickBuild(false);
}
}
@@ -162,14 +155,14 @@ void QuickBuildComponent::Update(float deltaTime) {
if (m_Timer >= m_ResetTime - 4.0f) {
if (!m_ShowResetEffect) {
m_ShowResetEffect = true;
m_StateDirty = true;
Game::entityManager->SerializeEntity(m_Parent);
}
}
if (m_Timer >= m_ResetTime) {
GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
GameMessages::SendDie(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
ResetQuickBuild(false);
}
@@ -182,7 +175,6 @@ void QuickBuildComponent::Update(float deltaTime) {
if (!builder) {
ResetQuickBuild(false);
return;
}
@@ -190,7 +182,7 @@ void QuickBuildComponent::Update(float deltaTime) {
m_Timer += deltaTime;
m_TimerIncomplete = 0;
m_ShowResetEffect = false;
m_StateDirty = true;
if (m_TimeBeforeDrain <= 0.0f) {
m_TimeBeforeDrain = m_CompleteTime / static_cast<float>(m_TakeImagination);
@@ -209,6 +201,7 @@ void QuickBuildComponent::Update(float deltaTime) {
break;
}
}
Game::entityManager->SerializeEntity(builder);
if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) {
CompleteQuickBuild(builder);
@@ -223,15 +216,13 @@ void QuickBuildComponent::Update(float deltaTime) {
if (m_TimeBeforeSmash > 0) {
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
m_ShowResetEffect = true;
m_StateDirty = true;
Game::entityManager->SerializeEntity(m_Parent);
}
if (m_TimerIncomplete >= m_TimeBeforeSmash) {
m_Builder = LWOOBJID_EMPTY;
GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
ClearActivityPlayerData();
GameMessages::SendDie(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
ResetQuickBuild(false);
}
}
@@ -276,11 +267,8 @@ void QuickBuildComponent::SpawnActivator() {
void QuickBuildComponent::DespawnActivator() {
if (m_Activator) {
Game::entityManager->DestructEntity(m_Activator);
m_Activator->ScheduleKillAfterUpdate();
m_Activator = nullptr;
m_ActivatorId = LWOOBJID_EMPTY;
}
}
@@ -317,10 +305,6 @@ std::vector<int> QuickBuildComponent::GetCustomModules() {
return m_CustomModules;
}
int QuickBuildComponent::GetActivityId() {
return m_ActivityId;
}
int QuickBuildComponent::GetPostImaginationCost() {
return m_PostImaginationCost;
}
@@ -334,7 +318,9 @@ eQuickBuildState QuickBuildComponent::GetState() {
}
Entity* QuickBuildComponent::GetBuilder() const {
auto* builder = Game::entityManager->GetEntity(m_Builder);
const auto players = GetActivityPlayers();
if (players.empty()) return nullptr;
auto* builder = Game::entityManager->GetEntity(players[0]->playerID);
return builder;
}
@@ -348,15 +334,13 @@ void QuickBuildComponent::SetActivatorPosition(NiPoint3 value) {
}
void QuickBuildComponent::SetResetTime(float value) {
m_ResetTime = value;
if (value < 0) m_ResetTime = 20.0f;
else m_ResetTime = value;
}
void QuickBuildComponent::SetCompleteTime(float value) {
if (value < 0) {
m_CompleteTime = 4.5f;
} else {
m_CompleteTime = value;
}
if (value < 0) m_CompleteTime = 4.5f;
else m_CompleteTime = value;
}
void QuickBuildComponent::SetTakeImagination(int value) {
@@ -375,20 +359,13 @@ void QuickBuildComponent::SetCustomModules(std::vector<int> value) {
m_CustomModules = value;
}
void QuickBuildComponent::SetActivityId(int value) {
m_ActivityId = value;
}
void QuickBuildComponent::SetPostImaginationCost(int value) {
m_PostImaginationCost = value;
}
void QuickBuildComponent::SetTimeBeforeSmash(float value) {
if (value < 0) {
m_TimeBeforeSmash = 10.0f;
} else {
m_TimeBeforeSmash = value;
}
if (value < 0) m_TimeBeforeSmash = 10.0f;
else m_TimeBeforeSmash = value;
}
void QuickBuildComponent::SetRepositionPlayer(bool value) {
@@ -397,7 +374,8 @@ void QuickBuildComponent::SetRepositionPlayer(bool value) {
void QuickBuildComponent::StartQuickBuild(Entity* user) {
if (m_State == eQuickBuildState::OPEN || m_State == eQuickBuildState::COMPLETED || m_State == eQuickBuildState::INCOMPLETE) {
m_Builder = user->GetObjectID();
// user->GetObjectID();
AddActivityPlayerData(user->GetObjectID());
auto* character = user->GetComponent<CharacterComponent>();
character->SetCurrentActivity(eGameActivity::QUICKBUILDING);
@@ -478,14 +456,14 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* user) {
auto* member = Game::entityManager->GetEntity(memberId);
if (member) {
auto* missionComponent = member->GetComponent<MissionComponent>();
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, GetActivityID());
}
}
} else {
auto* missionComponent = builder->GetComponent<MissionComponent>();
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, GetActivityID());
}
Loot::DropActivityLoot(builder, m_Parent, m_ActivityId, 1);
Loot::DropActivityLoot(builder, m_Parent, GetActivityID(), 1);
}
// Notify scripts
@@ -557,8 +535,7 @@ void QuickBuildComponent::ResetQuickBuild(bool failed) {
void QuickBuildComponent::CancelQuickBuild(Entity* entity, eQuickBuildFailReason failReason, bool skipChecks) {
if (m_State != eQuickBuildState::COMPLETED || skipChecks) {
m_Builder = LWOOBJID_EMPTY;
RemoveActivityPlayerData(entity->GetObjectID());
const auto entityID = entity != nullptr ? entity->GetObjectID() : LWOOBJID_EMPTY;

View File

@@ -8,7 +8,7 @@
#include "NiPoint3.h"
#include "ScriptedActivityComponent.h"
#include "Preconditions.h"
#include "Component.h"
#include "ActivityComponent.h"
#include "eReplicaComponentType.h"
#include "eQuickBuildState.h"
@@ -20,11 +20,11 @@ enum class eQuickBuildFailReason : uint32_t;
* consists of an activator that shows a popup and then the actual entity that the bricks are built into. Note
* that quick builds are also scripted activities so this shared some logic with the ScriptedActivityComponent.
*/
class QuickBuildComponent : public Component {
class QuickBuildComponent : public ActivityComponent {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
QuickBuildComponent(Entity* entity);
QuickBuildComponent(Entity* parent, uint32_t id);
~QuickBuildComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
@@ -213,11 +213,11 @@ public:
/**
* Cancels the quickbuild if it wasn't completed
* @param builder the player that's currently building
* @param entity the player that's currently building
* @param failReason the reason the quickbuild was cancelled
* @param skipChecks whether or not to skip the check for the quickbuild not being completed
*/
void CancelQuickBuild(Entity* builder, eQuickBuildFailReason failReason, bool skipChecks = false);
void CancelQuickBuild(Entity* entity, eQuickBuildFailReason failReason, bool skipChecks = false);
private:
/**
* Whether or not the quickbuild state has been changed since we last serialized it.
@@ -304,11 +304,6 @@ private:
*/
std::vector<int> m_CustomModules{};
/**
* The activity ID that players partake in when doing this quickbuild
*/
int m_ActivityId = 0;
/**
* Currently unused
*/
@@ -339,11 +334,6 @@ private:
*/
float m_SoftTimer = 0;
/**
* The ID of the entity that's currently building the quickbuild
*/
LWOOBJID m_Builder = LWOOBJID_EMPTY;
/**
* Preconditions to be met before being able to start the quickbuild
*/
@@ -360,6 +350,11 @@ private:
* @param user the entity that completed the quickbuild
*/
void CompleteQuickBuild(Entity* user);
/**
* Is this quickbuild from a choicebuild
*/
bool m_IsChoiceBuild = false;
};
#endif // QUICKBUILDCOMPONENT_H

View File

@@ -300,7 +300,7 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
if (!racingPlayer.noSmashOnReload) {
racingPlayer.smashedTimes++;
GameMessages::SendDie(vehicle, vehicle->GetObjectID(), LWOOBJID_EMPTY, true,
eKillType::VIOLENT, u"", 0, 0, 90.0f, false, true, 0);
eKillType::VIOLENT, u"", 0, 0, 90.0f, false, true);
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
uint32_t respawnImagination = 0;
@@ -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, [=, this]() {
vehicle->AddCallbackTimer(2.0f, [=]() {
if (!vehicle || !this->m_Parent) return;
GameMessages::SendRacingResetPlayerToLastReset(
m_Parent->GetObjectID(), racingPlayer.playerID,
@@ -769,7 +769,7 @@ void RacingControlComponent::Update(float deltaTime) {
if (vehiclePosition.y < -500) {
GameMessages::SendDie(vehicle, m_Parent->GetObjectID(),
LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0,
true, false, 0);
true, false);
OnRequestDie(playerEntity);

View File

@@ -814,29 +814,7 @@ void GameMessages::SendTerminateInteraction(const LWOOBJID& objectID, eTerminate
SEND_PACKET_BROADCAST;
}
void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(eGameMessageType::DIE);
bitStream.Write(bClientDeath);
bitStream.Write(bSpawnLoot);
bitStream.Write(deathType);
bitStream.Write(directionRelative_AngleXZ);
bitStream.Write(directionRelative_AngleY);
bitStream.Write(directionRelative_Force);
bitStream.Write(killType != eKillType::VIOLENT);
if (killType != eKillType::VIOLENT) bitStream.Write(killType);
bitStream.Write(killerID);
bitStream.Write(lootOwnerID);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, bool bDieAccepted, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot, float coinSpawnTime) {
void GameMessages::SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, bool bDieAccepted, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot) {
CBITSTREAM;
CMSGHEADER;
@@ -847,9 +825,6 @@ void GameMessages::SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOB
bitStream.Write(bClientDeath);
bitStream.Write(bSpawnLoot);
//bitStream.Write(coinSpawnTime != -1.0f);
//if (coinSpawnTime != -1.0f) bitStream.Write(coinSpawnTime);
uint32_t deathTypeLength = deathType.size();
bitStream.Write(deathTypeLength);
for (uint32_t k = 0; k < deathTypeLength; k++) {
@@ -4072,7 +4047,6 @@ void GameMessages::HandleRacingClientReady(RakNet::BitStream* inStream, Entity*
void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
bool bClientDeath;
bool bSpawnLoot;
std::u16string deathType;
float directionRelativeAngleXZ;
float directionRelativeAngleY;
@@ -4080,17 +4054,14 @@ void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity,
eKillType killType = eKillType::VIOLENT;
LWOOBJID killerID;
LWOOBJID lootOwnerID = LWOOBJID_EMPTY;
uint32_t deathTypeLength = 0;
bClientDeath = inStream->ReadBit();
bSpawnLoot = inStream->ReadBit();
uint32_t deathTypeLength = 0;
inStream->Read(deathTypeLength);
for (size_t i = 0; i < deathTypeLength; i++) {
char16_t character;
inStream->Read(character);
deathType.push_back(character);
}
@@ -4098,39 +4069,25 @@ void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity,
inStream->Read(directionRelativeAngleY);
inStream->Read(directionRelativeForce);
if (inStream->ReadBit()) {
inStream->Read(killType);
}
if (inStream->ReadBit()) inStream->Read(killType);
inStream->Read(killerID);
if (inStream->ReadBit()) {
inStream->Read(lootOwnerID);
}
inStream->Read(lootOwnerID);
auto* zoneController = Game::zoneManager->GetZoneControlObject();
auto* racingControlComponent = zoneController->GetComponent<RacingControlComponent>();
LOG("Got die request: %i", entity->GetLOT());
if (racingControlComponent != nullptr) {
if (racingControlComponent) {
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
if (possessableComponent != nullptr) {
if (possessableComponent) {
entity = Game::entityManager->GetEntity(possessableComponent->GetPossessor());
if (entity == nullptr) {
return;
}
if (!entity) return;
}
racingControlComponent->OnRequestDie(entity);
} else {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Smash(killerID, killType, deathType);
}
}
@@ -4953,7 +4910,7 @@ void GameMessages::HandleQuickBuildCancel(RakNet::BitStream* inStream, Entity* e
inStream->Read(bEarlyRelease);
inStream->Read(userID);
auto* quickBuildComponent = static_cast<QuickBuildComponent*>(entity->GetComponent(eReplicaComponentType::QUICK_BUILD));;
auto* quickBuildComponent = entity->GetComponent<QuickBuildComponent>();
if (!quickBuildComponent) return;
quickBuildComponent->CancelQuickBuild(Game::entityManager->GetEntity(userID), eQuickBuildFailReason::CANCELED_EARLY);
@@ -5258,45 +5215,6 @@ void GameMessages::HandlePickupCurrency(RakNet::BitStream* inStream, Entity* ent
}
}
void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity) {
LWOOBJID killerID;
LWOOBJID lootOwnerID;
bool bDieAccepted = false;
eKillType killType;
std::u16string deathType;
float directionRelative_AngleY;
float directionRelative_AngleXZ;
float directionRelative_Force;
bool bClientDeath = false;
bool bSpawnLoot = true;
float coinSpawnTime = -1.0f;
inStream->Read(bClientDeath);
inStream->Read(bDieAccepted);
inStream->Read(bSpawnLoot);
bool coinSpawnTimeIsDefault{};
inStream->Read(coinSpawnTimeIsDefault);
if (coinSpawnTimeIsDefault != 0) inStream->Read(coinSpawnTime);
/*uint32_t deathTypeLength = deathType.size();
inStream->Read(deathTypeLength);
for (uint32_t k = 0; k < deathTypeLength; k++) {
inStream->Read<uint16_t>(deathType[k]);
}*/
inStream->Read(directionRelative_AngleXZ);
inStream->Read(directionRelative_AngleY);
inStream->Read(directionRelative_Force);
bool killTypeIsDefault{};
inStream->Read(killTypeIsDefault);
if (killTypeIsDefault != 0) inStream->Read(killType);
inStream->Read(lootOwnerID);
inStream->Read(killerID);
}
void GameMessages::HandleEquipItem(RakNet::BitStream* inStream, Entity* entity) {
bool immediate;
LWOOBJID objectID;

View File

@@ -105,8 +105,7 @@ namespace GameMessages {
void AddActivityOwner(Entity* entity, LWOOBJID& ownerID);
void SendTerminateInteraction(const LWOOBJID& objectID, eTerminateType type, const LWOOBJID& terminator);
void SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot);
void SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, bool bDieAccepted, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot, float coinSpawnTime);
void SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, bool bDieAccepted, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot);
void SendSetInventorySize(Entity* entity, int invType, int size);
@@ -613,7 +612,6 @@ namespace GameMessages {
void HandleHasBeenCollected(RakNet::BitStream* inStream, Entity* entity);
void HandleNotifyServerLevelProcessingComplete(RakNet::BitStream* inStream, Entity* entity);
void HandlePickupCurrency(RakNet::BitStream* inStream, Entity* entity);
void HandleRequestDie(RakNet::BitStream* inStream, Entity* entity);
void HandleEquipItem(RakNet::BitStream* inStream, Entity* entity);
void HandleUnequipItem(RakNet::BitStream* inStream, Entity* entity);
void HandleRemoveItemFromInventory(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);

View File

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

View File

@@ -294,20 +294,21 @@ void VanityUtilities::ParseXML(const std::string& file) {
auto* partyPhrases = npcs->FirstChildElement("partyphrases");
if (partyPhrases == nullptr) {
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);
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;
}
m_PartyPhrases.push_back(text);
}
for (auto* npc = npcs->FirstChildElement("npc"); npc != nullptr; npc = npc->NextSiblingElement("npc")) {
@@ -524,12 +525,12 @@ std::string VanityUtilities::ParseMarkdown(const std::string& file) {
#endif
// Replace "__TIMESTAMP__" with the __TIMESTAMP__
GeneralUtils::ReplaceInString(line, "__TIMESTAMP__", __TIMESTAMP__);
// Replace "__VERSION__" with the PROJECT_VERSION
GeneralUtils::ReplaceInString(line, "__VERSION__", Game::projectVersion);
// Replace "__VERSION__" wit'h the PROJECT_VERSION
GeneralUtils::ReplaceInString(line, "__VERSION__", STRINGIFY(PROJECT_VERSION));
// Replace "__SOURCE__" with SOURCE
GeneralUtils::ReplaceInString(line, "__SOURCE__", Game::config->GetValue("source"));
// Replace "__LICENSE__" with LICENSE
GeneralUtils::ReplaceInString(line, "__LICENSE__", "AGPL-3.0");
GeneralUtils::ReplaceInString(line, "__LICENSE__", STRINGIFY(LICENSE));
if (line.find("##") != std::string::npos) {
// Add "&lt;font size=&apos;18&apos; color=&apos;#000000&apos;&gt;" before the header

View File

@@ -1,12 +1,10 @@
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)

View File

@@ -9,11 +9,10 @@
#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;
@@ -58,7 +57,33 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers);
//Start the actual process:
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, 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(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());
m_Instances.push_back(instance);
@@ -134,7 +159,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];
@@ -293,7 +318,28 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password);
//Start the actual process:
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
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());
m_Instances.push_back(instance);

View File

@@ -7,7 +7,11 @@
#include <thread>
#include <fstream>
#ifdef _WIN32
#include <bcrypt/BCrypt.hpp>
#else
#include <bcrypt.h>
#endif
#include <csignal>
@@ -39,7 +43,6 @@
#include "PacketUtils.h"
#include "FdbToSqlite.h"
#include "BitStreamUtils.h"
#include "Start.h"
namespace Game {
Logger* logger = nullptr;
@@ -47,15 +50,16 @@ namespace Game {
InstanceManager* im = nullptr;
dConfig* config = nullptr;
AssetManager* assetManager = nullptr;
Game::signal_t lastSignal = 0;
bool universeShutdownRequested = false;
bool shouldShutdown = false;
std::mt19937 randomEngine;
} //namespace Game
bool shutdownSequenceStarted = false;
int ShutdownSequence(int32_t signal = -1);
void 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;
@@ -74,39 +78,39 @@ int main(int argc, char** argv) {
//Triggers the shutdown sequence at application exit
std::atexit([]() { ShutdownSequence(); });
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
signal(SIGINT, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
signal(SIGTERM, [](int32_t signal) { ShutdownSequence(EXIT_FAILURE); });
//Create all the objects we need to run our service:
Game::logger = SetupLogger();
if (!Game::logger) return EXIT_FAILURE;
if (!dConfig::Exists("authconfig.ini")) {
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "authconfig.ini")) {
LOG("Couldnt find authconfig.ini");
return EXIT_FAILURE;
}
if (!dConfig::Exists("chatconfig.ini")) {
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "chatconfig.ini")) {
LOG("Couldnt find chatconfig.ini");
return EXIT_FAILURE;
}
if (!dConfig::Exists("masterconfig.ini")) {
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "masterconfig.ini")) {
LOG("Couldnt find masterconfig.ini");
return EXIT_FAILURE;
}
if (!dConfig::Exists("sharedconfig.ini")) {
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini")) {
LOG("Couldnt find sharedconfig.ini");
return EXIT_FAILURE;
}
if (!dConfig::Exists("worldconfig.ini")) {
if (!std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "worldconfig.ini")) {
LOG("Couldnt find worldconfig.ini");
return EXIT_FAILURE;
}
Game::config = new dConfig("masterconfig.ini");
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "masterconfig.ini").string());
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
@@ -122,7 +126,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: %s", PROJECT_VERSION);
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
LOG("Compiled on: %s", __TIMESTAMP__);
//Connect to the MySQL Database
@@ -287,7 +291,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::lastSignal);
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::shouldShutdown);
//Query for the database for a server labeled "master"
@@ -322,8 +326,7 @@ int main(int argc, char** argv) {
uint32_t framesSinceLastSQLPing = 0;
uint32_t framesSinceKillUniverseCommand = 0;
Game::logger->Flush();
while (!Game::ShouldShutdown()) {
while (true) {
//In world we'd update our other systems here.
//Check for packets here:
@@ -357,10 +360,10 @@ int main(int argc, char** argv) {
framesSinceLastSQLPing++;
//10m shutdown for universe kill command
if (Game::universeShutdownRequested) {
if (Game::shouldShutdown) {
if (framesSinceKillUniverseCommand >= shutdownUniverseTime) {
//Break main loop and exit
Game::lastSignal = -1;
break;
} else
framesSinceKillUniverseCommand++;
}
@@ -404,7 +407,7 @@ int main(int argc, char** argv) {
t += std::chrono::milliseconds(masterFrameDelta);
std::this_thread::sleep_until(t);
}
return ShutdownSequence(EXIT_SUCCESS);
return FinalizeShutdown(EXIT_SUCCESS);
}
Logger* SetupLogger() {
@@ -801,7 +804,7 @@ void HandlePacket(Packet* packet) {
case eMasterMessageType::SHUTDOWN_UNIVERSE: {
LOG("Received shutdown universe command, shutting down in 10 minutes.");
Game::universeShutdownRequested = true;
Game::shouldShutdown = true;
break;
}
@@ -811,12 +814,46 @@ void HandlePacket(Packet* packet) {
}
}
int ShutdownSequence(int32_t signal) {
if (!Game::logger) return -1;
LOG("Recieved Signal %d", signal);
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) {
if (shutdownSequenceStarted) {
LOG("Duplicate Shutdown Sequence");
return -1;
return;
}
if (!Game::im) {
@@ -825,7 +862,7 @@ int ShutdownSequence(int32_t signal) {
Game::im->SetIsShuttingDown(true);
shutdownSequenceStarted = true;
Game::lastSignal = -1;
Game::shouldShutdown = true;
{
CBITSTREAM;
@@ -894,20 +931,16 @@ int ShutdownSequence(int32_t signal) {
}
}
return FinalizeShutdown(signal);
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;

View File

@@ -1,71 +0,0 @@
#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());
}

View File

@@ -1,6 +0,0 @@
#pragma once
#include "dCommonVars.h"
void StartAuthServer();
void StartChatServer();
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);

View File

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

View File

@@ -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, Game::signal_t* lastSignal, 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, bool* shouldShutdown, 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 = lastSignal;
mShouldShutdown = shouldShutdown;
//Attempt to start our server here:
mIsOkay = Startup();
@@ -75,9 +75,7 @@ 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();
if (!ConnectToMaster()) {
LOG("Failed ConnectToMaster!");
}
ConnectToMaster();
}
//Set up Replica if we're a world server:
@@ -131,7 +129,7 @@ Packet* dServer::ReceiveFromMaster() {
break;
}
case eMasterMessageType::SHUTDOWN:
*mShouldShutdown = -2;
*mShouldShutdown = true;
break;
//When we handle these packets in World instead dServer, we just return the packet's pointer.
@@ -238,12 +236,10 @@ void dServer::Shutdown() {
void dServer::SetupForMasterConnection() {
mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
mMasterPeer = RakNetworkFactory::GetRakPeerInterface();
bool ret = mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1);
if (!ret) LOG("Failed MasterPeer Startup!");
mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1);
}
bool dServer::ConnectToMaster() {
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
}

View File

@@ -1,6 +1,5 @@
#pragma once
#include <string>
#include <csignal>
#include "RakPeerInterface.h"
#include "ReplicaManager.h"
#include "NetworkIDManager.h"
@@ -16,10 +15,6 @@ 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!
@@ -36,7 +31,7 @@ public:
int masterPort,
ServerType serverType,
dConfig* config,
Game::signal_t* shouldShutdown,
bool* shouldShutdown,
unsigned int zoneID = 0);
~dServer();
@@ -86,9 +81,9 @@ private:
NetworkIDManager* mNetIDManager = nullptr;
/**
* Whether or not to shut down the server. Pointer to Game::lastSignal.
* Whether or not to shut down the server. Pointer to Game::shouldShutdown.
*/
Game::signal_t* mShouldShutdown = nullptr;
bool* mShouldShutdown = nullptr;
SocketDescriptor mSocketDescriptor;
std::string mIP;
int mPort;

View File

@@ -55,7 +55,7 @@ void RaceMaelstromGeiser::OnProximityUpdate(Entity* self, Entity* entering, std:
}
GameMessages::SendDie(vehicle, self->GetObjectID(), LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0, true, false, 0);
GameMessages::SendDie(vehicle, self->GetObjectID(), LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0, true, false);
auto* zoneController = Game::zoneManager->GetZoneControlObject();

View File

@@ -40,7 +40,7 @@ void ActVehicleDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
}
GameMessages::SendDie(vehicle, self->GetObjectID(), LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0, true, false, 0);
GameMessages::SendDie(vehicle, self->GetObjectID(), LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0, true, false);
auto* zoneController = Game::zoneManager->GetZoneControlObject();

View File

@@ -5,7 +5,6 @@ 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)

View File

@@ -88,10 +88,9 @@ namespace Game {
RakPeerInterface* chatServer = nullptr;
std::mt19937 randomEngine;
SystemAddress chatSysAddr;
Game::signal_t lastSignal = 0;
bool shouldShutdown = false;
EntityManager* entityManager = nullptr;
dZoneManager* zoneManager = nullptr;
std::string projectVersion = PROJECT_VERSION;
} // namespace Game
bool chatDisabled = false;
@@ -124,8 +123,8 @@ int main(int argc, char** argv) {
// Triggers the shutdown sequence at application exit
std::atexit(WorldShutdownSequence);
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
signal(SIGINT, [](int) { WorldShutdownSequence(); });
signal(SIGTERM, [](int) { WorldShutdownSequence(); });
uint32_t zoneID = 1000;
uint32_t cloneID = 0;
@@ -148,12 +147,12 @@ int main(int argc, char** argv) {
if (!Game::logger) return EXIT_FAILURE;
//Read our config:
Game::config = new dConfig("worldconfig.ini");
Game::config = new dConfig((BinaryPathFinder::GetBinaryDir() / "worldconfig.ini").string());
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
LOG("Starting World server...");
LOG("Version: %s", Game::projectVersion.c_str());
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
LOG("Compiled on: %s", __TIMESTAMP__);
if (Game::config->GetValue("disable_chat") == "1") chatDisabled = true;
@@ -212,7 +211,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::lastSignal, zoneID);
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::shouldShutdown, zoneID);
//Connect to the chat server:
uint32_t chatPort = 1501;
@@ -313,8 +312,6 @@ 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);
@@ -365,9 +362,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::lastSignal = -1;
Game::shouldShutdown = true;
}
} else framesSinceMasterDisconnect = 0;
@@ -462,7 +459,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::lastSignal = -1;
Game::shouldShutdown = true;
}
} else {
framesSinceLastUser = 0;
@@ -515,7 +512,7 @@ int main(int argc, char** argv) {
}
}
if (Game::ShouldShutdown() && !worldShutdownSequenceComplete) {
if (Game::shouldShutdown && !worldShutdownSequenceComplete) {
WorldShutdownProcess(zoneID);
break;
}
@@ -824,7 +821,7 @@ void HandlePacket(Packet* packet) {
}
case eMasterMessageType::SHUTDOWN: {
Game::lastSignal = -1;
Game::shouldShutdown = true;
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
break;
}
@@ -1291,17 +1288,14 @@ void WorldShutdownProcess(uint32_t zoneId) {
}
void WorldShutdownSequence() {
bool shouldShutdown = Game::ShouldShutdown() || worldShutdownSequenceComplete;
Game::lastSignal = -1;
Game::shouldShutdown = true;
#ifndef DARKFLAME_PLATFORM_WIN32
if (shouldShutdown)
if (Game::shouldShutdown || worldShutdownSequenceComplete)
#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();

View File

@@ -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([=, this]() {
ssEntity->AddDieCallback([=]() {
Spawn();
});
}
for (Spawner* ssSpawner : spawnSmashSpawners) {
m_SpawnSmashFoundGroup = true;
ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
ssSpawner->AddSpawnedEntityDieCallback([=]() {
Spawn();
});
}
for (Spawner* ssSpawner : spawnSmashSpawnersN) {
m_SpawnSmashFoundGroup = true;
m_SpawnOnSmash = ssSpawner;
ssSpawner->AddSpawnedEntityDieCallback([=, this]() {
ssSpawner->AddSpawnedEntityDieCallback([=]() {
Spawn();
});
}

View File

@@ -33,7 +33,7 @@ ARG BUILD_THREADS=1
ARG BUILD_VERSION=171022
RUN echo "Build server"
RUN sed -i -e "s/MARIADB_CONNECTOR_COMPILE_JOBS=.*/MARIADB_CONNECTOR_COMPILE_JOBS=${BUILD_THREADS}/g" CMakeVariables.txt
RUN sed -i -e "s/__maria_db_connector_compile_jobs__=.*/__maria_db_connector_compile_jobs__=${BUILD_THREADS}/g" CMakeVariables.txt
RUN mkdir -p cmake_build
RUN cd cmake_build && \
cmake .. -DCMAKE_BUILD_RPATH_USE_ORIGIN=TRUE && \

View File

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

View File

@@ -11,5 +11,4 @@ namespace Game {
AssetManager* assetManager = nullptr;
SystemAddress chatSysAddr;
EntityManager* entityManager = nullptr;
std::string projectVersion;
}

View File

@@ -11,17 +11,11 @@ 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)
@@ -37,7 +31,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

View File

@@ -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${MARIADB_CONNECTOR_COMPILE_JOBS}
BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${__maria_db_connector_compile_jobs__}
INSTALL_COMMAND "")
ExternalProject_Get_Property(mariadb_connector_cpp BINARY_DIR)

View File

@@ -80,8 +80,6 @@ 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)