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:
Jocke
2016-01-13 16:09:16 +01:00
parent 2284399538
commit f47f913bf5
4 changed files with 65 additions and 80 deletions
+7 -2
View File
@@ -3,6 +3,7 @@
#include <string>
#include <ctime>
#include <limits>
#include <glm/common.hpp>
#include <boost/asio.hpp>
@@ -45,6 +46,10 @@ private:
std::string m_PlayerName;
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
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot;
@@ -56,7 +61,7 @@ private:
// Private member functions
void readFromServer();
void sendSnapshotToServer();
void sendInputEvents();
int receive(char* data, size_t length);
void send(Packet& packet);
void connect();
@@ -73,7 +78,7 @@ private:
void identifyPacketLoss();
bool isConnected();
EntityID createPlayer();
bool hasMappedEntity(EntityID entityID);
// Events
EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand;
+1 -1
View File
@@ -12,6 +12,7 @@
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Network/Network.h"
#include "Input/EInputCommand.h"
class Server : public Network
{
@@ -72,7 +73,6 @@ private:
void parseDisconnect();
void parseClientPing();
void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss();
EntityID createPlayer();
};
+47 -36
View File
@@ -5,6 +5,8 @@ using namespace boost::asio::ip;
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
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
int port = config->Get<int>("Networking.Port", 13);
@@ -16,8 +18,7 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
}
Client::~Client()
{
}
{ }
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.
m_NextSnapshot.InputForward = "";
@@ -187,9 +188,16 @@ void Client::parseSnapshot(Packet& packet)
{
std::string componentType = packet.ReadString();
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();
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 the entity and the component exists update it
updateFields(packet, componentInfo, entityID, componentType);
@@ -202,11 +210,12 @@ void Client::parseSnapshot(Packet& packet)
}
// If the entity dosent exist nor the component
} else {
//Create Entity
// Create Entity
// If entity dosen't exist
EntityID newEntityID = m_World->CreateEntity();
m_ServerToClientMap.insert(std::make_pair(receivedEntityID, newEntityID));
// 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 \
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
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)
{
if (isConnected()) {
ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
if (e.Command == "Forward") {
if (e.Value > 0) {
(bool&)player["Forward"] = true;
(bool&)player["Back"] = false;
} else if (e.Value < 0) {
(bool&)player["Back"] = true;
(bool&)player["Forward"] = false;
} 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
if (e.Command == "Forward" || e.Command == "Right") {
Packet packet(MessageType::Event, m_SendPacketID);
packet.WriteString(e.Command);
packet.WritePrimitive(e.PlayerID);
packet.WritePrimitive(e.Value);
send(packet);
LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
return true;
} else if (e.Command == "ConnectToServer") { // Connect for now
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;
}
void Client::identifyPacketLoss()
{
// if no packets lost, difference should be equal to 1
@@ -335,3 +341,8 @@ EntityID Client::createPlayer()
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
return entityID;
}
bool Client::hasMappedEntity(EntityID entityID)
{
return m_ServerToClientMap.find(entityID) != m_ServerToClientMap.end();
}
+10 -41
View File
@@ -76,7 +76,6 @@ void Server::parseMessageType(Packet& packet)
case MessageType::Message:
break;
case MessageType::Snapshot:
parseSnapshot(packet);
break;
case MessageType::Disconnect:
parseDisconnect();
@@ -149,13 +148,15 @@ void Server::sendSnapshot()
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
for (auto& it : worldComponentPools) {
Packet packet(MessageType::Snapshot, m_SendPacketID);
std::string componentType = it.first;
ComponentPool* componentPool = it.second;
ComponentInfo componentInfo = componentPool->ComponentInfo();
// Component Type
packet.WriteString(componentInfo.Name);
for (auto& componentWrapper : *componentPool) {
// Components EntityID
packet.WritePrimitive(componentWrapper.EntityID);
// Parents EntityID
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID));
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
if (fieldInfo.Type == "string") {
@@ -228,29 +229,12 @@ void Server::parseEvent(Packet& packet)
// If no player matches the address return.
if (i >= 8)
return;
unsigned int entityId = m_PlayerDefinitions[i].EntityID;
std::string eventString = packet.ReadString();
if ("+Forward" == eventString) {
m_World->GetComponent(entityId, "Player")["Forward"] = true;
m_World->GetComponent(entityId, "Player")["Back"] = false;
} 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;
}
Events::InputCommand e;
e.Command = packet.ReadString();
e.PlayerID = packet.ReadPrimitive<int>();
e.Value = packet.ReadPrimitive<float>();
m_EventBroker->Publish(e);
LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
}
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()
{
// if no packets lost, difference should be equal to 1