123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include <iostream>
- #include <cstring>
- #include <chrono>
- #include <mutex>
- #include <thread>
- #include <vector>
- #include <poll.h>
- #include <readline/readline.h>
- #include <readline/history.h>
- #include <unistd.h>
- #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<std::string> 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<std::mutex> lg(comandQueueMutex);
- commandQueue.push_back(command);
- }
- free(test);
- }
- }
- static void handleCommandQueue()
- {
- std::lock_guard<std::mutex> 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();
- }
|