Files
DarkflameServer/dMasterServer/Start.cpp
Aaron Kimbrell 37cc844562 revert(master): the edit mode flag on a private instance
This reverts commit 4cf0909d. Nothing starts an edit mode instance any more. Its two
fixes that had nothing to do with edit mode come back in the next commit.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-10 19:34:43 -06:00

238 lines
6.8 KiB
C++

#include "Start.h"
#include "Logger.h"
#include "dConfig.h"
#include "Game.h"
#include "BinaryPathFinder.h"
#ifdef _WIN32
#include <windows.h>
#include <handleapi.h>
#include <processthreadsapi.h>
namespace {
const auto startup = STARTUPINFOW{
.cb = sizeof(STARTUPINFOW),
.lpReserved = nullptr,
.lpDesktop = nullptr,
.lpTitle = nullptr,
.dwX = 0,
.dwY = 0,
.dwXSize = 0,
.dwYSize = 0,
.dwXCountChars = 0,
.dwYCountChars = 0,
.dwFillAttribute = 0,
.dwFlags = 0,
.wShowWindow = 0,
.cbReserved2 = 0,
.lpReserved2 = nullptr,
.hStdInput = INVALID_HANDLE_VALUE,
.hStdOutput = INVALID_HANDLE_VALUE,
.hStdError = INVALID_HANDLE_VALUE,
};
}
#else
#include <cstdio>
#include <unistd.h>
#endif
uint32_t StartChatServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Chat will not be restarted.");
return 0;
}
auto chat_path = BinaryPathFinder::GetBinaryDir() / "ChatServer";
#ifdef _WIN32
chat_path.replace_extension(".exe");
auto chat_startup = startup;
auto chat_info = PROCESS_INFORMATION{};
if (!CreateProcessW(chat_path.wstring().data(), chat_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&chat_startup, &chat_info))
{
LOG("Failed to launch ChatServer");
return 0;
}
// get pid and close unused handles
auto chat_pid = chat_info.dwProcessId;
CloseHandle(chat_info.hProcess);
CloseHandle(chat_info.hThread);
#else // *nix systems
const auto chat_pid = fork();
if (chat_pid < 0) {
LOG("Failed to launch ChatServer");
return 0;
} else if (chat_pid == 0) {
// We are the child process
execl(chat_path.string().c_str(), chat_path.string().c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);
}
#endif
LOG("ChatServer PID is %d", chat_pid);
return chat_pid;
}
uint32_t StartAuthServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Auth will not be restarted.");
return 0;
}
auto auth_path = BinaryPathFinder::GetBinaryDir() / "AuthServer";
#ifdef _WIN32
auth_path.replace_extension(".exe");
auto auth_startup = startup;
auto auth_info = PROCESS_INFORMATION{};
if (!CreateProcessW(auth_path.wstring().data(), auth_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&auth_startup, &auth_info))
{
LOG("Failed to launch AuthServer");
return 0;
}
// get pid and close unused handles
auto auth_pid = auth_info.dwProcessId;
CloseHandle(auth_info.hProcess);
CloseHandle(auth_info.hThread);
#else // *nix systems
const auto auth_pid = fork();
if (auth_pid < 0) {
LOG("Failed to launch AuthServer");
return 0;
} else if (auth_pid == 0) {
// We are the child process
execl(auth_path.string().c_str(), auth_path.string().c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);
}
#endif
LOG("AuthServer PID is %d", auth_pid);
return auth_pid;
}
uint32_t StartDashboardServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. DashboardServer will not be restarted.");
return 0;
}
auto web_path = BinaryPathFinder::GetBinaryDir() / "DashboardServer";
#ifdef _WIN32
web_path.replace_extension(".exe");
auto web_startup = startup;
auto web_info = PROCESS_INFORMATION{};
if (!CreateProcessW(web_path.wstring().data(), web_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&web_startup, &web_info))
{
LOG("Failed to launch DashboardServer");
return 0;
}
// get pid and close unused handles
auto web_pid = web_info.dwProcessId;
CloseHandle(web_info.hProcess);
CloseHandle(web_info.hThread);
#else // *nix systems
const auto web_pid = fork();
if (web_pid < 0) {
LOG("Failed to launch DashboardServer");
return 0;
} else if (web_pid == 0) {
// We are the child process
execl(web_path.string().c_str(), web_path.string().c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);
}
#endif
LOG("DashboardServer PID is %d", web_pid);
return web_pid;
}
uint32_t StartUgcServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. UgcServer will not be restarted.");
return 0;
}
auto ugc_path = BinaryPathFinder::GetBinaryDir() / "UgcServer";
#ifdef _WIN32
ugc_path.replace_extension(".exe");
auto ugc_startup = startup;
auto ugc_info = PROCESS_INFORMATION{};
if (!CreateProcessW(ugc_path.wstring().data(), ugc_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&ugc_startup, &ugc_info))
{
LOG("Failed to launch UgcServer");
return 0;
}
// get pid and close unused handles
auto ugc_pid = ugc_info.dwProcessId;
CloseHandle(ugc_info.hProcess);
CloseHandle(ugc_info.hThread);
#else // *nix systems
const auto ugc_pid = fork();
if (ugc_pid < 0) {
LOG("Failed to launch UgcServer");
return 0;
} else if (ugc_pid == 0) {
// We are the child process
execl(ugc_path.string().c_str(), ugc_path.string().c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);
}
#endif
LOG("UgcServer PID is %d", ugc_pid);
return ugc_pid;
}
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
auto world_path = BinaryPathFinder::GetBinaryDir() / "WorldServer";
#ifdef _WIN32
world_path.replace_extension(".exe");
auto cmd = world_path.wstring() + L" -zone " + std::to_wstring(mapID) + L" -port " + std::to_wstring(port) +
L" -instance " + std::to_wstring(lastInstanceID) + L" -maxclients " + std::to_wstring(maxPlayers) +
L" -clone " + std::to_wstring(cloneID);
auto world_startup = startup;
auto world_info = PROCESS_INFORMATION{};
if (!CreateProcessW(world_path.wstring().data(), cmd.data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&world_startup, &world_info))
{
LOG("Failed to launch WorldServer");
return 0;
}
// get pid and close unused handles
auto world_pid = world_info.dwProcessId;
CloseHandle(world_info.hProcess);
CloseHandle(world_info.hThread);
#else
const auto world_pid = fork();
if (world_pid < 0) {
LOG("Failed to launch WorldServer");
return 0;
} else if (world_pid == 0) {
// We are the child process
execl(world_path.string().c_str(), world_path.string().c_str(),
"-zone", std::to_string(mapID).c_str(),
"-port", std::to_string(port).c_str(),
"-instance", std::to_string(lastInstanceID).c_str(),
"-maxclients", std::to_string(maxPlayers).c_str(),
"-clone", std::to_string(cloneID).c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);
}
#endif
LOG("WorldServer PID is %d", world_pid);
return world_pid;
}