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 <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;
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
@@ -205,8 +213,9 @@ void Client::parseSnapshot(Packet& packet)
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user