From 7ae42a5bf7e7ccb1a789a7257f8d56228b01ccf7 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 6 Jan 2016 11:39:32 +0100 Subject: [PATCH 01/22] Removed some comments. Basically did nothing --- include/Engine/Network/Network.h | 1 + src/Engine/Input/InputProxy.cpp | 4 ++-- src/Engine/Network/Client.cpp | 14 +++++--------- src/Engine/Network/Server.cpp | 8 ++++++-- src/Game/Game.cpp | 13 ++++++------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index 0f7baefe..c5107b2b 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -14,6 +14,7 @@ public: virtual ~Network() { }; virtual void Start(World* m_world, EventBroker *eventBroker) = 0; virtual void Update() = 0; + virtual void Close() = 0; }; #endif \ No newline at end of file diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp index c3e4d669..ad589df3 100644 --- a/src/Engine/Input/InputProxy.cpp +++ b/src/Engine/Input/InputProxy.cpp @@ -62,7 +62,7 @@ void InputProxy::Process() e.Command = command; e.Value = currentValue; m_EventBroker->Publish(e); - LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); m_LastCommandValues[command] = currentValue; } } @@ -78,7 +78,7 @@ void InputProxy::Process() } //e.Value = std::max(-1.f, std::min(e.Value, 1.f)); m_EventBroker->Publish(e); - LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); } m_CommandQueue.clear(); } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 5c7e9c8f..a417c4e5 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -17,7 +17,7 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService) Client::~Client() { - + m_EventBroker->Unsubscribe(m_EInputCommand); } void Client::Start(World* world, EventBroker* eventBroker) @@ -27,14 +27,10 @@ void Client::Start(World* world, EventBroker* eventBroker) m_World = world; // Subscribe to events - m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); - m_EventBroker->Subscribe(m_EInputCommand); + //m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); + //m_EventBroker->Subscribe(m_EInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); - - //while (m_PlayerName.size() > 7) { - // LOG_INFO("Please enter your name (No longer than 7 characters):"); - // std::cin >> m_PlayerName; - //} m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); } @@ -73,7 +69,7 @@ void Client::readFromServer() void Client::sendSnapshotToServer() { - // Reset previouse key state in snapshot. + // Reset previous key state in snapshot. m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 261583cc..c53dce8f 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -4,7 +4,9 @@ Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::a { } Server::~Server() -{ } +{ + +} void Server::Start(World* world, EventBroker* eventBroker) @@ -25,6 +27,8 @@ void Server::Update() void Server::Close() { m_ThreadIsRunning = false; + m_Socket.close(); + } void Server::readFromClients() @@ -271,7 +275,7 @@ void Server::parseConnect(Packet& packet) m_StopTimes[i] = std::clock(); - LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name, m_PlayerDefinitions[i].Endpoint.address().to_string()); + LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); Packet packet(MessageType::Connect, m_SendPacketID); packet.WritePrimitive(i); // Player ID diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index f1582d5d..d8bebea6 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -128,11 +128,15 @@ bool Game::debugOnInputCommand(const Events::InputCommand& e) } } if (e.Command == "SwitchToServer" && e.Value > 0) { + m_ClientOrServer->Close(); // memory leak for now, use delete when it works + //delete m_ClientOrServer; m_ClientOrServer = new Server(); LOG_INFO("Switching to server"); m_ClientOrServer->Start(m_World, m_EventBroker); } - if (e.Command == "SwitchToClient" && e.Value > 0) { + else if (e.Command == "SwitchToClient" && e.Value > 0) { + m_ClientOrServer->Close(); // memory leak for now, use delete when it works + //delete m_ClientOrServer; m_ClientOrServer = new Client(m_Config); m_ClientOrServer->Start(m_World, m_EventBroker); LOG_INFO("Switching to client"); @@ -163,10 +167,5 @@ void Game::networkFunction() m_ClientOrServer = new Server(); } m_ClientOrServer->Start(m_World, m_EventBroker); - // I don't think we are reaching this part of the code right now. - // ~Game() is not called if the game is exited by closing console windows - // When server or client is done set it to false. - //m_IsClientOrServer = false; - // Destroy it - //delete m_ClientOrServer; + } \ No newline at end of file From f47f913bf571c824fc31766ffdd7792f0f4244bc Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 13 Jan 2016 16:09:16 +0100 Subject: [PATCH 02/22] 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. --- include/Engine/Network/Client.h | 9 +++- include/Engine/Network/Server.h | 2 +- src/Engine/Network/Client.cpp | 83 +++++++++++++++++++-------------- src/Engine/Network/Server.cpp | 51 ++++---------------- 4 files changed, 65 insertions(+), 80 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index a5488210..da734810 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -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 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 m_EInputCommand; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 893eed0b..84d8c143 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -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(); }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index b8849ed0..3ecee0e0 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -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("Networking.Address", "127.0.0.1"); int port = config->Get("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(); + // Components EntityID + EntityID receivedEntityID = packet.ReadPrimitive(); + // Parents EntityID + EntityID receivedParentEntityID = packet.ReadPrimitive(); 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::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(); +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 07fed65b..e98213a5 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -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 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(); + e.Value = packet.ReadPrimitive(); + 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 From a060640da3eee5e2017819fbd4fa8322302645e9 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 13 Jan 2016 18:00:12 +0100 Subject: [PATCH 03/22] Removed unnecessary unnecessary if in Client::OnInputCommand. Change name from Server::parseEvent to Server::parseOnInputCommand --- include/Engine/Network/Client.h | 3 ++- include/Engine/Network/MessageType.h | 1 + include/Engine/Network/Server.h | 2 +- src/Engine/Network/Client.cpp | 13 ++++++------- src/Engine/Network/Server.cpp | 6 ++++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index da734810..6b73c95c 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -81,8 +81,9 @@ private: bool hasMappedEntity(EntityID entityID); // Events EventBroker* m_EventBroker; + EventRelay m_EInputCommand; - bool OnInputCommand(const Events::InputCommand &e); + bool OnInputCommand(const Events::InputCommand& e); }; #endif diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index 8d09c7ee..68bda9b0 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -12,6 +12,7 @@ enum class MessageType Message, Snapshot, Event, + OnInputCommand }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 84d8c143..ec2560b5 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -68,7 +68,7 @@ private: void checkForTimeOuts(); void disconnect(int i); void parseMessageType(Packet& packet); - void parseEvent(Packet& packet); + void parseOnInputCommand(Packet& packet); void parseConnect(Packet& packet); void parseDisconnect(); void parseClientPing(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 3ecee0e0..37ee35d9 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -254,7 +254,6 @@ int Client::receive(char* data, size_t length) if (error) { LOG_ERROR("receive: %s", error.message().c_str()); } - return bytesReceived; } @@ -297,18 +296,18 @@ void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize) bool Client::OnInputCommand(const Events::InputCommand & e) { - if (e.Command == "Forward" || e.Command == "Right") { - Packet packet(MessageType::Event, m_SendPacketID); + 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; + } else { + Packet packet(MessageType::OnInputCommand, 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; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index e98213a5..6b59a31a 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -81,8 +81,10 @@ void Server::parseMessageType(Packet& packet) parseDisconnect(); break; case MessageType::Event: - parseEvent(packet); break; + case MessageType::OnInputCommand: + parseOnInputCommand(packet); + break;; default: break; } @@ -218,7 +220,7 @@ void Server::disconnect(int i) m_PlayerDefinitions[i].Name = ""; } -void Server::parseEvent(Packet& packet) +void Server::parseOnInputCommand(Packet& packet) { size_t i; for (i = 0; i < MAXCONNECTIONS; i++) { From db18a453685d5c220dfec27462d1312a0919f412 Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 14 Jan 2016 10:16:11 +0100 Subject: [PATCH 04/22] We are now sending EPlayerDamage events. Client now listens to EPlayerDamage events and send them to Server. Server publishes EPlayerDamage events received from Client. --- include/Engine/Network/Client.h | 5 ++++- include/Engine/Network/MessageType.h | 3 ++- include/Engine/Network/Server.h | 2 ++ src/Engine/Network/Client.cpp | 14 ++++++++++++-- src/Engine/Network/Server.cpp | 26 +++++++++++++++----------- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 6b73c95c..3027ad87 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -16,6 +16,7 @@ #include "Core/EventBroker.h" #include "Core/ConfigFile.h" #include "Input/EInputCommand.h" +#include "Core/EPlayerDamage.h" class Client : public Network { @@ -79,11 +80,13 @@ private: bool isConnected(); EntityID createPlayer(); bool hasMappedEntity(EntityID entityID); + // Events EventBroker* m_EventBroker; - EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_EPlayeDamage; + bool OnPlayerDamage(const Events::PlayerDamage& e); }; #endif diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index 68bda9b0..42b049e8 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -12,7 +12,8 @@ enum class MessageType Message, Snapshot, Event, - OnInputCommand + OnInputCommand, + OnPlayerDamage }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index ec2560b5..dc7b25cd 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -13,6 +13,7 @@ #include "Core/EventBroker.h" #include "Network/Network.h" #include "Input/EInputCommand.h" +#include "Core/EPlayerDamage.h" class Server : public Network { @@ -69,6 +70,7 @@ private: void disconnect(int i); void parseMessageType(Packet& packet); void parseOnInputCommand(Packet& packet); + void parseOnPlayerDamage(Packet& packet); void parseConnect(Packet& packet); void parseDisconnect(); void parseClientPing(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 37ee35d9..c073e79a 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -298,7 +298,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e) { 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); + LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } else { Packet packet(MessageType::OnInputCommand, m_SendPacketID); @@ -306,12 +306,22 @@ bool Client::OnInputCommand(const Events::InputCommand & e) 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); + LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } return false; } +bool Client::OnPlayerDamage(const Events::PlayerDamage & e) +{ + Packet packet(MessageType::OnInputCommand, m_SendPacketID); + packet.WritePrimitive(e.DamageAmount); + packet.WritePrimitive(e.PlayerDamagedID); + packet.WriteString(e.TypeOfDamage); + send(packet); + return false; +} + void Client::identifyPacketLoss() { // if no packets lost, difference should be equal to 1 diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 6b59a31a..1a915863 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -84,7 +84,10 @@ void Server::parseMessageType(Packet& packet) break; case MessageType::OnInputCommand: parseOnInputCommand(packet); - break;; + break; + case MessageType::OnPlayerDamage: + parseOnPlayerDamage(packet); + break; default: break; } @@ -222,21 +225,22 @@ void Server::disconnect(int i) void Server::parseOnInputCommand(Packet& packet) { - size_t i; - for (i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - break; - } - } - // If no player matches the address return. - if (i >= 8) - return; Events::InputCommand e; e.Command = packet.ReadString(); e.PlayerID = packet.ReadPrimitive(); e.Value = packet.ReadPrimitive(); 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); + LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); +} + +void Server::parseOnPlayerDamage(Packet & packet) +{ + Events::PlayerDamage e; + e.DamageAmount = packet.ReadPrimitive(); + e.PlayerDamagedID = packet.ReadPrimitive(); + e.TypeOfDamage = packet.ReadString(); + m_EventBroker->Publish(e); + LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); } void Server::parseConnect(Packet& packet) From 696f44a673788475d2df091ed1e2d5893c4d9934 Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 14 Jan 2016 17:11:54 +0100 Subject: [PATCH 05/22] Added logic for mapping between ServerEntityIDs and LocalEntityIDs removed old code that wasn't used. Added 1 map to Client and renamed m_ServerToClientMap to m_ServerIDToClientID. // Good to know To keep this structure please use insertIntoServerClientMaps() when adding items to them. m_ServerIDToClientID and m_ClientIDToServerID maps between server EntityIDs and local EntityIDs. To see if a local EntityID exist in m_ClientIDToServerID use clientServerMapsHasEntity(EntityID clientEntityID); To see if server EntityID exist in m_ServerIDToClientID use serverClientMapsHasEntity(EntityID serverEntityID); --- include/Engine/Network/Client.h | 23 ++--- include/Engine/Network/MessageType.h | 4 +- include/Engine/Network/Server.h | 4 - src/Engine/Network/Client.cpp | 122 ++++++++------------------- src/Engine/Network/Server.cpp | 34 ++------ 5 files changed, 56 insertions(+), 131 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 3027ad87..81b2b834 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -34,8 +34,6 @@ private: // Sending message to server logic int bytesRead = -1; char readBuf[INPUTSIZE] = { 0 }; - int snapshotInterval = 33; - std::clock_t previousSnapshotMessage = std::clock(); // Packet loss logic unsigned int m_PacketID = 0; @@ -46,40 +44,43 @@ private: World* m_World; std::string m_PlayerName; int m_PlayerID = -1; - + EntityID m_ServerEntityID = std::numeric_limits::max(); // Server Client Lookup map // Assumes that root node for client and server is EntityID 0. - std::unordered_map m_ServerToClientMap; + + // Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!! + std::unordered_map m_ServerIDToClientID; + std::unordered_map m_ClientIDToServerID; // Network logic PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; SnapshotDefinitions m_NextSnapshot; double m_DurationOfPingTime; std::clock_t m_StartPingTime; - // Use to check if we should send disconnect message - // if game is turned of by closing window. - bool m_WasStarted = false; // Private member functions void readFromServer(); - void sendInputEvents(); int receive(char* data, size_t length); void send(Packet& packet); void connect(); void disconnect(); void ping(); - void moveMessageHead(char*& data, size_t& length, size_t stepSize); void parseMessageType(Packet& packet); - void parseEventMessage(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); void parseConnect(Packet& packet); + void parsePlayerConnected(Packet& packet); void parsePing(); void parseServerPing(); void parseSnapshot(Packet& packet); void identifyPacketLoss(); bool isConnected(); EntityID createPlayer(); - bool hasMappedEntity(EntityID entityID); + // Mapping Logic + // Returns if local EntityID exist in map + bool clientServerMapsHasEntity(EntityID clientEntityID); + // Returns if server EntityID exist in map + bool serverClientMapsHasEntity(EntityID serverEntityID); + void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID); // Events EventBroker* m_EventBroker; diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index 42b049e8..ba9684d9 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -11,9 +11,9 @@ enum class MessageType ServerPing, Message, Snapshot, - Event, OnInputCommand, - OnPlayerDamage + OnPlayerDamage, + PlayerConnected }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index dc7b25cd..4c71be95 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -48,8 +48,6 @@ private: // Game logic World* m_World; EventBroker* m_EventBroker; - // vec.size() = ammount of players to create, stores playerID's - std::vector m_PlayersToCreate; // Packet loss logic unsigned int m_PacketID; @@ -61,8 +59,6 @@ private: void readFromClients(); void send(Packet& packet, int playerID); void send(Packet& packet); - void moveMessageHead(char*& data, size_t& length, size_t stepSize); - void broadcast(std::string message); void broadcast(Packet& packet); void sendSnapshot(); void sendPing(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index c073e79a..37534a27 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,15 +6,13 @@ 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)); + insertIntoServerClientMaps(0, 0); // Default is local host std::string address = config->Get("Networking.Address", "127.0.0.1"); int port = config->Get("Networking.Port", 13); m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); // Set up network stream m_PlayerName = config->Get("Networking.Name", "Raptorcopter"); - m_NextSnapshot.InputForward = ""; - m_NextSnapshot.InputRight = ""; } Client::~Client() @@ -22,7 +20,6 @@ Client::~Client() void Client::Start(World* world, EventBroker* eventBroker) { - m_WasStarted = true; m_EventBroker = eventBroker; m_World = world; @@ -47,58 +44,6 @@ void Client::readFromServer() parseMessageType(packet); } } - std::clock_t currentTime = std::clock(); - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - if (isConnected()) { - //sendSnapshotToServer(); - } - previousSnapshotMessage = currentTime; - } -} - -void Client::sendInputEvents() -{ - // Reset previous key state in snapshot. - m_NextSnapshot.InputForward = ""; - m_NextSnapshot.InputRight = ""; - - auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); - - // See if any movement keys are down - // We dont care if it's overwritten by later - // if statement. Watcha gonna do, right! - if (player["Forward"]) { - m_NextSnapshot.InputForward = "+Forward"; - } - if (player["Left"]) { - m_NextSnapshot.InputRight = "-Right"; - } - if (player["Back"]) { - m_NextSnapshot.InputForward = "-Forward"; - } - if (player["Right"]) { - m_NextSnapshot.InputRight = "+Right"; - } - - if (m_NextSnapshot.InputForward != "") { - Packet packet(MessageType::Event, m_SendPacketID); - packet.WriteString(m_NextSnapshot.InputForward); - send(packet); - } else { - Packet packet(MessageType::Event, m_SendPacketID); - packet.WriteString("0Forward"); - send(packet); - } - - if (m_NextSnapshot.InputRight != "") { - Packet packet(MessageType::Event, m_SendPacketID); - packet.WriteString(m_NextSnapshot.InputRight); - send(packet); - } else { - Packet packet(MessageType::Event, m_SendPacketID); - packet.WriteString("0Right"); - send(packet); - } } void Client::parseMessageType(Packet& packet) @@ -130,9 +75,8 @@ void Client::parseMessageType(Packet& packet) break; case MessageType::Disconnect: break; - case MessageType::Event: - parseEventMessage(packet); - break; + case MessageType::PlayerConnected: + parsePlayerConnected(packet); default: break; } @@ -140,10 +84,19 @@ void Client::parseMessageType(Packet& packet) void Client::parseConnect(Packet& packet) { + // Set your own player id m_PlayerID = packet.ReadPrimitive(); + m_ServerEntityID = packet.ReadPrimitive(); + // Map ServerEntityID and your PlayerID LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); } +void Client::parsePlayerConnected(Packet & packet) +{ + // Map ServerEntityID and other player's PlayerID + LOG_INFO("A Player connected"); +} + void Client::parsePing() { m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); @@ -157,19 +110,6 @@ void Client::parseServerPing() send(packet); } -void Client::parseEventMessage(Packet& packet) -{ - int Id = -1; - std::string command = packet.ReadString(); - if (command.find("+Player") != std::string::npos) { - Id = packet.ReadPrimitive(); - // Sett Player name - m_PlayerDefinitions[Id].Name = command.erase(0, 7); - } else { - LOG_INFO("%i: Event message: %s", m_PacketID, command.c_str()); - } -} - void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) { for (auto field : componentInfo.FieldsInOrder) { @@ -194,9 +134,9 @@ void Client::parseSnapshot(Packet& packet) EntityID receivedParentEntityID = packet.ReadPrimitive(); ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); // Check if the received EntityID is mapped to one of our local EntityIDs - if (hasMappedEntity(receivedEntityID)) { + if (clientServerMapsHasEntity(receivedEntityID)) { // Get the local EntityID - EntityID entityID = m_ServerToClientMap.at(receivedEntityID); + EntityID entityID = m_ServerIDToClientID.at(receivedEntityID); // Check if the component exists if (m_World->HasComponent(entityID, componentType)) { // If the entity and the component exists update it @@ -213,7 +153,7 @@ 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)); + insertIntoServerClientMaps(receivedEntityID, newEntityID); // Check if EntityIDs are out of sync if (newEntityID != receivedEntityID) { LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \ @@ -228,15 +168,15 @@ void Client::parseSnapshot(Packet& packet) // Parent Logic // Don't need to check if receivedEntityID is mapped. (It should have been set) if (receivedParentEntityID != std::numeric_limits::max()) { - if (hasMappedEntity(receivedParentEntityID)) { - m_World->SetParent(m_ServerToClientMap.at(receivedEntityID), m_ServerToClientMap.at(receivedParentEntityID)); + if (clientServerMapsHasEntity(receivedParentEntityID)) { + m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.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)); + insertIntoServerClientMaps(receivedParentEntityID, newParentEntityID); // Set the newly created Entity as parent. - m_World->SetParent(m_ServerToClientMap.at(receivedEntityID), newParentEntityID); + m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), newParentEntityID); } } } @@ -252,7 +192,7 @@ int Client::receive(char* data, size_t length) 0, error); if (error) { - LOG_ERROR("receive: %s", error.message().c_str()); + //LOG_ERROR("receive: %s", error.message().c_str()); } return bytesReceived; } @@ -288,12 +228,6 @@ void Client::ping() send(packet); } -void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize) -{ - data += stepSize; - length -= stepSize; -} - bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "ConnectToServer") { // Connect for now @@ -351,7 +285,19 @@ EntityID Client::createPlayer() return entityID; } -bool Client::hasMappedEntity(EntityID entityID) +bool Client::clientServerMapsHasEntity(EntityID clientEntityID) { - return m_ServerToClientMap.find(entityID) != m_ServerToClientMap.end(); + return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end(); +} + +bool Client::serverClientMapsHasEntity(EntityID serverEntityID) +{ + return m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end(); +} + +void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID) +{ + m_ServerIDToClientID.insert(std::make_pair(serverEntityID, clientEntityID)); + m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID)); + } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 1a915863..5ec674d0 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -50,7 +50,7 @@ void Server::readFromClients() // Time out logic if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - //checkForTimeOuts(); + checkForTimeOuts(); timOutTimer = currentTime; } } @@ -80,8 +80,6 @@ void Server::parseMessageType(Packet& packet) case MessageType::Disconnect: parseDisconnect(); break; - case MessageType::Event: - break; case MessageType::OnInputCommand: parseOnInputCommand(packet); break; @@ -120,23 +118,6 @@ void Server::send(Packet & packet) 0); } -void Server::moveMessageHead(char *& data, size_t & length, size_t stepSize) -{ - data += stepSize; - length -= stepSize; -} - -void Server::broadcast(std::string message) -{ - Packet packet(MessageType::Event, m_SendPacketID); - packet.WriteString(message); - for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - send(packet, i); - } - } -} - void Server::broadcast(Packet& packet) { for (int i = 0; i < MAXCONNECTIONS; ++i) { @@ -214,7 +195,7 @@ void Server::checkForTimeOuts() void Server::disconnect(int i) { - broadcast("A player disconnected"); + //broadcast("A player disconnected"); LOG_INFO("Player %i disconnected/timed out", i); // Remove enteties and stuff @@ -234,7 +215,7 @@ void Server::parseOnInputCommand(Packet& packet) } void Server::parseOnPlayerDamage(Packet & packet) -{ +{ Events::PlayerDamage e; e.DamageAmount = packet.ReadPrimitive(); e.PlayerDamagedID = packet.ReadPrimitive(); @@ -264,15 +245,16 @@ void Server::parseConnect(Packet& packet) LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); + // Send a message to the player that connected Packet packet(MessageType::Connect, m_SendPacketID); packet.WritePrimitive(i); // Player ID - + packet.WritePrimitive(m_PlayerDefinitions[i].EntityID); // Entity ID send(packet, i); // Send notification that a player has connected - std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " - + m_PlayerDefinitions[i].Endpoint.address().to_string(); - broadcast(str); + Packet notificationPacket(MessageType::PlayerConnected, m_PacketID); + broadcast(notificationPacket); + break; } } From db62d767ac12587cf6961b8d8beef0223a4ef057 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 15 Jan 2016 12:06:20 +0100 Subject: [PATCH 06/22] Fixed bug in Client::parseSnapshot(). --- src/Engine/Network/Client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 37534a27..55292234 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -134,7 +134,7 @@ void Client::parseSnapshot(Packet& packet) EntityID receivedParentEntityID = packet.ReadPrimitive(); ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); // Check if the received EntityID is mapped to one of our local EntityIDs - if (clientServerMapsHasEntity(receivedEntityID)) { + if (serverClientMapsHasEntity(receivedEntityID)) { // Get the local EntityID EntityID entityID = m_ServerIDToClientID.at(receivedEntityID); // Check if the component exists @@ -168,7 +168,7 @@ void Client::parseSnapshot(Packet& packet) // Parent Logic // Don't need to check if receivedEntityID is mapped. (It should have been set) if (receivedParentEntityID != std::numeric_limits::max()) { - if (clientServerMapsHasEntity(receivedParentEntityID)) { + if (serverClientMapsHasEntity(receivedParentEntityID)) { m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.at(receivedParentEntityID)); // If Parent dosen't exist create one and map receivedParentEntityID to it. } else { From d995713d3b4e1e4216e9d462081a0ab2d1375b36 Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 18 Jan 2016 11:05:32 +0100 Subject: [PATCH 07/22] Added input queue to Client and Input Listener debug code in server. --- assets | 2 +- include/Engine/Network/Client.h | 2 ++ include/Engine/Network/Server.h | 4 ++++ src/Engine/Network/Client.cpp | 27 +++++++++++++++------- src/Engine/Network/Server.cpp | 40 ++++++++++++++++++++++++++------- 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/assets b/assets index 6cbf2365..a3c92ac8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6cbf2365d49e6280750ea3bcd0f9c271779e6f15 +Subproject commit a3c92ac876dd061776c36d1594bd82264372f028 diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 81b2b834..7aa20126 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -57,6 +57,7 @@ private: SnapshotDefinitions m_NextSnapshot; double m_DurationOfPingTime; std::clock_t m_StartPingTime; + std::vector m_InputCommandBuffer; // Private member functions void readFromServer(); @@ -75,6 +76,7 @@ private: void identifyPacketLoss(); bool isConnected(); EntityID createPlayer(); + void sendInputCommands(); // Mapping Logic // Returns if local EntityID exist in map bool clientServerMapsHasEntity(EntityID clientEntityID); diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 4c71be95..9aba921a 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -73,6 +73,10 @@ private: void parseServerPing(); void identifyPacketLoss(); EntityID createPlayer(); + // Debug event + + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& e); }; #endif diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 55292234..e07bcf7a 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -25,6 +25,7 @@ void Client::Start(World* world, EventBroker* eventBroker) // Subscribe to events EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EPlayeDamage, &Client::OnPlayerDamage); m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); @@ -44,6 +45,7 @@ void Client::readFromServer() parseMessageType(packet); } } + sendInputCommands(); } void Client::parseMessageType(Packet& packet) @@ -92,7 +94,7 @@ void Client::parseConnect(Packet& packet) } void Client::parsePlayerConnected(Packet & packet) -{ +{ // Map ServerEntityID and other player's PlayerID LOG_INFO("A Player connected"); } @@ -235,12 +237,8 @@ bool Client::OnInputCommand(const Events::InputCommand & e) LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } else { - Packet packet(MessageType::OnInputCommand, m_SendPacketID); - packet.WriteString(e.Command); - packet.WritePrimitive(e.PlayerID); - packet.WritePrimitive(e.Value); - send(packet); - LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + m_InputCommandBuffer.push_back(e); + 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; @@ -285,6 +283,19 @@ EntityID Client::createPlayer() return entityID; } +void Client::sendInputCommands() +{ + if (m_InputCommandBuffer.size() > 0) { + Packet packet(MessageType::OnInputCommand, m_SendPacketID); + for (int i = 0; i < m_InputCommandBuffer.size(); i++) { + packet.WriteString(m_InputCommandBuffer[i].Command); + packet.WritePrimitive(m_InputCommandBuffer[i].Value); + } + send(packet); + m_InputCommandBuffer.clear(); + } +} + bool Client::clientServerMapsHasEntity(EntityID clientEntityID) { return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end(); @@ -296,7 +307,7 @@ bool Client::serverClientMapsHasEntity(EntityID serverEntityID) } void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID) -{ +{ m_ServerIDToClientID.insert(std::make_pair(serverEntityID, clientEntityID)); m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID)); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 5ec674d0..2563d9b1 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -13,6 +13,8 @@ void Server::Start(World* world, EventBroker* eventBroker) { m_World = world; m_EventBroker = eventBroker; + // Subscribe to events + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); for (size_t i = 0; i < MAXCONNECTIONS; i++) { m_StopTimes[i] = std::clock(); } @@ -22,6 +24,7 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { readFromClients(); + m_EventBroker->Process(); } void Server::readFromClients() @@ -206,12 +209,26 @@ void Server::disconnect(int i) void Server::parseOnInputCommand(Packet& packet) { - Events::InputCommand e; - e.Command = packet.ReadString(); - e.PlayerID = packet.ReadPrimitive(); - e.Value = packet.ReadPrimitive(); - m_EventBroker->Publish(e); - LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + int playerID = -1; + // Check which player it was who sent the message + for (int i = 0; i < MAXCONNECTIONS; i++) { + // if the player is connected set playerID to the correct PlayerID + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address() + && m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) { + playerID = i; + break; + } + } + if (playerID != -1) { + while (packet.DataReadSize() < packet.Size()) { + Events::InputCommand e; + e.Command = packet.ReadString(); + e.PlayerID = playerID; // Set correct player id + e.Value = packet.ReadPrimitive(); + m_EventBroker->Publish(e); + LOG_DEBUG("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + } + } } void Server::parseOnPlayerDamage(Packet & packet) @@ -221,7 +238,7 @@ void Server::parseOnPlayerDamage(Packet & packet) e.PlayerDamagedID = packet.ReadPrimitive(); e.TypeOfDamage = packet.ReadString(); m_EventBroker->Publish(e); - LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); + LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); } void Server::parseConnect(Packet& packet) @@ -229,7 +246,8 @@ void Server::parseConnect(Packet& packet) LOG_INFO("Parsing connections"); // Check if player is already connected for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address() && + m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) { return; } } @@ -311,3 +329,9 @@ EntityID Server::createPlayer() ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); return entityID; } + +bool Server::OnInputCommand(const Events::InputCommand & e) +{ + LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + return true; +} From 6ba6deb863476e523d194c46e47b29b67b66163a Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 18 Jan 2016 11:35:35 +0100 Subject: [PATCH 08/22] Removed some debug spam. --- src/Engine/Network/Client.cpp | 4 ++-- src/Engine/Network/Server.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index e07bcf7a..d6e8f4c5 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -234,11 +234,11 @@ bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "ConnectToServer") { // Connect for now connect(); - LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } else { m_InputCommandBuffer.push_back(e); - LOG_INFO("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } return false; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 2563d9b1..422d6523 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -226,7 +226,7 @@ void Server::parseOnInputCommand(Packet& packet) e.PlayerID = playerID; // Set correct player id e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); - LOG_DEBUG("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); } } } @@ -332,6 +332,6 @@ EntityID Server::createPlayer() bool Server::OnInputCommand(const Events::InputCommand & e) { - LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } From d7780d8248eb696b44fc7b9ca43cab55cb0dff38 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 18 Jan 2016 17:11:37 +0100 Subject: [PATCH 09/22] WIP implementing interpolation --- include/Engine/Network/EInterpolate.h | 20 +++++++++++ include/Game/InterpolationSystem.h | 42 ++++++++++++++++++++++ src/Game/InterpolationSystem.cpp | 50 +++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 include/Engine/Network/EInterpolate.h create mode 100644 include/Game/InterpolationSystem.h create mode 100644 src/Game/InterpolationSystem.cpp diff --git a/include/Engine/Network/EInterpolate.h b/include/Engine/Network/EInterpolate.h new file mode 100644 index 00000000..65038e49 --- /dev/null +++ b/include/Engine/Network/EInterpolate.h @@ -0,0 +1,20 @@ +#ifndef Events_Interpolate_h__ +#define Events_Interpolate_h__ + +#include + +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace Events +{ + +struct Interpolate : Event +{ + EntityID Entity; + boost::shared_array DataArray; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Game/InterpolationSystem.h b/include/Game/InterpolationSystem.h new file mode 100644 index 00000000..c87ee5a7 --- /dev/null +++ b/include/Game/InterpolationSystem.h @@ -0,0 +1,42 @@ +#ifndef Systems_InterpolationSystem_h__ +#define Systems_InterpolationSystem_h__ + +#include +#include +#include +#include + +#include "Common.h" +#include "Core/System.h" +#include "Core/EventBroker.h" + +#include "Network/EInterpolate.h" + +struct Transform { + glm::vec3 Position; + glm::vec3 Scale; + glm::vec3 Orientation; + double interpolationTime; +}; + +class InterpolationSystem : public PureSystem +{ +public: + InterpolationSystem(EventBroker* eventbroker) + : PureSystem(eventbroker, "Transform") + { + EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate); + } + ~InterpolationSystem() { } + + virtual void UpdateComponent(World* world, ComponentWrapper& transform, double dt) override; +private: + std::unordered_map> m_InterpolationPoints; + + glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); + + EventRelay m_EInterpolate; + bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e); +}; + +#endif diff --git a/src/Game/InterpolationSystem.cpp b/src/Game/InterpolationSystem.cpp new file mode 100644 index 00000000..d2d81fda --- /dev/null +++ b/src/Game/InterpolationSystem.cpp @@ -0,0 +1,50 @@ +#include "InterpolationSystem.h" + +void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & transform, double dt) +{ + if (m_InterpolationPoints[transform.EntityID].size() > 0) { + Transform& sTransform = m_InterpolationPoints[transform.EntityID].front(); + sTransform.interpolationTime += dt; + if (sTransform.interpolationTime > 0.05) { + double time = std::fmod(sTransform.interpolationTime, 0.05f); + m_InterpolationPoints[transform.EntityID].pop(); + if (m_InterpolationPoints[transform.EntityID].size() <= 0) { + return; + } + sTransform = m_InterpolationPoints[transform.EntityID].front(); + sTransform.interpolationTime = time; + } + glm::vec3 nextPosition = sTransform.Position; + glm::vec3 currentPosition = static_cast(transform["Position"]); + transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); + } +} + +glm::vec3 InterpolationSystem::vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime) +{ + glm::vec3 difference = next - prev; + glm::vec3 position = difference / 0.05f * static_cast(currentTime); + return position; +} + +bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) +{ + Transform transform; + int offset = 0; + // Read the data + memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3)); + offset += sizeof(glm::vec3); + memcpy(&transform.Orientation, e.DataArray.get() + offset, sizeof(glm::vec3)); + offset += sizeof(glm::vec3); + memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); + + // Check if queue already exists + if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue + m_InterpolationPoints[e.Entity].push(transform); + } else { // Did not exist, create queue + std::queue transformQueue; + transformQueue.push(transform); + m_InterpolationPoints[e.Entity] = transformQueue; + } + return false; +} From 0c7f2c5198d821217b48a4992f4eac3a605a4a89 Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 18 Jan 2016 17:12:07 +0100 Subject: [PATCH 10/22] WIP implemented Interpolation (server logic) --- include/Engine/Network/Client.h | 5 ++++- src/Engine/Network/Client.cpp | 22 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 7aa20126..6aaa9e77 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -4,9 +4,11 @@ #include #include #include +#include #include #include +#include #include "Network/Network.h" #include "Network/MessageType.h" @@ -68,10 +70,11 @@ private: void ping(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); - void parseConnect(Packet& packet); + void parseConnect(Packet& packet); void parsePlayerConnected(Packet& packet); void parsePing(); void parseServerPing(); + void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); void identifyPacketLoss(); bool isConnected(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index d6e8f4c5..9ffd570b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -112,6 +112,21 @@ void Client::parseServerPing() send(packet); } +// Fields with strings will not work right now +void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) +{ + int sizeOfFields = 0; + for (auto field : componentInfo.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); + sizeOfFields = fieldInfo.Stride; + } + // Is the size correct? + boost::shared_array eventData(new char[componentInfo.Meta.Stride]); + memcpy(eventData.get(), packet.ReadData(componentInfo.Meta.Stride), componentInfo.Meta.Stride); + //Send event to interpolat system + +} + void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) { for (auto field : componentInfo.FieldsInOrder) { @@ -125,7 +140,6 @@ void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, co } } -// Field parse void Client::parseSnapshot(Packet& packet) { std::string componentType = packet.ReadString(); @@ -142,7 +156,11 @@ void Client::parseSnapshot(Packet& packet) // 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); + if (componentType == "Transform") { + InterpolateFields(packet, componentInfo, entityID, componentType); + } else { + updateFields(packet, componentInfo, entityID, componentType); + } // if entity exists but not the component } else { // Create component From 62c3f72355201b52dbde5d38a7eed96eecac03e8 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 18 Jan 2016 17:27:37 +0100 Subject: [PATCH 11/22] Fixed cmake for interpolationsystem. --- include/Engine/Network/EInterpolate.h | 2 +- src/Game/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Engine/Network/EInterpolate.h b/include/Engine/Network/EInterpolate.h index 65038e49..93bf1a5c 100644 --- a/include/Engine/Network/EInterpolate.h +++ b/include/Engine/Network/EInterpolate.h @@ -12,7 +12,7 @@ namespace Events struct Interpolate : Event { EntityID Entity; - boost::shared_array DataArray; + boost::shared_array DataArray; }; } diff --git a/src/Game/CMakeLists.txt b/src/Game/CMakeLists.txt index 04146670..769cbd4f 100644 --- a/src/Game/CMakeLists.txt +++ b/src/Game/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCE_FILES "Game.cpp" "HealthSystem.cpp" "PlayerSystem.cpp" + "InterpolationSystem.cpp" ) set(LIBRARIES From 765509b51095da7c96cf815e0a44778fc907f429 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 18 Jan 2016 17:34:17 +0100 Subject: [PATCH 12/22] Added interpolationsystem to pipeline. --- include/Game/Game.h | 2 +- src/Engine/Network/Client.cpp | 1 + src/Game/Game.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Game/Game.h b/include/Game/Game.h index dfe1cff6..6614957f 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -20,7 +20,7 @@ #include "Core/EntityFile.h" #include "Rendering/RenderSystem.h" #include "Core/EntityFileParser.h" - +#include "InterpolationSystem.h" // Network #include #include "Network/Network.h" diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 9ffd570b..139d15ae 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -33,6 +33,7 @@ void Client::Start(World* world, EventBroker* eventBroker) void Client::Update() { + m_EventBroker->Process(); readFromServer(); } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index ba660a7d..7ccd7fac 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -66,6 +66,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); //Collision and TriggerSystem should update after player. ++updateOrderLevel; @@ -119,7 +120,6 @@ void Game::Tick() // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); m_Renderer->Update(dt); - m_EventBroker->Process(); GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(*m_RenderFrame); From 3e90ed564c0de4288e29f84087fd481c596681d3 Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 18 Jan 2016 18:07:39 +0100 Subject: [PATCH 13/22] Moved Struct in InterpolationSystem.h and fixed bug. --- include/Game/InterpolationSystem.h | 14 ++++++++------ src/Game/InterpolationSystem.cpp | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/Game/InterpolationSystem.h b/include/Game/InterpolationSystem.h index c87ee5a7..2acea373 100644 --- a/include/Game/InterpolationSystem.h +++ b/include/Game/InterpolationSystem.h @@ -12,15 +12,17 @@ #include "Network/EInterpolate.h" -struct Transform { - glm::vec3 Position; - glm::vec3 Scale; - glm::vec3 Orientation; - double interpolationTime; -}; class InterpolationSystem : public PureSystem { + struct Transform + { + glm::vec3 Position; + glm::vec3 Scale; + glm::vec3 Orientation; + double interpolationTime; + }; + public: InterpolationSystem(EventBroker* eventbroker) : PureSystem(eventbroker, "Transform") diff --git a/src/Game/InterpolationSystem.cpp b/src/Game/InterpolationSystem.cpp index d2d81fda..72207531 100644 --- a/src/Game/InterpolationSystem.cpp +++ b/src/Game/InterpolationSystem.cpp @@ -16,7 +16,7 @@ void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & tran } glm::vec3 nextPosition = sTransform.Position; glm::vec3 currentPosition = static_cast(transform["Position"]); - transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); + (glm::vec3&)transform["Position"] += vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); } } @@ -37,6 +37,7 @@ bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) memcpy(&transform.Orientation, e.DataArray.get() + offset, sizeof(glm::vec3)); offset += sizeof(glm::vec3); memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); + transform.interpolationTime = 0.0f; // Check if queue already exists if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue From 88eb3ca2dbf3d4da34aed86a985ccc386e7c9632 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 18 Jan 2016 18:07:59 +0100 Subject: [PATCH 14/22] Scraping queues for interpolation --- include/Game/InterpolationSystem.h | 16 ++++---- src/Engine/Network/Packet.cpp | 8 ++-- src/Engine/Network/Server.cpp | 4 +- src/Game/InterpolationSystem.cpp | 60 ++++++++++++++++++------------ 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/include/Game/InterpolationSystem.h b/include/Game/InterpolationSystem.h index c87ee5a7..3984ab5e 100644 --- a/include/Game/InterpolationSystem.h +++ b/include/Game/InterpolationSystem.h @@ -12,15 +12,14 @@ #include "Network/EInterpolate.h" -struct Transform { - glm::vec3 Position; - glm::vec3 Scale; - glm::vec3 Orientation; - double interpolationTime; -}; - class InterpolationSystem : public PureSystem { + struct Transform { + glm::vec3 Position; + glm::vec3 Scale; + glm::vec3 Orientation; + double interpolationTime; + }; public: InterpolationSystem(EventBroker* eventbroker) : PureSystem(eventbroker, "Transform") @@ -31,7 +30,8 @@ public: virtual void UpdateComponent(World* world, ComponentWrapper& transform, double dt) override; private: - std::unordered_map> m_InterpolationPoints; + //std::unordered_map> m_InterpolationPoints; + std::unordered_map m_InterpolationPoints; glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 2b2c7938..568a78e3 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -40,7 +40,7 @@ void Packet::WriteString(const std::string& str) // Message, add one extra byte for null terminator int sizeOfString = str.size() + 1; if (m_Offset + sizeOfString > m_MaxPacketSize) { - LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); + //LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); resizeData(); } memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char)); @@ -50,7 +50,7 @@ void Packet::WriteString(const std::string& str) void Packet::WriteData(char * data, int sizeOfData) { if (m_Offset + sizeOfData > m_MaxPacketSize) { - LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); + //LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); resizeData(); } memcpy(m_Data + m_Offset, data, sizeOfData); @@ -61,7 +61,7 @@ std::string Packet::ReadString() { std::string returnValue(m_Data + m_ReturnDataOffset); if (m_Offset < m_ReturnDataOffset + returnValue.size()) { - LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom"); + //LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom"); return "PopFrontString Failed"; } // +1 for null terminator. @@ -72,7 +72,7 @@ std::string Packet::ReadString() char * Packet::ReadData(int SizeOfData) { if (m_Offset < m_ReturnDataOffset + SizeOfData) { - LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom"); + //LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom"); return nullptr; } unsigned int oldReturnDataOffset = m_ReturnDataOffset; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 9ec1a041..1f9db461 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -227,7 +227,7 @@ void Server::parseOnInputCommand(Packet& packet) e.PlayerID = playerID; // Set correct player id e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); - LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); } } } @@ -239,7 +239,7 @@ void Server::parseOnPlayerDamage(Packet & packet) e.PlayerDamagedID = packet.ReadPrimitive(); e.TypeOfDamage = packet.ReadString(); m_EventBroker->Publish(e); - LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); + //LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); } void Server::parseConnect(Packet& packet) diff --git a/src/Game/InterpolationSystem.cpp b/src/Game/InterpolationSystem.cpp index d2d81fda..d2413234 100644 --- a/src/Game/InterpolationSystem.cpp +++ b/src/Game/InterpolationSystem.cpp @@ -1,23 +1,32 @@ #include "InterpolationSystem.h" +//void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & transform, double dt) +//{ +// if (m_InterpolationPoints[transform.EntityID].size() > 0) { +// Transform& sTransform = m_InterpolationPoints[transform.EntityID].front(); +// sTransform.interpolationTime += dt; +// if (sTransform.interpolationTime > 0.05) { +// double time = std::fmod(sTransform.interpolationTime, 0.05f); +// m_InterpolationPoints[transform.EntityID].pop(); +// if (m_InterpolationPoints[transform.EntityID].size() <= 0) { +// return; +// } +// sTransform = m_InterpolationPoints[transform.EntityID].front(); +// sTransform.interpolationTime = time; +// } +// glm::vec3 nextPosition = sTransform.Position; +// glm::vec3 currentPosition = static_cast(transform["Position"]); +// transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); +// } +//} + void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & transform, double dt) { - if (m_InterpolationPoints[transform.EntityID].size() > 0) { - Transform& sTransform = m_InterpolationPoints[transform.EntityID].front(); - sTransform.interpolationTime += dt; - if (sTransform.interpolationTime > 0.05) { - double time = std::fmod(sTransform.interpolationTime, 0.05f); - m_InterpolationPoints[transform.EntityID].pop(); - if (m_InterpolationPoints[transform.EntityID].size() <= 0) { - return; - } - sTransform = m_InterpolationPoints[transform.EntityID].front(); - sTransform.interpolationTime = time; - } - glm::vec3 nextPosition = sTransform.Position; - glm::vec3 currentPosition = static_cast(transform["Position"]); - transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); - } + Transform& sTransform = m_InterpolationPoints[transform.EntityID]; + sTransform.interpolationTime += dt; + glm::vec3 nextPosition = sTransform.Position; + glm::vec3 currentPosition = static_cast(transform["Position"]); + transform["Position"] = vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); } glm::vec3 InterpolationSystem::vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime) @@ -37,14 +46,17 @@ bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) memcpy(&transform.Orientation, e.DataArray.get() + offset, sizeof(glm::vec3)); offset += sizeof(glm::vec3); memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); - + transform.interpolationTime = 0; + m_InterpolationPoints[e.Entity] = transform; // Check if queue already exists - if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue - m_InterpolationPoints[e.Entity].push(transform); - } else { // Did not exist, create queue - std::queue transformQueue; - transformQueue.push(transform); - m_InterpolationPoints[e.Entity] = transformQueue; - } + //if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue + // m_InterpolationPoints[e.Entity].push(transform); + //} + + //else { // Did not exist, create queue + // std::queue transformQueue; + // transformQueue.push(transform); + // m_InterpolationPoints[e.Entity] = transformQueue; + //} return false; } From 3142c701e3c68553094c783e0d2b77ee4e3fc37c Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 19 Jan 2016 11:42:30 +0100 Subject: [PATCH 15/22] WIP interpolating scale and orientation --- include/Game/InterpolationSystem.h | 13 +++++++++++-- src/Game/InterpolationSystem.cpp | 30 +++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/Game/InterpolationSystem.h b/include/Game/InterpolationSystem.h index c8e88834..73329094 100644 --- a/include/Game/InterpolationSystem.h +++ b/include/Game/InterpolationSystem.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "Common.h" #include "Core/System.h" @@ -12,6 +13,7 @@ #include "Network/EInterpolate.h" +#define SNAPSHOTINTERVAL 0.05f class InterpolationSystem : public PureSystem { @@ -19,7 +21,7 @@ class InterpolationSystem : public PureSystem { glm::vec3 Position; glm::vec3 Scale; - glm::vec3 Orientation; + glm::quat Orientation; double interpolationTime; }; public: @@ -35,7 +37,14 @@ private: //std::unordered_map> m_InterpolationPoints; std::unordered_map m_InterpolationPoints; - glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); + //glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); + template + T vectorInterpolation(T prev, T next, double currentTime) + { + T difference = next - prev; + T vector = (difference / SNAPSHOTINTERVAL) * static_cast(currentTime); + return vector; + } EventRelay m_EInterpolate; bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e); diff --git a/src/Game/InterpolationSystem.cpp b/src/Game/InterpolationSystem.cpp index 2d8de336..d3592132 100644 --- a/src/Game/InterpolationSystem.cpp +++ b/src/Game/InterpolationSystem.cpp @@ -24,17 +24,27 @@ void InterpolationSystem::UpdateComponent(World * world, ComponentWrapper & tran { Transform& sTransform = m_InterpolationPoints[transform.EntityID]; sTransform.interpolationTime += dt; + // Position glm::vec3 nextPosition = sTransform.Position; glm::vec3 currentPosition = static_cast(transform["Position"]); - (glm::vec3&)transform["Position"] += vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); + (glm::vec3&)transform["Position"] += vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); + // Orientation + glm::quat nextOrientation = sTransform.Orientation; + glm::quat currentOrientation = glm::quat(static_cast(transform["Orientation"])); + (glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp(currentOrientation, nextOrientation, sTransform.interpolationTime / SNAPSHOTINTERVAL)); + // Scale + glm::vec3 nextScale = sTransform.Scale; + glm::vec3 currentScale = static_cast(transform["Scale"]); + //glm::vec3 resize = vectorInterpolation(currentScale, nextScale, sTransform.interpolationTime); + (glm::vec3&)transform["Scale"] += vectorInterpolation(currentScale, nextScale, sTransform.interpolationTime); } -glm::vec3 InterpolationSystem::vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime) -{ - glm::vec3 difference = next - prev; - glm::vec3 position = difference / 0.05f * static_cast(currentTime); - return position; -} +//glm::vec3 InterpolationSystem::vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime) +//{ +// glm::vec3 difference = next - prev; +// glm::vec3 position = difference / SNAPSHOTINTERVAL * static_cast(currentTime); +// return position; +//} bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) { @@ -43,9 +53,11 @@ bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) // Read the data memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3)); offset += sizeof(glm::vec3); - memcpy(&transform.Orientation, e.DataArray.get() + offset, sizeof(glm::vec3)); + glm::vec3 tempOrientation; + memcpy(&tempOrientation, e.DataArray.get() + offset, sizeof(glm::vec3)); + transform.Orientation = glm::quat(tempOrientation); offset += sizeof(glm::vec3); - memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); + memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); transform.interpolationTime = 0.0f; m_InterpolationPoints[e.Entity] = transform; // Check if queue already exists From ad9bb5fba49a0c3127e586145e681894b115bc92 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 19 Jan 2016 15:03:10 +0100 Subject: [PATCH 16/22] Added an extra interpolation point. --- include/Game/Systems/InterpolationSystem.h | 4 +-- src/Game/Systems/InterpolationSystem.cpp | 37 ++++++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/include/Game/Systems/InterpolationSystem.h b/include/Game/Systems/InterpolationSystem.h index 15b8d167..fb7654b2 100644 --- a/include/Game/Systems/InterpolationSystem.h +++ b/include/Game/Systems/InterpolationSystem.h @@ -34,8 +34,8 @@ public: ~InterpolationSystem() { } virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& transform, double dt) override; private: - //std::unordered_map> m_InterpolationPoints; - std::unordered_map m_InterpolationPoints; + std::unordered_map m_NextTransform; + std::unordered_map m_LastReceivedTransform; //glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); template diff --git a/src/Game/Systems/InterpolationSystem.cpp b/src/Game/Systems/InterpolationSystem.cpp index 7676491f..f6d5989d 100644 --- a/src/Game/Systems/InterpolationSystem.cpp +++ b/src/Game/Systems/InterpolationSystem.cpp @@ -22,9 +22,20 @@ void InterpolationSystem::UpdateComponent(World * world, EntityWrapper& entity, ComponentWrapper & transform, double dt) { - if (m_InterpolationPoints.find(transform.EntityID) != m_InterpolationPoints.end()) { // Exists in map - Transform& sTransform = m_InterpolationPoints[transform.EntityID]; - sTransform.interpolationTime += dt; + if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map + m_NextTransform[transform.EntityID].interpolationTime += dt; + Transform sTransform = m_NextTransform[transform.EntityID]; + double time = sTransform.interpolationTime; + if (time > SNAPSHOTINTERVAL) { + if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) { + m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID]; + m_NextTransform[transform.EntityID].interpolationTime = time - SNAPSHOTINTERVAL; + sTransform = m_NextTransform[transform.EntityID]; + m_LastReceivedTransform.erase(transform.EntityID); + } else { + m_NextTransform.erase(transform.EntityID); + } + } if (transform.Info.Name == "Transform") { // Position glm::vec3 nextPosition = sTransform.Position; @@ -38,23 +49,10 @@ void InterpolationSystem::UpdateComponent(World * world, EntityWrapper& entity, glm::vec3 nextScale = sTransform.Scale; glm::vec3 currentScale = static_cast(transform["Scale"]); (glm::vec3&)transform["Scale"] += vectorInterpolation(currentScale, nextScale, sTransform.interpolationTime); - int testVar = 0; - if (glm::isnan(resize.r) || glm::isnan(resize.g) || glm::isnan(resize.b)) { - //(glm::vec3&)transform["Scale"] = currentScale; - return; - } - += resize; } } } -//glm::vec3 InterpolationSystem::vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime) -//{ -// glm::vec3 difference = next - prev; -// glm::vec3 position = difference / SNAPSHOTINTERVAL * static_cast(currentTime); -// return position; -//} - bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) { Transform transform; @@ -68,7 +66,12 @@ bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) offset += sizeof(glm::vec3); memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); transform.interpolationTime = 0.0f; - m_InterpolationPoints[e.Entity] = transform; + + if (m_NextTransform.find(e.Entity) != m_NextTransform.end()) { // Did exist + m_LastReceivedTransform[e.Entity] = transform; + } else { // Did not + m_NextTransform[e.Entity] = transform; + } // Check if queue already exists //if (m_InterpolationPoints.find(e.Entity) != m_InterpolationPoints.end()) { // Did exist, push to queue // m_InterpolationPoints[e.Entity].push(transform); From f52cddb44592d64dabfa0133efbebb777f5594e9 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 20 Jan 2016 13:43:11 +0100 Subject: [PATCH 17/22] Added packet loss logic for multiple clients. Changed packet class to fit our needs. --- include/Engine/Network/Packet.h | 3 +- include/Engine/Network/PlayerDefinition.h | 2 + include/Engine/Network/Server.h | 8 ++-- src/Engine/Network/Client.cpp | 6 +-- src/Engine/Network/Packet.cpp | 21 +++++++++-- src/Engine/Network/Server.cpp | 46 ++++++++++++++++------- 6 files changed, 58 insertions(+), 28 deletions(-) diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index 112ebe34..2891bf87 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -14,6 +14,7 @@ public: Packet(MessageType type, unsigned int& packetID); // Used to create packet from already existing data buffer. Packet(char* data, const int sizeOfPacket); + Packet(MessageType type); ~Packet(); void Init(MessageType type, unsigned int& packetID); @@ -49,7 +50,7 @@ public: // Pops the first element as if it was a string. std::string ReadString(); char* ReadData(int SizeOfData); - + void ChangePacketID(unsigned int& packetID); int Size() { return m_Offset; }; char* Data() { return m_Data; }; unsigned int DataReadSize() { return m_ReturnDataOffset; } diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index dbacda95..4b8b8e6e 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -6,6 +6,8 @@ struct PlayerDefinition { int EntityID = -1; std::string Name = ""; boost::asio::ip::udp::endpoint Endpoint; + unsigned int PacketID; + std::clock_t StopTime; }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 9aba921a..3b871e43 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -43,16 +43,14 @@ private: //Timers std::clock_t m_StartPingTime; - std::clock_t m_StopTimes[8]; // Game logic World* m_World; EventBroker* m_EventBroker; // Packet loss logic - unsigned int m_PacketID; - unsigned int m_PreviousPacketID; - unsigned int m_SendPacketID; + unsigned int m_PacketID = 0; + unsigned int m_PreviousPacketID = 0; // Private member functions int receive(char* data, size_t length); @@ -73,8 +71,8 @@ private: void parseServerPing(); void identifyPacketLoss(); EntityID createPlayer(); + int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); // Debug event - EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index ae71d0ae..fd6825b5 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -57,9 +57,7 @@ void Client::parseMessageType(Packet& packet) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id - if (m_PacketID <= m_PreviousPacketID) - return; - //IdentifyPacketLoss(); + identifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: @@ -282,7 +280,7 @@ void Client::identifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - LOG_INFO("%i Packet(s) were lost...", difference); + LOG_INFO("%i Packet(s) were lost...", difference -1); } } diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 568a78e3..6308a130 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -17,20 +17,26 @@ Packet::Packet(char* data, const int sizeOfPacket) m_Offset = sizeOfPacket; } +Packet::Packet(MessageType type) +{ + m_Data = new char[m_MaxPacketSize]; + unsigned int dummy = 0; + Init(type, dummy); +} + Packet::~Packet() { delete[] m_Data; } void Packet::Init(MessageType type, unsigned int & packetID) -{ +{ m_ReturnDataOffset = 0; m_Offset = 0; // Create message header // Add message type int messageType = static_cast(type); Packet::WritePrimitive(messageType); - packetID = packetID % 1000; // Packet id modulos Packet::WritePrimitive(packetID); packetID++; } @@ -80,14 +86,21 @@ char * Packet::ReadData(int SizeOfData) return (m_Data + oldReturnDataOffset); } +void Packet::ChangePacketID(unsigned int & packetID) +{ + packetID = packetID + 1; + // Overwrite old PacketID + memcpy(m_Data + sizeof(int), &packetID, sizeof(int)); +} + void Packet::resizeData() -{ +{ // Allocate memory to store our data in char* holdData = new char[m_MaxPacketSize]; // Copy our data to the newly allocated memory memcpy(holdData, m_Data, m_Offset); - // Increase max packet size + // Increase max packet size m_MaxPacketSize = m_MaxPacketSize * 2; // Delete our data delete m_Data; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 1f9db461..ce3a735c 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -16,7 +16,7 @@ void Server::Start(World* world, EventBroker* eventBroker) // Subscribe to events EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); for (size_t i = 0; i < MAXCONNECTIONS; i++) { - m_StopTimes[i] = std::clock(); + m_PlayerDefinitions[i].StopTime = std::clock(); } LOG_INFO("I am Server. BIP BOP\n"); } @@ -66,7 +66,7 @@ void Server::parseMessageType(Packet& packet) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id - //IdentifyPacketLoss(); + //identifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: parseConnect(packet); @@ -126,6 +126,7 @@ void Server::broadcast(Packet& packet) { for (int i = 0; i < MAXCONNECTIONS; ++i) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { + packet.ChangePacketID(m_PlayerDefinitions[i].PacketID); send(packet, i); } } @@ -137,7 +138,7 @@ void Server::sendSnapshot() // Should time this std::unordered_map worldComponentPools = m_World->GetComponentPools(); for (auto& it : worldComponentPools) { - Packet packet(MessageType::Snapshot, m_SendPacketID); + Packet packet(MessageType::Snapshot); ComponentPool* componentPool = it.second; ComponentInfo componentInfo = componentPool->ComponentInfo(); // Component Type @@ -166,12 +167,12 @@ void Server::sendPing() // Prints connected players ping for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PacketID, i, ping); + int ping = 1000 * (m_PlayerDefinitions[i].StopTime - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PlayerDefinitions[i].PacketID, i, ping); } } // Create ping message - Packet packet(MessageType::ServerPing, m_SendPacketID); + Packet packet(MessageType::ServerPing); packet.WriteString("Ping from server"); // Time message m_StartPingTime = std::clock(); @@ -187,8 +188,8 @@ void Server::checkForTimeOuts() for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - int stopPing = 1000 * m_StopTimes[i] - / static_cast(CLOCKS_PER_SEC); + int stopPing = 1000 * m_PlayerDefinitions[i].StopTime / + static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + timeOutTimeMs) { LOG_INFO("Player %i timed out!", i); disconnect(i); @@ -206,6 +207,7 @@ void Server::disconnect(int i) m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].Name = ""; + m_PlayerDefinitions[i].PacketID = 0; } void Server::parseOnInputCommand(Packet& packet) @@ -259,19 +261,20 @@ void Server::parseConnect(Packet& packet) m_PlayerDefinitions[i].EntityID = createPlayer(); m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = packet.ReadString(); + m_PlayerDefinitions[i].PacketID = 0; - m_StopTimes[i] = std::clock(); + m_PlayerDefinitions[i].StopTime = std::clock(); LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); // Send a message to the player that connected - Packet packet(MessageType::Connect, m_SendPacketID); + Packet packet(MessageType::Connect, m_PlayerDefinitions[i].PacketID); packet.WritePrimitive(i); // Player ID packet.WritePrimitive(m_PlayerDefinitions[i].EntityID); // Entity ID send(packet, i); // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected, m_PacketID); + Packet notificationPacket(MessageType::PlayerConnected); broadcast(notificationPacket); break; @@ -294,17 +297,21 @@ void Server::parseDisconnect() void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); + int playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); + if (playerID == -1) { + return; + } // Return ping - Packet packet(MessageType::ClientPing, m_SendPacketID); + Packet packet(MessageType::ClientPing, m_PlayerDefinitions[playerID].PacketID); packet.WriteString("Ping received"); - send(packet); // This dosen't work for multiple users + send(packet); } void Server::parseServerPing() { for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - m_StopTimes[i] = std::clock(); + m_PlayerDefinitions[i].StopTime = std::clock(); break; } } @@ -331,6 +338,17 @@ EntityID Server::createPlayer() return entityID; } +int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) +{ + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() && + m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) { + return i; + } + } + return -1; +} + bool Server::OnInputCommand(const Events::InputCommand & e) { //LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); From e9a576341e4a8f3a1d8e203b4192b3b99198c970 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 20 Jan 2016 14:31:50 +0100 Subject: [PATCH 18/22] Started on server disconnect logic. --- src/Engine/Network/Server.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index ce3a735c..c598f1f1 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -189,7 +189,7 @@ void Server::checkForTimeOuts() for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { int stopPing = 1000 * m_PlayerDefinitions[i].StopTime / - static_cast(CLOCKS_PER_SEC); + static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + timeOutTimeMs) { LOG_INFO("Player %i timed out!", i); disconnect(i); @@ -201,7 +201,7 @@ void Server::checkForTimeOuts() void Server::disconnect(int i) { //broadcast("A player disconnected"); - LOG_INFO("Player %i disconnected/timed out", i); + LOG_INFO("Player %s disconnected/timed out", m_PlayerDefinitions[i].Name.c_str()); // Remove enteties and stuff m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); @@ -216,7 +216,7 @@ void Server::parseOnInputCommand(Packet& packet) // Check which player it was who sent the message for (int i = 0; i < MAXCONNECTIONS; i++) { // if the player is connected set playerID to the correct PlayerID - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address() + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address() && m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) { playerID = i; break; @@ -248,13 +248,11 @@ void Server::parseConnect(Packet& packet) { LOG_INFO("Parsing connections"); // Check if player is already connected - for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address() && - m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) { - return; - } + if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { + return; } + // Find an empty spot to put the player in for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { // Create new player @@ -298,13 +296,13 @@ void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); int playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - if (playerID == -1) { + if (playerID == -1) { return; } // Return ping Packet packet(MessageType::ClientPing, m_PlayerDefinitions[playerID].PacketID); packet.WriteString("Ping received"); - send(packet); + send(packet); } void Server::parseServerPing() @@ -351,6 +349,6 @@ int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) bool Server::OnInputCommand(const Events::InputCommand & e) { - //LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } From 7e7ca7edcf79529c6afaed534eb544f493b782f2 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 20 Jan 2016 14:32:04 +0100 Subject: [PATCH 19/22] Listening to "DisconnectFromServer" --- src/Engine/Network/Client.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index ae71d0ae..83e0d886 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -57,9 +57,7 @@ void Client::parseMessageType(Packet& packet) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id - if (m_PacketID <= m_PreviousPacketID) - return; - //IdentifyPacketLoss(); + identifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: @@ -240,8 +238,7 @@ void Client::connect() void Client::disconnect() { - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString("+Disconnect"); + Packet packet(MessageType::Disconnect, m_SendPacketID); send(packet); } @@ -256,9 +253,16 @@ void Client::ping() bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "ConnectToServer") { // Connect for now - connect(); + if (e.Value > 0) { + connect(); + } //LOG_DEBUG("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 == "DisconnectFromServer") { + if (e.Value > 0) { + disconnect(); + } + return true; } else { m_InputCommandBuffer.push_back(e); //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); @@ -282,7 +286,7 @@ void Client::identifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - LOG_INFO("%i Packet(s) were lost...", difference); + LOG_INFO("%i Packet(s) were lost...", difference - 1); } } From 25d2aa34644b50d9ae23169e75616eba06523267 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 20 Jan 2016 16:27:23 +0100 Subject: [PATCH 20/22] =?UTF-8?q?"Supporting"=20spectators.=20Using=20a=20?= =?UTF-8?q?vector=20for=20connected=20units=20as=20we=20do=20not=20interpr?= =?UTF-8?q?et=20as=20players.=20=E2=80=9C=E2=80=9C=E2=80=9D=CC=BF=20=CC=BF?= =?UTF-8?q?=20=CC=BF=20=CC=BF=20=CC=BF=E2=80=99=CC=BF=E2=80=99=CC=B5=CD=87?= =?UTF-8?q?=CC=BF=CC=BF=D0=B7=3D(=E2=80=A2=CC=AA=E2=97=8F)=3D=CE=B5/=CC=B5?= =?UTF-8?q?=CD=87=CC=BF=CC=BF/=CC=BF=20=CC=BF=20=CC=BF=20=CC=BF=20=CC=BF?= =?UTF-8?q?=E2=80=99=E2=80=9C=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Engine/Network/Server.h | 3 +- src/Engine/Network/Client.cpp | 5 +- src/Engine/Network/Server.cpp | 90 ++++++++++++++++----------------- 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 3b871e43..ec1a173a 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -27,9 +27,10 @@ private: boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; - PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; // Sending messages to client logic + PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; + std::vector m_ConnectedUsers; char readBuffer[INPUTSIZE] = { 0 }; int bytesRead = 0; // time for previouse message diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 83e0d886..b6dea8e3 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -85,11 +85,8 @@ void Client::parseMessageType(Packet& packet) void Client::parseConnect(Packet& packet) { - // Set your own player id - m_PlayerID = packet.ReadPrimitive(); - m_ServerEntityID = packet.ReadPrimitive(); // Map ServerEntityID and your PlayerID - LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); + LOG_INFO("I be connected PogChamp"); } void Client::parsePlayerConnected(Packet & packet) diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index c598f1f1..4a2dcf96 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -8,7 +8,6 @@ Server::~Server() } - void Server::Start(World* world, EventBroker* eventBroker) { m_World = world; @@ -104,11 +103,11 @@ int Server::receive(char * data, size_t length) return length; } -void Server::send(Packet& packet, int playerID) +void Server::send(Packet& packet, int userID) { int bytesSent = m_Socket.send_to( boost::asio::buffer(packet.Data(), packet.Size()), - m_PlayerDefinitions[playerID].Endpoint, + m_ConnectedUsers[userID].Endpoint, 0); } @@ -124,9 +123,9 @@ void Server::send(Packet & packet) void Server::broadcast(Packet& packet) { - for (int i = 0; i < MAXCONNECTIONS; ++i) { - if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - packet.ChangePacketID(m_PlayerDefinitions[i].PacketID); + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { + packet.ChangePacketID(m_ConnectedUsers[i].PacketID); send(packet, i); } } @@ -165,10 +164,10 @@ void Server::sendSnapshot() void Server::sendPing() { // Prints connected players ping - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - int ping = 1000 * (m_PlayerDefinitions[i].StopTime - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PlayerDefinitions[i].PacketID, i, ping); + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { + int ping = 1000 * (m_ConnectedUsers[i].StopTime - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedUsers[i].PacketID, i, ping); } } // Create ping message @@ -186,12 +185,12 @@ void Server::checkForTimeOuts() int startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - int stopPing = 1000 * m_PlayerDefinitions[i].StopTime / + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { + int stopPing = 1000 * m_ConnectedUsers[i].StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + timeOutTimeMs) { - LOG_INFO("Player %i timed out!", i); + LOG_INFO("User %i timed out!", i); disconnect(i); } } @@ -201,13 +200,13 @@ void Server::checkForTimeOuts() void Server::disconnect(int i) { //broadcast("A player disconnected"); - LOG_INFO("Player %s disconnected/timed out", m_PlayerDefinitions[i].Name.c_str()); - - // Remove enteties and stuff + LOG_INFO("User %s disconnected/timed out", m_PlayerDefinitions[i].Name.c_str()); + // Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have) m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].Name = ""; m_PlayerDefinitions[i].PacketID = 0; + m_ConnectedUsers.erase(m_ConnectedUsers.begin() + i); } void Server::parseOnInputCommand(Packet& packet) @@ -251,41 +250,38 @@ void Server::parseConnect(Packet& packet) if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { return; } - - // Find an empty spot to put the player in - for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { - // Create new player - m_PlayerDefinitions[i].EntityID = createPlayer(); - m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; - m_PlayerDefinitions[i].Name = packet.ReadString(); - m_PlayerDefinitions[i].PacketID = 0; - - m_PlayerDefinitions[i].StopTime = std::clock(); - - LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); - - // Send a message to the player that connected - Packet packet(MessageType::Connect, m_PlayerDefinitions[i].PacketID); - packet.WritePrimitive(i); // Player ID - packet.WritePrimitive(m_PlayerDefinitions[i].EntityID); // Entity ID - send(packet, i); - - // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); - - break; + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address() && + m_ConnectedUsers[i].Endpoint.port() == m_ReceiverEndpoint.port()) { + // Already connected + return; } } + // Create a new player + PlayerDefinition pd; + pd.EntityID = 0; // Overlook this + pd.Endpoint = m_ReceiverEndpoint; + pd.Name = packet.ReadString(); + pd.PacketID = 0; + pd.StopTime = std::clock(); + m_ConnectedUsers.push_back(pd); + LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); + + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, m_ConnectedUsers[m_ConnectedUsers.size() - 1].PacketID); + send(connnectPacket); + + // Send notification that a player has connected + Packet notificationPacket(MessageType::PlayerConnected); + broadcast(notificationPacket); } void Server::parseDisconnect() { LOG_INFO("%i: Parsing disconnect", m_PacketID); - for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) { disconnect(i); break; } @@ -307,9 +303,9 @@ void Server::parseClientPing() void Server::parseServerPing() { - for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - m_PlayerDefinitions[i].StopTime = std::clock(); + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) { + m_ConnectedUsers[i].StopTime = std::clock(); break; } } From 3376f4a16ee10fbe5ea6d11b44d12a086ea061bf Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 20 Jan 2016 16:27:53 +0100 Subject: [PATCH 21/22] Added server has timed out logic to client. (>'')> --- include/Engine/Network/Client.h | 5 ++-- include/Engine/Network/Network.h | 1 + include/Engine/Network/Server.h | 2 +- src/Engine/Network/Client.cpp | 40 +++++++++++++++++++++----------- src/Engine/Network/Server.cpp | 3 +-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 73f0eb50..511ce5f7 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -48,6 +48,7 @@ private: std::string m_PlayerName; int m_PlayerID = -1; EntityID m_ServerEntityID = std::numeric_limits::max(); + bool m_IsConnected = false; // Server Client Lookup map // Assumes that root node for client and server is EntityID 0. @@ -71,14 +72,14 @@ private: void ping(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); - void parseConnect(Packet& packet); + void parseConnect(Packet& packet); void parsePlayerConnected(Packet& packet); void parsePing(); void parseServerPing(); void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); void identifyPacketLoss(); - bool isConnected(); + bool hasServerTimedOut(); EntityID createPlayer(); void sendInputCommands(); // Mapping Logic diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index cb86b941..1464a96f 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -7,6 +7,7 @@ #define MAXCONNECTIONS 8 #define INPUTSIZE 4097 +#define TIMEOUTMS 15000 class Network { diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 3b871e43..2f21816a 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -11,7 +11,7 @@ #include "Network/PlayerDefinition.h" #include "Core/World.h" #include "Core/EventBroker.h" -#include "Network/Network.h" +#include "../Network/Network.h" #include "Input/EInputCommand.h" #include "Core/EPlayerDamage.h" diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 83e0d886..a5c34963 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -35,6 +35,9 @@ void Client::Update() { m_EventBroker->Process(); readFromServer(); + if (m_IsConnected) { + hasServerTimedOut(); + } } void Client::readFromServer() @@ -86,10 +89,8 @@ void Client::parseMessageType(Packet& packet) void Client::parseConnect(Packet& packet) { // Set your own player id - m_PlayerID = packet.ReadPrimitive(); - m_ServerEntityID = packet.ReadPrimitive(); // Map ServerEntityID and your PlayerID - LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); + LOG_INFO("I are connected PogChamp"); } void Client::parsePlayerConnected(Packet & packet) @@ -100,12 +101,18 @@ void Client::parsePlayerConnected(Packet & packet) void Client::parsePing() { - m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime); + } void Client::parseServerPing() { + // Might miss connect message so set it here instead. + m_IsConnected = true; + // Time since last ping was received + m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime); + m_StartPingTime = std::clock(); + Packet packet(MessageType::ServerPing, m_SendPacketID); packet.WriteString("Ping recieved"); send(packet); @@ -238,16 +245,18 @@ void Client::connect() void Client::disconnect() { + m_PreviousPacketID = 0; + m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); send(packet); } void Client::ping() { - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString("Ping"); - m_StartPingTime = std::clock(); - send(packet); + //Packet packet(MessageType::Connect, m_SendPacketID); + //packet.WriteString("Ping"); + //m_StartPingTime = std::clock(); + //send(packet); } bool Client::OnInputCommand(const Events::InputCommand & e) @@ -290,12 +299,15 @@ void Client::identifyPacketLoss() } } -bool Client::isConnected() +bool Client::hasServerTimedOut() { - if (m_PlayerID != -1) { - if (m_PlayerDefinitions[m_PlayerID].EntityID != -1) { - return true; - } + // Time in ms + float timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + if (timeSincePing > TIMEOUTMS) { + // Clear everything and go to menu. + LOG_INFO("Server has timed out, returning to menu, Beep Boop."); + m_IsConnected = false; + return true; } return false; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index c598f1f1..ec593cb7 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -182,7 +182,6 @@ void Server::sendPing() void Server::checkForTimeOuts() { - int timeOutTimeMs = 5000; int startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); @@ -190,7 +189,7 @@ void Server::checkForTimeOuts() if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { int stopPing = 1000 * m_PlayerDefinitions[i].StopTime / static_cast(CLOCKS_PER_SEC); - if (startPing > stopPing + timeOutTimeMs) { + if (startPing > stopPing + TIMEOUTMS) { LOG_INFO("Player %i timed out!", i); disconnect(i); } From cd6725317325f3616e90a0bea1325160a4a52587 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 20 Jan 2016 17:41:16 +0100 Subject: [PATCH 22/22] Added logic to go from spectator to player. --- include/Engine/Network/Client.h | 1 + include/Engine/Network/MessageType.h | 3 +- include/Engine/Network/Server.h | 2 +- src/Engine/Network/Client.cpp | 12 ++++++- src/Engine/Network/Server.cpp | 52 +++++++++++++++++++++------- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 511ce5f7..96511baa 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -82,6 +82,7 @@ private: bool hasServerTimedOut(); EntityID createPlayer(); void sendInputCommands(); + void becomePlayer(); // Mapping Logic // Returns if local EntityID exist in map bool clientServerMapsHasEntity(EntityID clientEntityID); diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index ba9684d9..f0026190 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -13,7 +13,8 @@ enum class MessageType Snapshot, OnInputCommand, OnPlayerDamage, - PlayerConnected + PlayerConnected, + BecomePlayer }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index e4d11334..8aabceba 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -71,7 +71,7 @@ private: void parseClientPing(); void parseServerPing(); void identifyPacketLoss(); - EntityID createPlayer(); + void createPlayer(); int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); // Debug event EventRelay m_EInputCommand; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 5aec3145..8eee335e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -35,7 +35,7 @@ void Client::Update() { m_EventBroker->Process(); readFromServer(); - if (m_IsConnected) { + if (m_IsConnected) { hasServerTimedOut(); } } @@ -271,6 +271,10 @@ bool Client::OnInputCommand(const Events::InputCommand & e) disconnect(); } return true; + } else if (e.Command == "SwitchToPlayer") { + if (e.Value > 0) { + becomePlayer(); + } } else { m_InputCommandBuffer.push_back(e); //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); @@ -334,6 +338,12 @@ void Client::sendInputCommands() } } +void Client::becomePlayer() +{ + Packet packet = Packet(MessageType::BecomePlayer, m_SendPacketID); + send(packet); +} + bool Client::clientServerMapsHasEntity(EntityID clientEntityID) { return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end(); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 71ca7252..8a194c0e 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -89,6 +89,9 @@ void Server::parseMessageType(Packet& packet) case MessageType::OnPlayerDamage: parseOnPlayerDamage(packet); break; + case MessageType::BecomePlayer: + createPlayer(); + break; default: break; } @@ -123,8 +126,8 @@ void Server::send(Packet & packet) void Server::broadcast(Packet& packet) { - for (int i = 0; i < m_ConnectedUsers.size(); i++) { - if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { + for (int i = 0; i < m_ConnectedUsers.size(); i++) { + if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { packet.ChangePacketID(m_ConnectedUsers[i].PacketID); send(packet, i); } @@ -167,7 +170,7 @@ void Server::sendPing() for (int i = 0; i < m_ConnectedUsers.size(); i++) { if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) { int ping = 1000 * (m_ConnectedUsers[i].StopTime - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedUsers[i].PacketID, i, ping); + LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedUsers[i].PacketID, i, std::abs(ping)); } } // Create ping message @@ -319,16 +322,41 @@ void Server::identifyPacketLoss() } } -EntityID Server::createPlayer() +void Server::createPlayer() { - EntityID entityID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); - transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; - model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); - return entityID; + if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { + // Already connected as player + LOG_WARNING("Already connected!"); + return; + } + int userIndex; + for (userIndex = 0; userIndex < m_ConnectedUsers.size(); userIndex++) { + if (m_ConnectedUsers[userIndex].Endpoint.address() == m_ReceiverEndpoint.address() && + m_ConnectedUsers[userIndex].Endpoint.port() == m_ReceiverEndpoint.port()) { + // Found user + break; + } + } + if (userIndex == m_ConnectedUsers.size()) { + LOG_WARNING("Not a recognized user!"); + return; + } + for (int playerIndex = 0; playerIndex < MAXCONNECTIONS; playerIndex++) { + if (m_PlayerDefinitions[playerIndex].Endpoint.address() == boost::asio::ip::address()) { + m_PlayerDefinitions[playerIndex] = m_ConnectedUsers[userIndex]; + EntityID entityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); + transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); + m_PlayerDefinitions[playerIndex].EntityID = entityID; + return; + } + } + LOG_WARNING("Server is full!"); + } int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)