server console input
This commit is contained in:
@@ -63,13 +63,16 @@ private:
|
|||||||
std::thread m_Thread;
|
std::thread m_Thread;
|
||||||
bool m_ServerRunning;
|
bool m_ServerRunning;
|
||||||
public:
|
public:
|
||||||
Server(const std::string& worldFilePath);
|
Server();
|
||||||
virtual ~Server();
|
virtual ~Server();
|
||||||
|
|
||||||
bool Start(std::uint16_t port);
|
bool Start(std::uint16_t port, bool blocking);
|
||||||
void Stop(); // force the server to stop
|
void Stop(); // force the server to stop
|
||||||
void Close(); // at the end of a game
|
void Close(); // at the end of a game
|
||||||
|
|
||||||
|
bool LoadMap(const std::string& worldFilePath);
|
||||||
|
bool IsMapLoaded();
|
||||||
|
|
||||||
void RemoveConnexion(std::uint8_t connexionID);
|
void RemoveConnexion(std::uint8_t connexionID);
|
||||||
|
|
||||||
void BroadcastPacket(const protocol::Packet* packet);
|
void BroadcastPacket(const protocol::Packet* packet);
|
||||||
@@ -95,6 +98,7 @@ private:
|
|||||||
void Clean();
|
void Clean();
|
||||||
void StartThread();
|
void StartThread();
|
||||||
void StopThread();
|
void StopThread();
|
||||||
|
void ServerLoop();
|
||||||
void Tick(std::uint64_t delta);
|
void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
void OnPlayerJoin(std::uint8_t id);
|
void OnPlayerJoin(std::uint8_t id);
|
||||||
|
|||||||
@@ -37,11 +37,55 @@ static void DisplayHelp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool StartServer(const std::string& mapPath, std::uint16_t port) {
|
class ConsoleThread {
|
||||||
td::server::Server server {mapPath};
|
private:
|
||||||
return !server.Start(port);
|
td::server::Server& m_Server;
|
||||||
|
std::thread m_Thread;
|
||||||
|
bool m_Running = true;
|
||||||
|
public:
|
||||||
|
ConsoleThread(td::server::Server& server) : m_Server(server) {}
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
m_Thread = std::thread([this](){
|
||||||
|
std::string line;
|
||||||
|
while (m_Running) {
|
||||||
|
getline(std::cin, line);
|
||||||
|
|
||||||
|
if (line == "stop") {
|
||||||
|
m_Server.Stop();
|
||||||
|
} else if (line == "help") {
|
||||||
|
LOG("use \"stop\" to stop the server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stop() {
|
||||||
|
m_Running = false;
|
||||||
|
m_Thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ConsoleThread() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void StartServer(const std::string& mapPath, std::uint16_t port) {
|
||||||
|
td::server::Server server;
|
||||||
|
if (!server.LoadMap(mapPath)) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleThread consoleThread{ server };
|
||||||
|
consoleThread.Start();
|
||||||
|
|
||||||
|
if (!server.Start(port, true)) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Press Enter to coninue ...");
|
||||||
|
consoleThread.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
extern "C"
|
extern "C"
|
||||||
#endif
|
#endif
|
||||||
@@ -89,5 +133,7 @@ int main(int argc, const char* args[]) {
|
|||||||
mapFilePath = arg;
|
mapFilePath = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StartServer(mapFilePath, port);
|
StartServer(mapFilePath, port);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,9 @@ void MainMenu::Render() {
|
|||||||
bool MainMenu::StartServer() {
|
bool MainMenu::StartServer() {
|
||||||
if (m_WorldFilePath.empty())
|
if (m_WorldFilePath.empty())
|
||||||
return false;
|
return false;
|
||||||
m_Server = std::make_unique<td::server::Server>(m_WorldFilePath);
|
m_Server = std::make_unique<td::server::Server>();
|
||||||
if (!m_Server->Start(m_ServerPort)) {
|
m_Server->LoadMap(m_WorldFilePath);
|
||||||
|
if (!m_Server->Start(m_ServerPort, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace server {
|
namespace server {
|
||||||
|
|
||||||
Server::Server(const std::string& worldFilePath) : m_ServerRunning(false) {
|
Server::Server() : m_ServerRunning(false) {
|
||||||
m_Game.GetWorld()->LoadMapFromFile(worldFilePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server() {
|
||||||
@@ -19,24 +19,36 @@ Server::~Server() {
|
|||||||
m_Thread.join();
|
m_Thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::LoadMap(const std::string& worldFilePath) {
|
||||||
|
return m_Game.GetWorld()->LoadMapFromFile(worldFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::IsMapLoaded() {
|
||||||
|
return !m_Game.GetWorld()->GetTilePalette().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::ServerLoop() {
|
||||||
|
std::uint64_t lastTime = td::utils::GetTime();
|
||||||
|
while (m_ServerRunning) {
|
||||||
|
std::uint64_t time = td::utils::GetTime();
|
||||||
|
|
||||||
|
std::uint64_t delta = time - lastTime;
|
||||||
|
|
||||||
|
if (delta >= SERVER_TICK) {
|
||||||
|
Tick(delta);
|
||||||
|
lastTime = td::utils::GetTime();
|
||||||
|
m_TickCounter.SetMSPT(lastTime - time);
|
||||||
|
std::uint64_t sleepTime = SERVER_TICK - (delta - SERVER_TICK);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Clean();
|
||||||
|
}
|
||||||
|
|
||||||
void Server::StartThread() {
|
void Server::StartThread() {
|
||||||
m_Thread = std::thread([this]() {
|
m_Thread = std::thread([this]() {
|
||||||
std::uint64_t lastTime = td::utils::GetTime();
|
ServerLoop();
|
||||||
while (m_ServerRunning) {
|
|
||||||
std::uint64_t time = td::utils::GetTime();
|
|
||||||
|
|
||||||
std::uint64_t delta = time - lastTime;
|
|
||||||
|
|
||||||
if (delta >= SERVER_TICK) {
|
|
||||||
Tick(delta);
|
|
||||||
lastTime = td::utils::GetTime();
|
|
||||||
m_TickCounter.SetMSPT(lastTime - time);
|
|
||||||
std::uint64_t sleepTime = SERVER_TICK - (delta - SERVER_TICK);
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Clean();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +60,11 @@ void Server::StopThread() {
|
|||||||
m_ServerRunning = false;
|
m_ServerRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::Start(std::uint16_t port) {
|
bool Server::Start(std::uint16_t port, bool blocking) {
|
||||||
|
if (!IsMapLoaded()) {
|
||||||
|
utils::LOGE(utils::format("No map loaded !"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!m_Listener.Listen(port, 10)) {
|
if (!m_Listener.Listen(port, 10)) {
|
||||||
utils::LOGE(utils::format("Failed to bind port %u !", port));
|
utils::LOGE(utils::format("Failed to bind port %u !", port));
|
||||||
return false;
|
return false;
|
||||||
@@ -60,7 +76,11 @@ bool Server::Start(std::uint16_t port) {
|
|||||||
utils::LOG(utils::format("Server started at port %u !", port));
|
utils::LOG(utils::format("Server started at port %u !", port));
|
||||||
m_TickCounter.Reset();
|
m_TickCounter.Reset();
|
||||||
m_ServerRunning = true;
|
m_ServerRunning = true;
|
||||||
StartThread();
|
if (blocking) {
|
||||||
|
ServerLoop();
|
||||||
|
} else {
|
||||||
|
StartThread();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +165,11 @@ void Server::OnPlayerJoin(std::uint8_t id) {
|
|||||||
void Server::OnPlayerLeave(std::uint8_t id) {
|
void Server::OnPlayerLeave(std::uint8_t id) {
|
||||||
protocol::PlayerLeavePacket packet(id);
|
protocol::PlayerLeavePacket packet(id);
|
||||||
BroadcastPacket(&packet);
|
BroadcastPacket(&packet);
|
||||||
|
|
||||||
|
if (GetPlayers().empty()) {
|
||||||
|
utils::LOG("All players left. Stopping server ...");
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
Reference in New Issue
Block a user