123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include <csignal>
- #include <cstdlib>
- #include <Datei.h>
- #include <fstream>
- #include <Globals.h>
- #include <iostream>
- #include <Klient.h>
- #ifndef _WINDOWS
- # include <sys/resource.h>
- #endif
- #include <AsynchronCall.h>
- #include <Text.h>
- #include <Zeit.h>
- #include "ChunkMap.h"
- #include "Server.h"
- FactoryCraftServer* mserver = 0;
- void exit()
- {
- if (mserver)
- {
- std::cout << "The server terminated unexpectedly. Trying to save game "
- "progress.\n";
- mserver->close();
- }
- }
- bool exited = false;
- class DuplicatingStreamBuf : public std::stringbuf
- {
- private:
- std::ostream& console;
- std::ostream& file;
- bool hasFile = 0;
- int infoLength;
- Critical cs;
- public:
- DuplicatingStreamBuf(std::ostream& console, std::ostream& file)
- : std::stringbuf(),
- console(console),
- file(file),
- hasFile(1),
- infoLength(0)
- {}
- DuplicatingStreamBuf(std::ostream& console)
- : std::stringbuf(),
- console(console),
- file(console),
- hasFile(0),
- infoLength(0)
- {}
- #ifdef WIN32
- void __CLR_OR_THIS_CALL _Lock() override
- {
- cs.lock();
- }
- void __CLR_OR_THIS_CALL _Unlock() override
- {
- cs.unlock();
- }
- #endif
- int sync() override
- {
- cs.lock();
- std::string value = str();
- if (value.length() == 0 && !Game::INSTANCE)
- {
- cs.unlock();
- return 0;
- }
- str("");
- if (infoLength > 0)
- {
- console << /* store cursor position */ "\033[s"
- << /* move cursor a line up*/ "\033[1A"
- << /* clear the line */ "\x1b[2K"
- << /* return to beginning of line */ "\r";
- }
- int newLines = Text(value.c_str()).anzahlVon('\n');
- if (value.length() > 0)
- {
- console << value;
- if (value.c_str()[value.length() - 1] != '\n')
- {
- console << "\n";
- newLines++;
- }
- }
- if (!exited && Game::INSTANCE)
- {
- int tps = Game::INSTANCE->getTicksPerSecond();
- Framework::Text infoLine = "";
- infoLine.append()
- << "Players: " << Game::INSTANCE->getPlayerCount()
- << "\tChunks: " << Game::INSTANCE->getChunkCount() << "\ttps: ";
- if (tps < 15)
- { // red
- infoLine += "\033[1;31m";
- }
- else if (tps < 20)
- { // yellow
- infoLine += "\033[1;33m";
- }
- else
- { // green
- infoLine += "\033[1;32m";
- }
- infoLine.append() << tps << /* reset color */ "\033[0m"
- << "\tAverage Tick Time: "
- << Game::INSTANCE->getAverageTickTime() << "\n";
- if (infoLength > 0)
- {
- infoLine.append()
- << /* restore cursor position */ "\033[u"
- << /* set cursor down by amount of new lines */
- (newLines > 0 ? (Text("\033[") + newLines + "B").getText()
- : "");
- // << "\x1b[0K";
- }
- infoLength = infoLine.getLength();
- console << infoLine << std::flush;
- }
- else
- {
- infoLength = 0;
- }
- if (hasFile) file << value << std::flush;
- cs.unlock();
- return 0;
- }
- };
- int main()
- {
- Framework::initFramework();
- #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();
- DateiPfadErstellen(pfad->getText());
- std::ofstream file;
- std::streambuf* sbuf = std::cout.rdbuf();
- // #ifndef _DEBUG
- file.open(pfad->getText());
- std::ostream newCout(sbuf);
- DuplicatingStreamBuf duplicator(newCout, file);
- std::cout.rdbuf(&duplicator);
- /* #else
- std::ostream newCout(sbuf);
- DuplicatingStreamBuf duplicator(newCout);
- std::cout.rdbuf(&duplicator);
- #endif */
- pfad->release();
- std::cout << "Starting...\n";
- std::cout << "Loading config file fcInit.ini ...\n";
- InitDatei* dat = new InitDatei("fcInit.ini");
- if (!dat->laden())
- {
- std::cout << "error: Datei konnte nicht gelesen werden. Das Programm "
- "wird geschlossen.\n";
- dat->release();
- // #ifndef _DEBUG
- file.close();
- // #endif
- std::cout.rdbuf(sbuf);
- exit(1);
- }
- const char* wichtig[]
- = {"SSLPort", "SSLCert", "SSLKey", "SSLPasswort", "Port"};
- for (const char* w : wichtig)
- {
- if (!dat->wertExistiert(w))
- {
- std::cout << "error: The value '" << w
- << "' was not specified. The Server can not start.\n";
- dat->release();
- file.close();
- std::cout.rdbuf(sbuf);
- exit(1);
- }
- }
- mserver = new FactoryCraftServer(dat);
- std::atexit(exit);
- signal(SIGTERM, exit);
- signal(SIGSEGV, exit);
- signal(SIGILL, exit);
- signal(SIGABRT, exit);
- signal(SIGFPE, exit);
- signal(SIGINT, exit);
- new Framework::AsynchronCall("Commander", []() {
- while (mserver)
- {
- std::string line;
- std::getline(std::cin, line);
- if (!mserver) return;
- std::cout << std::flush << "\033[1A"
- << "\x1b[2K"
- << "\x1b[0G" << line << "\n\033[1A\033[s" << std::flush;
- if (Text(line.c_str()) == Text("exit"))
- {
- std::cout << "The server will be terminated and the game "
- "progress will be saved.\n";
- mserver->close();
- return;
- }
- else if (Game::INSTANCE)
- {
- Game::INSTANCE->zChat()->zCommandExecutor()->execute(
- line.c_str(), 0);
- }
- }
- });
- std::cout << "The Server is now running.\n";
- 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();
- std::cout << "The server was shut down successfully.\n" << std::flush;
- // #ifndef _DEBUG
- file.close();
- // #endif
- std::cout.rdbuf(sbuf);
- Framework::releaseFramework();
- return 0;
- }
|