#include #include #include #include #include #include #include #ifndef _WINDOWS # include #else # define NO_MAIN # include #endif #include #include #include #include #include #include "Chat.h" #include "ChunkMap.h" #include "Server.h" FactoryCraftServer* mserver = 0; #ifdef _WINDOWS LONG WINAPI exceptionHandler(struct _EXCEPTION_POINTERS* apExceptionInfo) { Sleep(10000); Logging::error() << "Creating dump"; createMinidump(apExceptionInfo); if (mserver) { Logging::error() << "The server terminated unexpectedly. Trying to save game " "progress."; mserver->close(); } return EXCEPTION_CONTINUE_SEARCH; } #endif void onError(int i) { Sleep(10000); Logging::error() << "Creating dump"; createMinidump(0); if (mserver) { Logging::error() << "The server terminated unexpectedly. Trying to save game " "progress."; mserver->close(); } } void onExit() { Sleep(10000); Logging::info() << "Programm exited"; onError(0); } bool exited = false; class StatusBar : public StickyConsoleContent { public: StatusBar() : StickyConsoleContent() {} int print() const override { if (!exited && Game::INSTANCE) { std::cout << "\r\33[0K"; // erase current line int tps = Game::INSTANCE->getTicksPerSecond(); std::cout << "Players: " << Game::INSTANCE->getPlayerCount() << "\tChunks: " << Game::INSTANCE->getChunkCount() << "\ttps: "; if (tps < 15) { // red std::cout << "\033[1;31m"; } else if (tps < 20) { // yellow std::cout << "\033[1;33m"; } else { // green std::cout << "\033[1;32m"; } std::cout << tps << /* reset color */ "\033[0m" << "\tAverage Tick Time: " << Game::INSTANCE->getAverageTickTime(); return 1; } return 0; } }; int main() { #ifdef _WINDOWS SetUnhandledExceptionFilter(exceptionHandler); #endif Framework::initFramework(); Game::consoleHandler = new ConsoleHandler(); #ifndef _WINDOWS struct rlimit core_limits; core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &core_limits); #endif Zeit* z = getZeit(); Text* pfad = new Text("log/"); pfad->append(z->getZeit("y-m-d_h-i-s.log")); z->release(); Datei* logFile = new Datei(pfad); Logging::LoggingChannel* fileLogger = new Logging::FileLoggingChannel(logFile); fileLogger->setFormat(Logging::LoggingFormatBuilder() .datetime("h:i:s") .level(false) .text(": ") .build()); Logging::zLoggingHandler()->addChannel(fileLogger); Logging::zLoggingHandler()->removeLoggingChannel( Logging::LogLevel::Error, fileLogger); Logging::zLoggingHandler()->removeLoggingChannel( Logging::LogLevel::Warning, fileLogger); Logging::LoggingChannel* errorFileLogger = new Logging::FileLoggingChannel( dynamic_cast(logFile->getThis())); errorFileLogger->setFormat(Logging::LoggingFormatBuilder() .datetime("h:i:s") .level() .fileName() .functionName() .text("(") .fileLine(false) .text("): ") .build()); Framework::Logging::zLoggingHandler()->addChannel( Logging::LogLevel::Warning, dynamic_cast(errorFileLogger->getThis())); Framework::Logging::zLoggingHandler()->addChannel( Logging::LogLevel::Error, errorFileLogger); Logging::LoggingChannel* consoleLogger = new Logging::ConsoleHandlerLoggingChannel( dynamic_cast(Game::consoleHandler->getThis())); consoleLogger->setFormat( Logging::LoggingFormatBuilder() .color(Logging::LogLevel::Debug, Color::LIGHT_BLUE) .color(Logging::LogLevel::Trace, Color::LIGHT_CYAN) .datetime("h:i:s") .level(false) .text(": ") .build()); Framework::Logging::zLoggingHandler()->addChannel(consoleLogger); Framework::Logging::zLoggingHandler()->removeLoggingChannel( Logging::LogLevel::Error, consoleLogger); Framework::Logging::zLoggingHandler()->removeLoggingChannel( Logging::LogLevel::Warning, consoleLogger); Logging::LoggingChannel* errorConsoleLogger = new Logging::ConsoleHandlerLoggingChannel( dynamic_cast(Game::consoleHandler->getThis())); errorConsoleLogger->setFormat( Logging::LoggingFormatBuilder() .color(Logging::LogLevel::Warning, Color::LIGHT_YELLOW) .color(Logging::LogLevel::Error, Color::LIGHT_RED) .datetime("h:i:s") .level() .fileName() .functionName() .text("(") .fileLine(false) .text("): ") .build()); Framework::Logging::zLoggingHandler()->addChannel( Logging::LogLevel::Warning, dynamic_cast(errorConsoleLogger->getThis())); Framework::Logging::zLoggingHandler()->addChannel( Logging::LogLevel::Error, errorConsoleLogger); Game::consoleInput = new InputLine(); Game::consoleHandler->addContent( Game::consoleInput, ConsoleContentPosition::Bottom); Game::consoleHandler->addContent( new StatusBar(), ConsoleContentPosition::Bottom); Logging::info() << "Starting ..."; Logging::info() << "Loading config file fcInit.ini ..."; InitDatei* dat = new InitDatei("fcInit.ini"); if (!dat->laden()) { Logging::error() << "Datei konnte nicht gelesen werden. Das Programm " "wird geschlossen."; dat->release(); Game::consoleHandler->release(); Framework::releaseFramework(); return 1; } const char* wichtig[] = {"SSLPort", "SSLCert", "SSLKey", "SSLPasswort", "Port"}; for (const char* w : wichtig) { if (!dat->wertExistiert(w)) { Logging::error() << "The value '" << w << "' was not specified. The Server can not start."; dat->release(); Game::consoleHandler->release(); Framework::releaseFramework(); return 1; } } mserver = new FactoryCraftServer(dat); std::atexit(onExit); signal(SIGTERM, onError); signal(SIGSEGV, onError); signal(SIGILL, onError); signal(SIGABRT, onError); signal(SIGFPE, onError); signal(SIGINT, onError); Logging::info() << "The Server is now running."; mserver->run(); exited = 1; mserver->release(); mserver = 0; if (Game::INSTANCE) { Game* tmp = Game::INSTANCE; tmp->requestStop(); tmp->warteAufThread(100000000); tmp->release(); Game::INSTANCE = 0; } dat->release(); Logging::info() << "The server was shut down successfully."; Game::consoleHandler->release(); Framework::releaseFramework(); return 0; }