#include #include #include #include #include #include #include #include #include #include #include "server/GameServer.h" #include "server/network/Server.h" #include "server/commands/ServerCommands.h" #include "server/commands/CommandManager.h" static ServerCommands serverCommands; static const std::chrono::nanoseconds NANOS_PER_TICK = std::chrono::nanoseconds(50000000); static const std::chrono::nanoseconds MIN_NANO_SLEEP = std::chrono::nanoseconds(300000); static std::vector commandQueue; static std::mutex comandQueueMutex; static void init() { rl_bind_key('\t', rl_insert); rl_event_hook = []() { if(!serverCommands.isRunning()) { rl_stuff_char('\n'); } return 0; }; } static void readFromConsole() { while(serverCommands.isRunning()) { char* test = readline("> "); if(test == nullptr) { continue; } std::string command(test); if(command.size() != 0) { add_history(test); std::lock_guard lg(comandQueueMutex); commandQueue.push_back(command); } free(test); } } static void handleCommandQueue() { std::lock_guard lg(comandQueueMutex); for(std::string& s : commandQueue) { CommandManager::execute(serverCommands, s); } commandQueue.clear(); } static void tick() { rl_clear_visible_line(); handleCommandQueue(); std::cout << "tick\n"; rl_forced_update_display(); } static void onFullServerClientConnect(int socket) { Stream answer; answer.write("Sorry, the server is full"); answer.sendToSocket(socket); } static void onClientConnect(int socket) { std::cout << socket << " has connected\n"; Stream answer; answer.write("Welcome to the server."); answer.sendToSocket(socket); } static void onClientPackage(int socket, Stream& in) { std::string s = ""; while(in.hasData()) { char c; in.read(&c, 1); s = c + s; } Stream answer; answer.write(s.data(), s.length()); answer.sendToSocket(socket); } static void onClientDisconnect(int socket) { std::cout << socket << " has disconnected\n"; Stream answer; answer.write("Bye."); answer.sendToSocket(socket); } static void loop() { auto lastTime = std::chrono::steady_clock::now().time_since_epoch(); auto lag = lastTime.zero(); std::thread commandThread = std::thread(readFromConsole); while(serverCommands.isRunning()) { auto time = std::chrono::steady_clock::now().time_since_epoch(); lag += time - lastTime; lastTime = time; while(lag >= NANOS_PER_TICK) { lag -= NANOS_PER_TICK; tick(); } auto waitTime = NANOS_PER_TICK - lag - MIN_NANO_SLEEP; if(waitTime > MIN_NANO_SLEEP) { std::this_thread::sleep_for(waitTime); } } commandThread.join(); } void GameServer::start(u16 port, u16 maxClients) { init(); Server::setFullServerClientConnectFunction(onFullServerClientConnect); Server::setClientConnectFunction(onClientConnect); Server::setClientPackageFunction(onClientPackage); Server::setClientDisconnectFunction(onClientDisconnect); if(!Server::start(port, maxClients)) { return; } loop(); }