Add internal command interpretation
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
6
src/messages/StopCommandInternal.cpp
Normal file
6
src/messages/StopCommandInternal.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
void StopCommandInternal::execute(GameServer *server)
|
||||||
|
{
|
||||||
|
server->m_running = false;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/messages/TestCommandInternal.cpp
Normal file
8
src/messages/TestCommandInternal.cpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void TestCommandInternal::execute(GameServer *server)
|
||||||
|
{
|
||||||
|
std::cout << "Internal testcommand launched!" << std::endl;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user