From 84beaf7fd63050b25a3d614b334ae7b07306995f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Nie=C3=9Fner?= Date: Sun, 2 Jun 2019 17:52:15 +0200 Subject: [PATCH] Add internal command interpretation --- src/DarkRP2DDedicatedServer.cpp | 37 +++++++++++++++++++++++++--- src/GameServer.cpp | 25 +++++++++++++++++-- src/GameServer.h | 12 ++++++--- src/messages/Command.cpp | 22 ++++++++++++++--- src/messages/Command.h | 32 ++++++++++++++++++++---- src/messages/SetNameCommand.cpp | 4 +-- src/messages/StopCommandInternal.cpp | 6 +++++ src/messages/TestCommand.cpp | 2 +- src/messages/TestCommandInternal.cpp | 8 ++++++ 9 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 src/messages/StopCommandInternal.cpp create mode 100644 src/messages/TestCommandInternal.cpp diff --git a/src/DarkRP2DDedicatedServer.cpp b/src/DarkRP2DDedicatedServer.cpp index 9d6735f..9641e1f 100644 --- a/src/DarkRP2DDedicatedServer.cpp +++ b/src/DarkRP2DDedicatedServer.cpp @@ -1,6 +1,12 @@ + +//std #include #include +//thread +#include +#include + // Vendor #include @@ -18,7 +24,22 @@ static GameServer *serv; void interrupt_handler(int /*dummy*/) { - serv->m_running = false; + serv->dispatchCommand("stop"); +} + +void ReadCin(std::atomic &run) +{ + std::string buffer; + + while (run.load()) + { + std::getline(std::cin, buffer); + serv->dispatchCommand(buffer); + if (buffer == "stop") + { + run.store(false); + } + } } int main(int argc, char *argv[]) @@ -29,12 +50,13 @@ int main(int argc, char *argv[]) DWORD prev_mode; hInput = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hInput, &prev_mode); - SetConsoleMode(hInput, prev_mode & ENABLE_EXTENDED_FLAGS); + prev_mode &= ~ENABLE_QUICK_EDIT_MODE; + SetConsoleMode(hInput, prev_mode); #endif - if (!InitializeYojimbo()) { - printf("error: failed to initialize Yojimbo!\n"); + std::cout << "error: failed to initialize Yojimbo!" << std::endl; + ; return 1; } yojimbo_log_level(YOJIMBO_LOG_LEVEL_INFO); @@ -45,8 +67,15 @@ int main(int argc, char *argv[]) yojimbo::Address addr(127, 0, 0, 1, 9999); GameServer server(addr); serv = &server; //For interrupt + + std::atomic run(true); + std::thread cinThread(ReadCin, std::ref(run)); + server.Run(); + run.store(false); + cinThread.join(); + ShutdownYojimbo(); return EXIT_SUCCESS; } diff --git a/src/GameServer.cpp b/src/GameServer.cpp index 0ccefaf..cc52487 100644 --- a/src/GameServer.cpp +++ b/src/GameServer.cpp @@ -5,7 +5,6 @@ #include //own -#include "messages/Command.h" #include "core/Components.h" using namespace yojimbo; @@ -86,12 +85,32 @@ void GameServer::Update(float dt) ProcessMessages(); // ... process client inputs ... + this->m_commandQueueMutex.lock(); //As long as the server is processing the que the adding is blocked + while (!this->commandQueue.empty()) + { + std::unique_ptr command_ptr = std::move(commandQueue.front()); + commandQueue.pop(); + command_ptr->execute(this); + } + this->m_commandQueueMutex.unlock(); + // ... update game ... // ... send game state to clients ... m_server.SendPackets(); } +void GameServer::dispatchCommand(std::string commandStr) //thread safe +{ + std::unique_ptr u_ptr(Command::create(commandStr)); + if (u_ptr) + { + this->m_commandQueueMutex.lock(); + this->commandQueue.push(std::move(u_ptr)); + this->m_commandQueueMutex.unlock(); + } +} + void GameServer::ProcessMessages() { for (int i = 0; i < MAX_PLAYERS; i++) @@ -106,7 +125,9 @@ void GameServer::ProcessMessages() std::unique_ptr command(Command::create(i, message)); if (command) { - command->execute(this); + this->m_commandQueueMutex.lock(); + this->commandQueue.push(std::move(command)); + this->m_commandQueueMutex.unlock(); } m_server.ReleaseMessage(i, message); message = m_server.ReceiveMessage(i, j); diff --git a/src/GameServer.h b/src/GameServer.h index b920cb7..b17315f 100644 --- a/src/GameServer.h +++ b/src/GameServer.h @@ -4,17 +4,22 @@ //Std #include #include +#include +#include //Vendor #include #include +class GameServer; + //Own #include "Shared.h" +#include "messages/Command.h" static const int MAX_PLAYERS = 64; -class GameServer; + class ServerAdapter : public SharedAdapter { @@ -37,20 +42,21 @@ public: void ClientConnected(int clientIndex); void ClientDisconnected(int clientIndex); - void ProcessCommand(std::string command); + void dispatchCommand(std::string commandStr); //thread safe void ProcessMessages(); - void ProcessMessage(int clientIndex, yojimbo::Message *message); void Run(); void Update(float dt); bool m_running; + std::queue> commandQueue; entityx::EntityX ex; std::map serverToEntityX; private: double m_time; + std::mutex m_commandQueueMutex; GameConnectionConfig m_connectionConfig; ServerAdapter m_adapter; diff --git a/src/messages/Command.cpp b/src/messages/Command.cpp index 0c9be88..e0120ce 100644 --- a/src/messages/Command.cpp +++ b/src/messages/Command.cpp @@ -2,6 +2,7 @@ #include "../Shared.h" #include +#include Command *Command::create(int clientIndex, yojimbo::Message *message) { @@ -9,13 +10,28 @@ Command *Command::create(int clientIndex, yojimbo::Message *message) { case (int)GameMessageType::TEST: return new TestCommand(clientIndex, message); - break; case (int)GameMessageType::SETNAME: return new SetNameCommand(clientIndex, message); - break; default: std::cout << "Unknown message type received!" << std::endl; return nullptr; - break; } +} + +Command *Command::create(std::string command) +{ + std::stringstream ss(command); + std::string token; + ss >> + token; + if (token == "stop") + { + return new StopCommandInternal(); + } + else if (token == "test") + { + return new TestCommandInternal(); + } + std::cout << "Internal commando don't exists: " << command << std::endl; + return nullptr; } \ No newline at end of file diff --git a/src/messages/Command.h b/src/messages/Command.h index 120151e..8fb41ba 100644 --- a/src/messages/Command.h +++ b/src/messages/Command.h @@ -2,6 +2,8 @@ //Vendor #include + +class Command; #include "../GameServer.h" // ---- Interface: @@ -12,33 +14,53 @@ public: // Create Commands from Network messages (Limited list) static Command *create(int clientIndex, yojimbo::Message *message); // Create Commands from Strings (Limited list) + static Command *create(std::string); + virtual void execute(GameServer *server) = 0; }; -// --- implemented Classes: +// --- Classes Network: class TestCommand : public Command { public: TestCommand(int clientIndex, yojimbo::Message *message) - : m_clientIndex(clientIndex), m_message((TestMessage *)message) {} + : m_clientIndex(clientIndex), + m_data(((TestMessage *)message)->m_data) + {} virtual void execute(GameServer *server) override; private: int m_clientIndex; - TestMessage *m_message; + int m_data; }; class SetNameCommand : public Command { public: SetNameCommand(int clientIndex, yojimbo::Message *message) - : m_clientIndex(clientIndex), m_message((SetNameMessage *)message) {} + : m_clientIndex(clientIndex), + m_name(std::string(((SetNameMessage *)message)->buffer)) + {} virtual void execute(GameServer *server) override; private: int m_clientIndex; - SetNameMessage *m_message; + std::string m_name; +}; + +// --- Classes Internal: + +class TestCommandInternal : public Command +{ +public: + virtual void execute(GameServer *server) override; +}; + +class StopCommandInternal : public Command +{ +public: + virtual void execute(GameServer *server) override; }; \ No newline at end of file diff --git a/src/messages/SetNameCommand.cpp b/src/messages/SetNameCommand.cpp index 9fa62fc..f954473 100644 --- a/src/messages/SetNameCommand.cpp +++ b/src/messages/SetNameCommand.cpp @@ -8,7 +8,7 @@ void SetNameCommand::execute(GameServer *server) entityx::ComponentHandle playerproperties = entity.component(); if (playerproperties) { - playerproperties->name = std::string(m_message->buffer); + playerproperties->name = m_name; } - std::cout << "Entity name changed to " << playerproperties->name << " Buffer content: " << std::string(m_message->buffer) << std::endl; + std::cout << "Entity name changed to " << playerproperties->name << " Buffer content: " << m_name << std::endl; } \ No newline at end of file diff --git a/src/messages/StopCommandInternal.cpp b/src/messages/StopCommandInternal.cpp new file mode 100644 index 0000000..5225d7e --- /dev/null +++ b/src/messages/StopCommandInternal.cpp @@ -0,0 +1,6 @@ +#include "Command.h" + +void StopCommandInternal::execute(GameServer *server) +{ + server->m_running = false; +} diff --git a/src/messages/TestCommand.cpp b/src/messages/TestCommand.cpp index 86e782c..7969f54 100644 --- a/src/messages/TestCommand.cpp +++ b/src/messages/TestCommand.cpp @@ -8,5 +8,5 @@ void TestCommand::execute(GameServer *server) entityx::Entity entity = server->serverToEntityX.at(m_clientIndex); entityx::ComponentHandle playerproperties = entity.component(); - std::cout << "Test message received from client " << playerproperties->name << ":" << m_clientIndex << " with data: " << m_message->m_data << std::endl; + std::cout << "Test message received from client " << playerproperties->name << ":" << m_clientIndex << " with data: " << m_data << std::endl; } diff --git a/src/messages/TestCommandInternal.cpp b/src/messages/TestCommandInternal.cpp new file mode 100644 index 0000000..c8d00a0 --- /dev/null +++ b/src/messages/TestCommandInternal.cpp @@ -0,0 +1,8 @@ +#include "Command.h" + +#include + +void TestCommandInternal::execute(GameServer *server) +{ + std::cout << "Internal testcommand launched!" << std::endl; +} \ No newline at end of file