Added packet loss logic for multiple clients.
Changed packet class to fit our needs.
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Server, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
};
|
||||
|
||||
@@ -57,9 +57,7 @@ void Client::parseMessageType(Packet& packet)
|
||||
// Read packet ID
|
||||
m_PreviousPacketID = m_PacketID; // Set previous packet id
|
||||
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
|
||||
if (m_PacketID <= m_PreviousPacketID)
|
||||
return;
|
||||
//IdentifyPacketLoss();
|
||||
identifyPacketLoss();
|
||||
|
||||
switch (static_cast<MessageType>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<int>(type);
|
||||
Packet::WritePrimitive<int>(messageType);
|
||||
packetID = packetID % 1000; // Packet id modulos
|
||||
Packet::WritePrimitive<int>(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;
|
||||
|
||||
@@ -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<int>(); //Read new packet id
|
||||
//IdentifyPacketLoss();
|
||||
//identifyPacketLoss();
|
||||
switch (static_cast<MessageType>(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<std::string, ComponentPool*> 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<double>(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<double>(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<double>(CLOCKS_PER_SEC);
|
||||
int stopPing = 1000 * m_PlayerDefinitions[i].StopTime /
|
||||
static_cast<double>(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<int>(i); // Player ID
|
||||
packet.WritePrimitive<EntityID>(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);
|
||||
|
||||
Reference in New Issue
Block a user