#pragma once #include #include #include #include #include #include "TConsole.h" // static class handling application start, shutdown, etc. // yes, static classes, singletons, globals are all pretty // bad idioms. In this case we need a central way to access // stuff like graceful shutdown, global settings (its in the name), // etc. class Application final { public: // types struct TSettings { TSettings() noexcept : DebugModeEnabled(true) { } std::string ServerName; std::string ServerDesc; std::string Resource; std::string MapName; std::string Key; int MaxPlayers {}; bool Private {}; int MaxCars {}; bool DebugModeEnabled; int Port {}; std::string CustomIP; [[nodiscard]] bool HasCustomIP() const { return !CustomIP.empty(); } }; using TShutdownHandler = std::function; // methods Application() = delete; // 'Handler' is called when GracefullyShutdown is called static void RegisterShutdownHandler(const TShutdownHandler& Handler); // Causes all threads to finish up and exit gracefull gracefully static void GracefullyShutdown(); static TConsole& Console() { return *mConsole; } static std::string ServerVersion() { return "2.0"; } static std::string ClientVersion() { return "2.0"; } static std::string PPS() { return mPPS; } static void SetPPS(std::string NewPPS) { mPPS = NewPPS; } static inline TSettings Settings {}; static std::string GetBackendUrlForAuth() { return "auth.beammp.com"; } static std::string GetBackendHostname() { return "beammp.com"; } static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; } private: static inline std::string mPPS; static std::unique_ptr mConsole; static inline std::mutex mShutdownHandlersMutex {}; static inline std::deque mShutdownHandlers {}; }; #define KB 1024 #define MB (KB * 1024) #ifndef DEBUG static inline void warn(const std::string& str) { Application::Console().Write(std::string("[WARN] ") + str); } static inline void error(const std::string& str) { Application::Console().Write(std::string("[ERROR] ") + str); } static inline void info(const std::string& str) { Application::Console().Write(std::string("[INFO] ") + str); } static inline void debug(const std::string& str) { if (Application::Settings.DebugModeEnabled) { Application::Console().Write(std::string("[DEBUG] ") + str); } } static inline void luaprint(const std::string& str) { Application::Console().WriteRaw(str); } #else // DEBUG #define _file_basename std::filesystem::path(__FILE__).filename().string() #define _line std::to_string(__LINE__) #define _in_lambda (std::string(__func__) == "operator()") // we would like the full function signature 'void a::foo() const' // on windows this is __FUNCSIG__, on GCC it's __PRETTY_FUNCTION__, // feel free to add more #if defined(WIN32) #define _function_name std::string(__FUNCSIG__) #elif defined(__unix) || defined(__unix__) #define _function_name std::string(__PRETTY_FUNCTION__) #else #define _function_name std::string(__func__) #endif // if this is defined, we will show the full function signature infront of // each info/debug/warn... call instead of the 'filename:line' format. #if defined(BMP_FULL_FUNCTION_NAMES) #define _this_location (_function_name) #else #define _this_location (_file_basename + ":" + _line) #endif #define warn(x) Application::Console().Write(_this_location + std::string(" [WARN] ") + (x)) #define info(x) Application::Console().Write(_this_location + std::string(" [INFO] ") + (x)) #define error(x) Application::Console().Write(_this_location + std::string(" [ERROR] ") + (x)) #define luaprint(x) Application::Console().Write(_this_location + std::string(" [LUA] ") + (x)) #define debug(x) \ do { \ if (Application::Settings.DebugModeEnabled) { \ Application::Console().Write(_this_location + std::string(" [DEBUG] ") + (x)); \ } \ } while (false) #endif // DEBUG #define Biggest 30000 std::string Comp(std::string Data); std::string DeComp(std::string Compressed);