Start.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. initializeBlockTypes();
  134. initializeItemTypes();
  135. initializeEntityTypes();
  136. initializeDimensions();
  137. initializeMultiblockTypes();
  138. #ifndef _WINDOWS
  139. struct rlimit core_limits;
  140. core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY;
  141. setrlimit(RLIMIT_CORE, &core_limits);
  142. #endif
  143. Zeit* z = getZeit();
  144. Text* pfad = new Text("log/");
  145. pfad->append(z->getZeit("y-m-d_h-i-s.log"));
  146. z->release();
  147. DateiPfadErstellen(pfad->getText());
  148. std::ofstream file;
  149. std::streambuf* sbuf = std::cout.rdbuf();
  150. // #ifndef _DEBUG
  151. file.open(pfad->getText());
  152. std::ostream newCout(sbuf);
  153. DuplicatingStreamBuf duplicator(newCout, file);
  154. std::cout.rdbuf(&duplicator);
  155. /* #else
  156. std::ostream newCout(sbuf);
  157. DuplicatingStreamBuf duplicator(newCout);
  158. std::cout.rdbuf(&duplicator);
  159. #endif */
  160. pfad->release();
  161. std::cout << "Starting...\n";
  162. std::cout << "Loading config file fcInit.ini ...\n";
  163. InitDatei* dat = new InitDatei("fcInit.ini");
  164. if (!dat->laden())
  165. {
  166. std::cout << "error: Datei konnte nicht gelesen werden. Das Programm "
  167. "wird geschlossen.\n";
  168. dat->release();
  169. //#ifndef _DEBUG
  170. file.close();
  171. //#endif
  172. std::cout.rdbuf(sbuf);
  173. exit(1);
  174. }
  175. const char* wichtig[]
  176. = {"SSLPort", "SSLCert", "SSLKey", "SSLPasswort", "Port"};
  177. for (const char* w : wichtig)
  178. {
  179. if (!dat->wertExistiert(w))
  180. {
  181. std::cout << "error: The value '" << w
  182. << "' was not specified. The Server can not start.\n";
  183. dat->release();
  184. file.close();
  185. std::cout.rdbuf(sbuf);
  186. exit(1);
  187. }
  188. }
  189. mserver = new FactoryCraftServer(dat);
  190. std::atexit(exit);
  191. signal(SIGTERM, exit);
  192. signal(SIGSEGV, exit);
  193. signal(SIGILL, exit);
  194. signal(SIGABRT, exit);
  195. signal(SIGFPE, exit);
  196. signal(SIGINT, exit);
  197. new Framework::AsynchronCall("Commander", []() {
  198. while (mserver)
  199. {
  200. std::string line;
  201. std::getline(std::cin, line);
  202. if (!mserver) return;
  203. std::cout << std::flush << "\033[1A"
  204. << "\x1b[2K"
  205. << "\x1b[0G" << line << "\n\033[1A\033[s" << std::flush;
  206. if (Text(line.c_str()) == Text("exit"))
  207. {
  208. std::cout << "The server will be terminated and the game "
  209. "progress will be saved.\n";
  210. mserver->close();
  211. return;
  212. }
  213. else if (Game::INSTANCE)
  214. {
  215. Game::INSTANCE->zChat()->zCommandExecutor()->execute(
  216. line.c_str(), 0);
  217. }
  218. }
  219. });
  220. std::cout << "The Server is now running.\n";
  221. mserver->run();
  222. exited = 1;
  223. mserver->release();
  224. mserver = 0;
  225. if (Game::INSTANCE)
  226. {
  227. Game* tmp = Game::INSTANCE;
  228. tmp->requestStop();
  229. tmp->warteAufThread(100000000);
  230. tmp->release();
  231. Game::INSTANCE = 0;
  232. }
  233. dat->release();
  234. std::cout << "The server was shut down successfully.\n" << std::flush;
  235. //#ifndef _DEBUG
  236. file.close();
  237. //#endif
  238. std::cout.rdbuf(sbuf);
  239. Framework::releaseFramework();
  240. return 0;
  241. }