Start.cpp 6.7 KB

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