Added logic for sending input from Client to Server.
Fixed so that snapshots set their parent correctly. Will get problems if we have more components than unsigned int max size, but that was already a problem. Client now maps Entitys received from server with local Entitys by mapping their EntityIDs.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <glm/common.hpp>
|
#include <glm/common.hpp>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
@@ -45,6 +46,10 @@ private:
|
|||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
int m_PlayerID = -1;
|
int m_PlayerID = -1;
|
||||||
|
|
||||||
|
// Server Client Lookup map
|
||||||
|
// Assumes that root node for client and server is EntityID 0.
|
||||||
|
std::unordered_map<EntityID, EntityID> m_ServerToClientMap;
|
||||||
|
|
||||||
// Network logic
|
// Network logic
|
||||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
||||||
SnapshotDefinitions m_NextSnapshot;
|
SnapshotDefinitions m_NextSnapshot;
|
||||||
@@ -56,7 +61,7 @@ private:
|
|||||||
|
|
||||||
// Private member functions
|
// Private member functions
|
||||||
void readFromServer();
|
void readFromServer();
|
||||||
void sendSnapshotToServer();
|
void sendInputEvents();
|
||||||
int receive(char* data, size_t length);
|
int receive(char* data, size_t length);
|
||||||
void send(Packet& packet);
|
void send(Packet& packet);
|
||||||
void connect();
|
void connect();
|
||||||
@@ -73,7 +78,7 @@ private:
|
|||||||
void identifyPacketLoss();
|
void identifyPacketLoss();
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
EntityID createPlayer();
|
EntityID createPlayer();
|
||||||
|
bool hasMappedEntity(EntityID entityID);
|
||||||
// Events
|
// Events
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
EventRelay<Client, Events::InputCommand> m_EInputCommand;
|
EventRelay<Client, Events::InputCommand> m_EInputCommand;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Core/World.h"
|
#include "Core/World.h"
|
||||||
#include "Core/EventBroker.h"
|
#include "Core/EventBroker.h"
|
||||||
#include "Network/Network.h"
|
#include "Network/Network.h"
|
||||||
|
#include "Input/EInputCommand.h"
|
||||||
|
|
||||||
class Server : public Network
|
class Server : public Network
|
||||||
{
|
{
|
||||||
@@ -72,7 +73,6 @@ private:
|
|||||||
void parseDisconnect();
|
void parseDisconnect();
|
||||||
void parseClientPing();
|
void parseClientPing();
|
||||||
void parseServerPing();
|
void parseServerPing();
|
||||||
void parseSnapshot(Packet& packet);
|
|
||||||
void identifyPacketLoss();
|
void identifyPacketLoss();
|
||||||
EntityID createPlayer();
|
EntityID createPlayer();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ using namespace boost::asio::ip;
|
|||||||
|
|
||||||
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
||||||
{
|
{
|
||||||
|
// Asumes root node is EntityID 0
|
||||||
|
m_ServerToClientMap.insert(std::make_pair(0, 0));
|
||||||
// Default is local host
|
// Default is local host
|
||||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||||
int port = config->Get<int>("Networking.Port", 13);
|
int port = config->Get<int>("Networking.Port", 13);
|
||||||
@@ -16,8 +18,7 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
|
|
||||||
void Client::Start(World* world, EventBroker* eventBroker)
|
void Client::Start(World* world, EventBroker* eventBroker)
|
||||||
{
|
{
|
||||||
@@ -55,7 +56,7 @@ void Client::readFromServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::sendSnapshotToServer()
|
void Client::sendInputEvents()
|
||||||
{
|
{
|
||||||
// Reset previous key state in snapshot.
|
// Reset previous key state in snapshot.
|
||||||
m_NextSnapshot.InputForward = "";
|
m_NextSnapshot.InputForward = "";
|
||||||
@@ -187,9 +188,16 @@ void Client::parseSnapshot(Packet& packet)
|
|||||||
{
|
{
|
||||||
std::string componentType = packet.ReadString();
|
std::string componentType = packet.ReadString();
|
||||||
while (packet.DataReadSize() < packet.Size()) {
|
while (packet.DataReadSize() < packet.Size()) {
|
||||||
EntityID entityID = packet.ReadPrimitive<EntityID>();
|
// Components EntityID
|
||||||
|
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
|
||||||
|
// Parents EntityID
|
||||||
|
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
|
||||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||||
if (m_World->ValidEntity(entityID)) {
|
// Check if the received EntityID is mapped to one of our local EntityIDs
|
||||||
|
if (hasMappedEntity(receivedEntityID)) {
|
||||||
|
// Get the local EntityID
|
||||||
|
EntityID entityID = m_ServerToClientMap.at(receivedEntityID);
|
||||||
|
// Check if the component exists
|
||||||
if (m_World->HasComponent(entityID, componentType)) {
|
if (m_World->HasComponent(entityID, componentType)) {
|
||||||
// If the entity and the component exists update it
|
// If the entity and the component exists update it
|
||||||
updateFields(packet, componentInfo, entityID, componentType);
|
updateFields(packet, componentInfo, entityID, componentType);
|
||||||
@@ -202,11 +210,12 @@ void Client::parseSnapshot(Packet& packet)
|
|||||||
}
|
}
|
||||||
// If the entity dosent exist nor the component
|
// If the entity dosent exist nor the component
|
||||||
} else {
|
} else {
|
||||||
//Create Entity
|
// Create Entity
|
||||||
// If entity dosen't exist
|
// If entity dosen't exist
|
||||||
EntityID newEntityID = m_World->CreateEntity();
|
EntityID newEntityID = m_World->CreateEntity();
|
||||||
|
m_ServerToClientMap.insert(std::make_pair(receivedEntityID, newEntityID));
|
||||||
// Check if EntityIDs are out of sync
|
// Check if EntityIDs are out of sync
|
||||||
if (newEntityID != entityID) {
|
if (newEntityID != receivedEntityID) {
|
||||||
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
|
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
|
||||||
same as the one sent by server (EntityIDs are out of sync)");
|
same as the one sent by server (EntityIDs are out of sync)");
|
||||||
}
|
}
|
||||||
@@ -215,6 +224,21 @@ void Client::parseSnapshot(Packet& packet)
|
|||||||
// Copy data to newly created component
|
// Copy data to newly created component
|
||||||
updateFields(packet, componentInfo, newEntityID, componentType);
|
updateFields(packet, componentInfo, newEntityID, componentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parent Logic
|
||||||
|
// Don't need to check if receivedEntityID is mapped. (It should have been set)
|
||||||
|
if (receivedParentEntityID != std::numeric_limits<EntityID>::max()) {
|
||||||
|
if (hasMappedEntity(receivedParentEntityID)) {
|
||||||
|
m_World->SetParent(m_ServerToClientMap.at(receivedEntityID), m_ServerToClientMap.at(receivedParentEntityID));
|
||||||
|
// If Parent dosen't exist create one and map receivedParentEntityID to it.
|
||||||
|
} else {
|
||||||
|
// Create the new parent and add it to map
|
||||||
|
EntityID newParentEntityID = m_World->CreateEntity();
|
||||||
|
m_ServerToClientMap.insert(std::make_pair(receivedParentEntityID, newParentEntityID));
|
||||||
|
// Set the newly created Entity as parent.
|
||||||
|
m_World->SetParent(m_ServerToClientMap.at(receivedEntityID), newParentEntityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,40 +297,22 @@ void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize)
|
|||||||
|
|
||||||
bool Client::OnInputCommand(const Events::InputCommand & e)
|
bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||||
{
|
{
|
||||||
if (isConnected()) {
|
if (e.Command == "Forward" || e.Command == "Right") {
|
||||||
ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
|
Packet packet(MessageType::Event, m_SendPacketID);
|
||||||
if (e.Command == "Forward") {
|
packet.WriteString(e.Command);
|
||||||
if (e.Value > 0) {
|
packet.WritePrimitive(e.PlayerID);
|
||||||
(bool&)player["Forward"] = true;
|
packet.WritePrimitive(e.Value);
|
||||||
(bool&)player["Back"] = false;
|
send(packet);
|
||||||
} else if (e.Value < 0) {
|
LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
(bool&)player["Back"] = true;
|
return true;
|
||||||
(bool&)player["Forward"] = false;
|
} else if (e.Command == "ConnectToServer") { // Connect for now
|
||||||
} else {
|
|
||||||
(bool&)player["Forward"] = false;
|
|
||||||
(bool&)player["Back"] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.Command == "Right") {
|
|
||||||
if (e.Value > 0) {
|
|
||||||
(bool&)player["Right"] = true;
|
|
||||||
(bool&)player["Left"] = false;
|
|
||||||
} else if (e.Value < 0) {
|
|
||||||
(bool&)player["Left"] = true;
|
|
||||||
(bool&)player["Right"] = false;
|
|
||||||
} else {
|
|
||||||
(bool&)player["Left"] = false;
|
|
||||||
(bool&)player["Right"] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.Command == "ConnectToServer") { // Connect for now
|
|
||||||
connect();
|
connect();
|
||||||
|
LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::identifyPacketLoss()
|
void Client::identifyPacketLoss()
|
||||||
{
|
{
|
||||||
// if no packets lost, difference should be equal to 1
|
// if no packets lost, difference should be equal to 1
|
||||||
@@ -335,3 +341,8 @@ EntityID Client::createPlayer()
|
|||||||
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
||||||
return entityID;
|
return entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::hasMappedEntity(EntityID entityID)
|
||||||
|
{
|
||||||
|
return m_ServerToClientMap.find(entityID) != m_ServerToClientMap.end();
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ void Server::parseMessageType(Packet& packet)
|
|||||||
case MessageType::Message:
|
case MessageType::Message:
|
||||||
break;
|
break;
|
||||||
case MessageType::Snapshot:
|
case MessageType::Snapshot:
|
||||||
parseSnapshot(packet);
|
|
||||||
break;
|
break;
|
||||||
case MessageType::Disconnect:
|
case MessageType::Disconnect:
|
||||||
parseDisconnect();
|
parseDisconnect();
|
||||||
@@ -149,13 +148,15 @@ void Server::sendSnapshot()
|
|||||||
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
||||||
for (auto& it : worldComponentPools) {
|
for (auto& it : worldComponentPools) {
|
||||||
Packet packet(MessageType::Snapshot, m_SendPacketID);
|
Packet packet(MessageType::Snapshot, m_SendPacketID);
|
||||||
std::string componentType = it.first;
|
|
||||||
ComponentPool* componentPool = it.second;
|
ComponentPool* componentPool = it.second;
|
||||||
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
||||||
|
// Component Type
|
||||||
packet.WriteString(componentInfo.Name);
|
packet.WriteString(componentInfo.Name);
|
||||||
|
|
||||||
for (auto& componentWrapper : *componentPool) {
|
for (auto& componentWrapper : *componentPool) {
|
||||||
|
// Components EntityID
|
||||||
packet.WritePrimitive(componentWrapper.EntityID);
|
packet.WritePrimitive(componentWrapper.EntityID);
|
||||||
|
// Parents EntityID
|
||||||
|
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID));
|
||||||
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
||||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
|
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
|
||||||
if (fieldInfo.Type == "string") {
|
if (fieldInfo.Type == "string") {
|
||||||
@@ -228,29 +229,12 @@ void Server::parseEvent(Packet& packet)
|
|||||||
// If no player matches the address return.
|
// If no player matches the address return.
|
||||||
if (i >= 8)
|
if (i >= 8)
|
||||||
return;
|
return;
|
||||||
|
Events::InputCommand e;
|
||||||
unsigned int entityId = m_PlayerDefinitions[i].EntityID;
|
e.Command = packet.ReadString();
|
||||||
std::string eventString = packet.ReadString();
|
e.PlayerID = packet.ReadPrimitive<int>();
|
||||||
if ("+Forward" == eventString) {
|
e.Value = packet.ReadPrimitive<float>();
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = true;
|
m_EventBroker->Publish(e);
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = false;
|
LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||||
} else if ("-Forward" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = true;
|
|
||||||
} else if ("0Forward" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = false;
|
|
||||||
}
|
|
||||||
if ("+Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = true;
|
|
||||||
} else if ("-Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = true;
|
|
||||||
} else if ("0Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::parseConnect(Packet& packet)
|
void Server::parseConnect(Packet& packet)
|
||||||
@@ -319,21 +303,6 @@ void Server::parseServerPing()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOT USED
|
|
||||||
void Server::parseSnapshot(Packet& packet)
|
|
||||||
{
|
|
||||||
// Does no logic. Returns snapshot if client request one
|
|
||||||
// The snapshot is not a real snapshot tho...
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
m_Socket.send_to(
|
|
||||||
boost::asio::buffer("I'm sending a snapshot to you guys!"),
|
|
||||||
m_PlayerDefinitions[i].Endpoint,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::identifyPacketLoss()
|
void Server::identifyPacketLoss()
|
||||||
{
|
{
|
||||||
// if no packets lost, difference should be equal to 1
|
// if no packets lost, difference should be equal to 1
|
||||||
|
|||||||
Reference in New Issue
Block a user