Start.cpp 6.7 KB

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