Start.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include <csignal>
  2. #include <cstdlib>
  3. #include <Datei.h>
  4. #include <fstream>
  5. #include <Globals.h>
  6. #include <iostream>
  7. #include <Klient.h>
  8. #ifndef _WINDOWS
  9. # include <sys/resource.h>
  10. #endif
  11. #include <AsynchronCall.h>
  12. #include <Text.h>
  13. #include <Zeit.h>
  14. #include "ChunkMap.h"
  15. #include "Server.h"
  16. FactoryCraftServer* mserver = 0;
  17. void exit()
  18. {
  19. if (mserver)
  20. {
  21. std::cout << "The server terminated unexpectedly. Trying to save game "
  22. "progress.\n";
  23. mserver->close();
  24. }
  25. }
  26. bool exited = false;
  27. class DuplicatingStreamBuf : public std::stringbuf
  28. {
  29. private:
  30. std::ostream& console;
  31. std::ostream& file;
  32. bool hasFile = 0;
  33. Critical cs;
  34. int infoLength;
  35. public:
  36. DuplicatingStreamBuf(std::ostream& console, std::ostream& file)
  37. : std::stringbuf(),
  38. console(console),
  39. file(file),
  40. hasFile(1),
  41. infoLength(0)
  42. {}
  43. DuplicatingStreamBuf(std::ostream& console)
  44. : std::stringbuf(),
  45. console(console),
  46. file(console),
  47. hasFile(0),
  48. infoLength(0)
  49. {}
  50. int sync() override
  51. {
  52. cs.lock();
  53. if (str().length() == 0 && !Game::INSTANCE)
  54. {
  55. cs.unlock();
  56. return 0;
  57. }
  58. if (infoLength > 0)
  59. {
  60. console << /* store cursor position */ "\033[s"
  61. << /* move cursor a line up*/ "\033[1A"
  62. << /* clear the line */ "\x1b[2K"
  63. << /* return to beginning of line */ "\r";
  64. }
  65. int newLines = Text(str().c_str()).anzahlVon('\n');
  66. if (str().length() > 0)
  67. {
  68. console << str();
  69. if (str().c_str()[str().length() - 1] != '\n')
  70. {
  71. console << "\n";
  72. newLines++;
  73. }
  74. }
  75. if (!exited && Game::INSTANCE)
  76. {
  77. int tps = Game::INSTANCE->getTicksPerSecond();
  78. Framework::Text infoLine = "";
  79. infoLine.append()
  80. << "Players: " << Game::INSTANCE->getPlayerCount()
  81. << "\tChunks: " << Game::INSTANCE->getChunkCount() << "\ttps: ";
  82. if (tps < 15)
  83. { // red
  84. infoLine += "\033[1;31m";
  85. }
  86. else if (tps < 20)
  87. { // yellow
  88. infoLine += "\033[1;33m";
  89. }
  90. else
  91. { // green
  92. infoLine += "\033[1;32m";
  93. }
  94. infoLine.append() << tps << /* reset color */ "\033[0m"
  95. << "\tAverage Tick Time: "
  96. << Game::INSTANCE->getAverageTickTime() << "\n";
  97. if (infoLength > 0)
  98. {
  99. infoLine.append()
  100. << /* restore cursor position */ "\033[u"
  101. << /* set cursor down by amount of new lines */
  102. (newLines > 0 ? (Text("\033[") + newLines + "B").getText()
  103. : "");
  104. // << "\x1b[0K";
  105. }
  106. infoLength = infoLine.getLength();
  107. console << infoLine << std::flush;
  108. }
  109. else
  110. {
  111. infoLength = 0;
  112. }
  113. if (hasFile) file << str() << std::flush;
  114. str("");
  115. cs.unlock();
  116. return 0;
  117. }
  118. };
  119. int main()
  120. {
  121. Framework::initFramework();
  122. initializeBlockTypes();
  123. initializeItemTypes();
  124. initializeEntityTypes();
  125. initializeDimensions();
  126. initializeMultiblockTypes();
  127. #ifndef _WINDOWS
  128. struct rlimit core_limits;
  129. core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY;
  130. setrlimit(RLIMIT_CORE, &core_limits);
  131. #endif
  132. Zeit* z = getZeit();
  133. Text* pfad = new Text("log/");
  134. pfad->append(z->getZeit("y-m-d_h-i-s.log"));
  135. z->release();
  136. DateiPfadErstellen(pfad->getText());
  137. std::ofstream file;
  138. std::streambuf* sbuf = std::cout.rdbuf();
  139. #ifndef _DEBUG
  140. file.open(pfad->getText());
  141. std::ostream newCout(sbuf);
  142. DuplicatingStreamBuf duplicator(newCout, file);
  143. std::cout.rdbuf(&duplicator);
  144. #else
  145. std::ostream newCout(sbuf);
  146. DuplicatingStreamBuf duplicator(newCout);
  147. std::cout.rdbuf(&duplicator);
  148. #endif
  149. pfad->release();
  150. std::cout << "Starting...\n";
  151. std::cout << "Loading config file fcInit.ini ...\n";
  152. InitDatei* dat = new InitDatei("fcInit.ini");
  153. if (!dat->laden())
  154. {
  155. std::cout << "error: Datei konnte nicht gelesen werden. Das Programm "
  156. "wird geschlossen.\n";
  157. dat->release();
  158. #ifndef _DEBUG
  159. file.close();
  160. #endif
  161. std::cout.rdbuf(sbuf);
  162. exit(1);
  163. }
  164. const char* wichtig[]
  165. = {"SSLPort", "SSLCert", "SSLKey", "SSLPasswort", "Port"};
  166. for (const char* w : wichtig)
  167. {
  168. if (!dat->wertExistiert(w))
  169. {
  170. std::cout << "error: The value '" << w
  171. << "' was not specified. The Server can not start.\n";
  172. dat->release();
  173. file.close();
  174. std::cout.rdbuf(sbuf);
  175. exit(1);
  176. }
  177. }
  178. mserver = new FactoryCraftServer(dat);
  179. std::atexit(exit);
  180. signal(SIGTERM, exit);
  181. signal(SIGSEGV, exit);
  182. signal(SIGILL, exit);
  183. signal(SIGABRT, exit);
  184. signal(SIGFPE, exit);
  185. signal(SIGINT, exit);
  186. new Framework::AsynchronCall("Commander", []() {
  187. while (mserver)
  188. {
  189. std::string line;
  190. std::getline(std::cin, line);
  191. if (!mserver) return;
  192. std::cout << std::flush << "\033[1A"
  193. << "\x1b[2K"
  194. << "\x1b[0G" << line << "\n\033[1A\033[s" << std::flush;
  195. if (Text(line.c_str()) == Text("exit"))
  196. {
  197. std::cout << "The server will be terminated and the game "
  198. "progress will be saved.\n";
  199. mserver->close();
  200. return;
  201. }
  202. else if (Game::INSTANCE)
  203. {
  204. Game::INSTANCE->zChat()->zCommandExecutor()->execute(
  205. line.c_str(), 0);
  206. }
  207. }
  208. });
  209. std::cout << "The Server is now running.\n";
  210. mserver->run();
  211. exited = 1;
  212. mserver->release();
  213. mserver = 0;
  214. if (Game::INSTANCE)
  215. {
  216. Game* tmp = Game::INSTANCE;
  217. tmp->requestStop();
  218. tmp->warteAufThread(100000000);
  219. tmp->release();
  220. Game::INSTANCE = 0;
  221. }
  222. dat->release();
  223. std::cout << "The server was shut down successfully.\n" << std::flush;
  224. #ifndef _DEBUG
  225. file.close();
  226. #endif
  227. std::cout.rdbuf(sbuf);
  228. Framework::releaseFramework();
  229. return 0;
  230. }