Add internal command interpretation

This commit is contained in:
Julian Nießner
2019-06-02 17:52:15 +02:00
parent 8ad1c7219d
commit 84beaf7fd6
9 changed files with 128 additions and 20 deletions

View File

@@ -1,6 +1,12 @@
//std
#include <signal.h> #include <signal.h>
#include <iostream> #include <iostream>
//thread
#include <atomic>
#include <thread>
// Vendor // Vendor
#include <yojimbo.h> #include <yojimbo.h>
@@ -18,7 +24,22 @@ static GameServer *serv;
void interrupt_handler(int /*dummy*/) void interrupt_handler(int /*dummy*/)
{ {
serv->m_running = false; serv->dispatchCommand("stop");
}
void ReadCin(std::atomic<bool> &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[]) int main(int argc, char *argv[])
@@ -29,12 +50,13 @@ int main(int argc, char *argv[])
DWORD prev_mode; DWORD prev_mode;
hInput = GetStdHandle(STD_INPUT_HANDLE); hInput = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hInput, &prev_mode); GetConsoleMode(hInput, &prev_mode);
SetConsoleMode(hInput, prev_mode & ENABLE_EXTENDED_FLAGS); prev_mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hInput, prev_mode);
#endif #endif
if (!InitializeYojimbo()) if (!InitializeYojimbo())
{ {
printf("error: failed to initialize Yojimbo!\n"); std::cout << "error: failed to initialize Yojimbo!" << std::endl;
;
return 1; return 1;
} }
yojimbo_log_level(YOJIMBO_LOG_LEVEL_INFO); 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); yojimbo::Address addr(127, 0, 0, 1, 9999);
GameServer server(addr); GameServer server(addr);
serv = &server; //For interrupt serv = &server; //For interrupt
std::atomic<bool> run(true);
std::thread cinThread(ReadCin, std::ref(run));
server.Run(); server.Run();
run.store(false);
cinThread.join();
ShutdownYojimbo(); ShutdownYojimbo();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@@ -5,7 +5,6 @@
#include <memory> #include <memory>
//own //own
#include "messages/Command.h"
#include "core/Components.h" #include "core/Components.h"
using namespace yojimbo; using namespace yojimbo;
@@ -86,12 +85,32 @@ void GameServer::Update(float dt)
ProcessMessages(); ProcessMessages();
// ... process client inputs ... // ... 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> command_ptr = std::move(commandQueue.front());
commandQueue.pop();
command_ptr->execute(this);
}
this->m_commandQueueMutex.unlock();
// ... update game ... // ... update game ...
// ... send game state to clients ... // ... send game state to clients ...
m_server.SendPackets(); m_server.SendPackets();
} }
void GameServer::dispatchCommand(std::string commandStr) //thread safe
{
std::unique_ptr<Command> 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() void GameServer::ProcessMessages()
{ {
for (int i = 0; i < MAX_PLAYERS; i++) for (int i = 0; i < MAX_PLAYERS; i++)
@@ -106,7 +125,9 @@ void GameServer::ProcessMessages()
std::unique_ptr<Command> command(Command::create(i, message)); std::unique_ptr<Command> command(Command::create(i, message));
if (command) if (command)
{ {
command->execute(this); this->m_commandQueueMutex.lock();
this->commandQueue.push(std::move(command));
this->m_commandQueueMutex.unlock();
} }
m_server.ReleaseMessage(i, message); m_server.ReleaseMessage(i, message);
message = m_server.ReceiveMessage(i, j); message = m_server.ReceiveMessage(i, j);

View File

@@ -4,17 +4,22 @@
//Std //Std
#include <string> #include <string>
#include <map> #include <map>
#include <mutex>
#include <queue>
//Vendor //Vendor
#include <yojimbo.h> #include <yojimbo.h>
#include <entityx/entityx.h> #include <entityx/entityx.h>
class GameServer;
//Own //Own
#include "Shared.h" #include "Shared.h"
#include "messages/Command.h"
static const int MAX_PLAYERS = 64; static const int MAX_PLAYERS = 64;
class GameServer;
class ServerAdapter : public SharedAdapter class ServerAdapter : public SharedAdapter
{ {
@@ -37,20 +42,21 @@ public:
void ClientConnected(int clientIndex); void ClientConnected(int clientIndex);
void ClientDisconnected(int clientIndex); void ClientDisconnected(int clientIndex);
void ProcessCommand(std::string command); void dispatchCommand(std::string commandStr); //thread safe
void ProcessMessages(); void ProcessMessages();
void ProcessMessage(int clientIndex, yojimbo::Message *message);
void Run(); void Run();
void Update(float dt); void Update(float dt);
bool m_running; bool m_running;
std::queue<std::unique_ptr<Command>> commandQueue;
entityx::EntityX ex; entityx::EntityX ex;
std::map<int, entityx::Entity> serverToEntityX; std::map<int, entityx::Entity> serverToEntityX;
private: private:
double m_time; double m_time;
std::mutex m_commandQueueMutex;
GameConnectionConfig m_connectionConfig; GameConnectionConfig m_connectionConfig;
ServerAdapter m_adapter; ServerAdapter m_adapter;

View File

@@ -2,6 +2,7 @@
#include "../Shared.h" #include "../Shared.h"
#include <iostream> #include <iostream>
#include <sstream>
Command *Command::create(int clientIndex, yojimbo::Message *message) Command *Command::create(int clientIndex, yojimbo::Message *message)
{ {
@@ -9,13 +10,28 @@ Command *Command::create(int clientIndex, yojimbo::Message *message)
{ {
case (int)GameMessageType::TEST: case (int)GameMessageType::TEST:
return new TestCommand(clientIndex, message); return new TestCommand(clientIndex, message);
break;
case (int)GameMessageType::SETNAME: case (int)GameMessageType::SETNAME:
return new SetNameCommand(clientIndex, message); return new SetNameCommand(clientIndex, message);
break;
default: default:
std::cout << "Unknown message type received!" << std::endl; std::cout << "Unknown message type received!" << std::endl;
return nullptr; 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;
} }

View File

@@ -2,6 +2,8 @@
//Vendor //Vendor
#include <yojimbo.h> #include <yojimbo.h>
class Command;
#include "../GameServer.h" #include "../GameServer.h"
// ---- Interface: // ---- Interface:
@@ -12,33 +14,53 @@ public:
// Create Commands from Network messages (Limited list) // Create Commands from Network messages (Limited list)
static Command *create(int clientIndex, yojimbo::Message *message); static Command *create(int clientIndex, yojimbo::Message *message);
// Create Commands from Strings (Limited list) // Create Commands from Strings (Limited list)
static Command *create(std::string);
virtual void execute(GameServer *server) = 0; virtual void execute(GameServer *server) = 0;
}; };
// --- implemented Classes: // --- Classes Network:
class TestCommand : public Command class TestCommand : public Command
{ {
public: public:
TestCommand(int clientIndex, yojimbo::Message *message) 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; virtual void execute(GameServer *server) override;
private: private:
int m_clientIndex; int m_clientIndex;
TestMessage *m_message; int m_data;
}; };
class SetNameCommand : public Command class SetNameCommand : public Command
{ {
public: public:
SetNameCommand(int clientIndex, yojimbo::Message *message) 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; virtual void execute(GameServer *server) override;
private: private:
int m_clientIndex; 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;
}; };

View File

@@ -8,7 +8,7 @@ void SetNameCommand::execute(GameServer *server)
entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>(); entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>();
if (playerproperties) 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;
} }

View File

@@ -0,0 +1,6 @@
#include "Command.h"
void StopCommandInternal::execute(GameServer *server)
{
server->m_running = false;
}

View File

@@ -8,5 +8,5 @@ void TestCommand::execute(GameServer *server)
entityx::Entity entity = server->serverToEntityX.at(m_clientIndex); entityx::Entity entity = server->serverToEntityX.at(m_clientIndex);
entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>(); entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>();
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;
} }

View File

@@ -0,0 +1,8 @@
#include "Command.h"
#include <iostream>
void TestCommandInternal::execute(GameServer *server)
{
std::cout << "Internal testcommand launched!" << std::endl;
}