mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 00:40:53 +01:00
242 lines
6.3 KiB
C++
242 lines
6.3 KiB
C++
|
|
|
||
|
|
#include <TiltedCore/Filesystem.hpp>
|
||
|
|
#include <chrono>
|
||
|
|
#include <filesystem>
|
||
|
|
#include <fstream>
|
||
|
|
#include <string>
|
||
|
|
#include <thread>
|
||
|
|
|
||
|
|
#include <spdlog/sinks/rotating_file_sink.h>
|
||
|
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||
|
|
|
||
|
|
#include <Setting.h>
|
||
|
|
#include <base/simpleini/SimpleIni.h>
|
||
|
|
#include <base/threading/ThreadUtils.h>
|
||
|
|
|
||
|
|
#include "DediRunner.h"
|
||
|
|
#include <crash_handler/CrashHandler.h>
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
#include <base/dialogues/win/TaskDialog.h>
|
||
|
|
#pragma comment(lib, "Comctl32.lib")
|
||
|
|
#elif defined(__linux__)
|
||
|
|
#include <signal.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
constexpr char kLogFileName[] = "STServerOut.log";
|
||
|
|
// Its fine for us if several potential server instances read this, since its a tilted platform thing
|
||
|
|
// and therefore not considered game specific.
|
||
|
|
constexpr char kEULAName[] = "EULA.txt";
|
||
|
|
constexpr char kEULAText[] = ";Please indicate your agreement to the Tilted platform service agreement\n"
|
||
|
|
";by setting bConfirmEULA to true\n"
|
||
|
|
"[EULA]\n";
|
||
|
|
constexpr char kEULATextFalse[] = "bConfirmEULA=false";
|
||
|
|
constexpr char kEULATextTrue[] = "bConfirmEULA=true";
|
||
|
|
|
||
|
|
namespace fs = std::filesystem;
|
||
|
|
|
||
|
|
Console::StringSetting sLogLevel{"sLogLevel", "Log level to print", "info"};
|
||
|
|
using namespace std::chrono_literals;
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
extern Console::Setting<bool> bConsole;
|
||
|
|
|
||
|
|
GS_IMPORT void SetDefaultLogger(std::shared_ptr<spdlog::logger> aLogger);
|
||
|
|
GS_IMPORT void RegisterLogger(std::shared_ptr<spdlog::logger> aLogger);
|
||
|
|
|
||
|
|
struct LogInstance
|
||
|
|
{
|
||
|
|
static constexpr size_t kLogFileSizeCap = 1048576 * 5;
|
||
|
|
|
||
|
|
LogInstance()
|
||
|
|
{
|
||
|
|
using namespace spdlog;
|
||
|
|
|
||
|
|
std::error_code ec;
|
||
|
|
fs::create_directory("logs", ec);
|
||
|
|
|
||
|
|
auto consoleOut = spdlog::stdout_color_mt(KCompilerStopThisBullshit);
|
||
|
|
consoleOut->set_pattern(">%$ %v");
|
||
|
|
|
||
|
|
// make the client aware of this logger.
|
||
|
|
RegisterLogger(consoleOut);
|
||
|
|
|
||
|
|
auto fileOut = std::make_shared<sinks::rotating_file_sink_mt>(std::string("logs/") + kLogFileName, kLogFileSizeCap, 3);
|
||
|
|
auto serverOut = std::make_shared<sinks::stdout_color_sink_mt>();
|
||
|
|
serverOut->set_pattern("%^[%H:%M:%S.%e] [%l] [tid %t] %$ %v");
|
||
|
|
auto globalOut = std::make_shared<logger>("", sinks_init_list{serverOut, fileOut});
|
||
|
|
globalOut->set_level(level::from_str(sLogLevel.value()));
|
||
|
|
|
||
|
|
// as the library is compiled into the client + server we have to do this twice
|
||
|
|
spdlog::set_default_logger(globalOut);
|
||
|
|
|
||
|
|
// also make the client aware of the file loggers
|
||
|
|
SetDefaultLogger(globalOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
~LogInstance() { spdlog::shutdown(); }
|
||
|
|
};
|
||
|
|
|
||
|
|
static bool RegisterQuitHandler()
|
||
|
|
{
|
||
|
|
#if defined(_WIN32)
|
||
|
|
static auto CtrlHandler = ([](DWORD aType) {
|
||
|
|
switch (aType)
|
||
|
|
{
|
||
|
|
case CTRL_C_EVENT:
|
||
|
|
case CTRL_CLOSE_EVENT:
|
||
|
|
case CTRL_BREAK_EVENT:
|
||
|
|
case CTRL_LOGOFF_EVENT:
|
||
|
|
case CTRL_SHUTDOWN_EVENT: {
|
||
|
|
if (auto* pRunner = GetDediRunner())
|
||
|
|
{
|
||
|
|
pRunner->RequestKill();
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
// if the user kills during the ctor we deny the request
|
||
|
|
// to save our dear life.
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
return SetConsoleCtrlHandler(CtrlHandler, TRUE);
|
||
|
|
|
||
|
|
#elif defined(__linux__)
|
||
|
|
static auto CtrlHandler = ([](int aSig) {
|
||
|
|
if (auto* pRunner = GetDediRunner())
|
||
|
|
{
|
||
|
|
pRunner->RequestKill();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
signal(SIGINT, CtrlHandler);
|
||
|
|
signal(SIGTERM, CtrlHandler);
|
||
|
|
signal(SIGKILL, CtrlHandler);
|
||
|
|
#else
|
||
|
|
return true;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
static bool ShowEULADialog()
|
||
|
|
{
|
||
|
|
Base::TaskDialog dia(LoadIconW(GetModuleHandleW(nullptr), MAKEINTRESOURCEW(102)), L"Tilted Platform Agreement", L"Confirm the Tilted Platform EULA", L"TODO: Link to EULA", nullptr);
|
||
|
|
dia.AppendButton(100, L"Accept EULA");
|
||
|
|
dia.AppendButton(101, L"Deny EULA");
|
||
|
|
dia.SetDefaultButton(101 /*So they have to think about it*/);
|
||
|
|
|
||
|
|
return dia.Show() == 100;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// The eula can be accepted in 3 ways:
|
||
|
|
// - Either confirm the dialog on startup(windows only)
|
||
|
|
// - Or signal agreement using an environment variable
|
||
|
|
// - Or Simply set bConfirmEULA in EULA.txt to true
|
||
|
|
static bool IsEULAAccepted()
|
||
|
|
{
|
||
|
|
const auto path = fs::current_path() / kConfigPathName / kEULAName;
|
||
|
|
|
||
|
|
bool preAccept = false;
|
||
|
|
if (char* pValue = std::getenv("TILTED_ACCEPT_EULA"))
|
||
|
|
{
|
||
|
|
std::string_view env(pValue);
|
||
|
|
preAccept = env == "true" || env == "1" || env == "TRUE";
|
||
|
|
}
|
||
|
|
|
||
|
|
auto saveFile = [&]()
|
||
|
|
{
|
||
|
|
#ifdef _WIN32
|
||
|
|
// try using the dialog
|
||
|
|
if (!preAccept)
|
||
|
|
preAccept = ShowEULADialog();
|
||
|
|
#endif
|
||
|
|
fs::create_directory(fs::current_path() / kConfigPathName);
|
||
|
|
|
||
|
|
TiltedPhoques::String eulaText = kEULAText;
|
||
|
|
eulaText += preAccept ? kEULATextTrue : kEULATextFalse;
|
||
|
|
|
||
|
|
TiltedPhoques::SaveFile(path, eulaText);
|
||
|
|
return preAccept;
|
||
|
|
};
|
||
|
|
|
||
|
|
if (!exists(path))
|
||
|
|
{
|
||
|
|
return saveFile();
|
||
|
|
}
|
||
|
|
|
||
|
|
const auto data = TiltedPhoques::LoadFile(path);
|
||
|
|
|
||
|
|
CSimpleIni si;
|
||
|
|
|
||
|
|
if (si.LoadData(data.c_str()) != SI_OK)
|
||
|
|
return preAccept;
|
||
|
|
|
||
|
|
if (!si.GetBoolValue("EULA", "bConfirmEULA", false))
|
||
|
|
{
|
||
|
|
#ifdef _WIN32
|
||
|
|
preAccept = false;
|
||
|
|
return saveFile();
|
||
|
|
#else
|
||
|
|
return false;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
GS_IMPORT bool CheckBuildTag(const char* apBuildTag);
|
||
|
|
|
||
|
|
void ConfigureConsoleMode()
|
||
|
|
{
|
||
|
|
#ifdef _WIN32
|
||
|
|
SetConsoleOutputCP(CP_UTF8);
|
||
|
|
// Set the input code page to UTF-8
|
||
|
|
SetConsoleCP(CP_UTF8);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char** argv)
|
||
|
|
{
|
||
|
|
ConfigureConsoleMode();
|
||
|
|
|
||
|
|
// the binaries are not from the same commit.
|
||
|
|
if (!CheckBuildTag(kBuildTag))
|
||
|
|
return 1;
|
||
|
|
|
||
|
|
Base::SetCurrentThreadName("ServerRunnerMain");
|
||
|
|
|
||
|
|
LogInstance logger;
|
||
|
|
(void)logger;
|
||
|
|
|
||
|
|
// Disabled EULA check since we have no EULA contents yet
|
||
|
|
/*
|
||
|
|
if (!IsEULAAccepted())
|
||
|
|
{
|
||
|
|
spdlog::error("Please accept the EULA by setting bConfirmEULA to true in EULA.txt");
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
|
||
|
|
//ScopedCrashHandler _(true, true);
|
||
|
|
|
||
|
|
// Note(Vince): This started crashing on 1.7+ lets disable it for now.
|
||
|
|
// RegisterQuitHandler();
|
||
|
|
|
||
|
|
// Keep stack free.
|
||
|
|
const auto cpRunner{std::make_unique<DediRunner>(argc, argv)};
|
||
|
|
if (bConsole)
|
||
|
|
{
|
||
|
|
cpRunner->StartTerminalIO();
|
||
|
|
}
|
||
|
|
|
||
|
|
cpRunner->RunGSThread();
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|