Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b547938928 | |||
| d1832c1741 | |||
| 4432891437 | |||
| a006db9e63 | |||
| 717af2c4a4 |
@@ -16,6 +16,8 @@ struct InputCommand : Event
|
||||
std::string Command;
|
||||
/** The value of the command. */
|
||||
float Value = 0;
|
||||
/** Timestamp of the command. */
|
||||
double TimeStamp = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ public:
|
||||
~Client();
|
||||
|
||||
void Connect(std::string address, int port);
|
||||
void Update() override;
|
||||
|
||||
void Update(double dt) override;
|
||||
private:
|
||||
std::vector<Events::PlayerSpawned> m_PlayerSpawnEvents;
|
||||
void parseSpawnEvents();
|
||||
// Save for children
|
||||
@@ -56,13 +56,13 @@ public:
|
||||
bool m_IsConnected = false;
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
// Server Client Lookup map
|
||||
// Assumes that root node for client and server is EntityID 0.
|
||||
|
||||
// Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!!
|
||||
std::unordered_map<EntityID, EntityID> m_ServerIDToClientID;
|
||||
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
|
||||
|
||||
// Network logic
|
||||
UDPClient m_Unreliable;
|
||||
TCPClient m_Reliable;
|
||||
PlayerDefinition m_PlayerDefinitions[8];
|
||||
SnapshotDefinitions m_NextSnapshot;
|
||||
double m_DurationOfPingTime;
|
||||
@@ -70,9 +70,9 @@ public:
|
||||
std::clock_t m_TimeSinceSentInputs;
|
||||
unsigned int m_SendInputIntervalMs;
|
||||
std::vector<Events::InputCommand> m_InputCommandBuffer;
|
||||
std::vector<Events::InputCommand> m_ReceivedInputCommands;
|
||||
|
||||
// Private member functions
|
||||
size_t receive(char* data);
|
||||
void disconnect();
|
||||
void parseMessageType(Packet& packet);
|
||||
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID);
|
||||
@@ -88,6 +88,8 @@ public:
|
||||
void parseComponentDeletion(Packet& packet);
|
||||
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
||||
void parseSnapshot(Packet& packet);
|
||||
void parseOnInputCommand(Packet& packet);
|
||||
void publishInputCommands();
|
||||
void identifyPacketLoss();
|
||||
void hasServerTimedOut();
|
||||
EntityID createPlayer();
|
||||
@@ -110,9 +112,6 @@ public:
|
||||
EventRelay<Client, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||
void parsePlayerDamage(Packet& packet);
|
||||
private:
|
||||
UDPClient m_Unreliable;
|
||||
TCPClient m_Reliable;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,13 @@ public:
|
||||
Network(World* world, EventBroker* eventBroker);
|
||||
virtual ~Network() { };
|
||||
|
||||
virtual void Update() = 0;
|
||||
virtual void Update(double dt) = 0;
|
||||
|
||||
protected:
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
// for network
|
||||
double m_TimeStamp = 0;
|
||||
|
||||
// For Debug
|
||||
bool isReadingData = false;
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
Server(World* world, EventBroker* eventBroker, int port);
|
||||
~Server();
|
||||
|
||||
void Update() override;
|
||||
void Update(double dt) override;
|
||||
|
||||
private:
|
||||
// Network channels
|
||||
@@ -52,6 +52,7 @@ private:
|
||||
int checkTimeOutInterval = 100;
|
||||
int m_NextPlayerID = 0;
|
||||
std::vector<Events::InputCommand> m_InputCommandsToBroadcast;
|
||||
std::vector<Events::InputCommand> m_InputCommandsToPublish;
|
||||
//Timers
|
||||
std::clock_t m_StartPingTime;
|
||||
|
||||
@@ -82,6 +83,7 @@ private:
|
||||
void parseTCPConnect(Packet & packet);
|
||||
void parseDisconnect();
|
||||
bool shouldSendToClient(EntityWrapper childEntity);
|
||||
void publishInputCommands();
|
||||
|
||||
// Debug event
|
||||
EventRelay<Server, Events::InputCommand> m_EInputCommand;
|
||||
|
||||
@@ -39,5 +39,5 @@ private:
|
||||
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||
|
||||
void updateMovementControllers(double dt);
|
||||
void updateVelocity(double dt);
|
||||
void updateVelocity(EntityWrapper player, double dt);
|
||||
};
|
||||
@@ -41,9 +41,11 @@ void Client::Connect(std::string address, int port)
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Update()
|
||||
void Client::Update(double dt)
|
||||
{
|
||||
m_EventBroker->Process<Client>();
|
||||
//m_TimeStamp += dt;
|
||||
publishInputCommands();
|
||||
while (m_Unreliable.IsSocketAvailable()) {
|
||||
// Packet will get real data in receive
|
||||
Packet packet(MessageType::Invalid);
|
||||
@@ -72,7 +74,8 @@ void Client::Update()
|
||||
sendInputCommands();
|
||||
m_TimeSinceSentInputs = std::clock();
|
||||
}
|
||||
// HACK: Send absolute player positions for now to avoid desync until we have reliable messages
|
||||
// HACK: Send absolute player positions for now to avoid desync until we have reliable messages.
|
||||
// Reliable messages and timestamps did not fix it.
|
||||
sendLocalPlayerTransform();
|
||||
|
||||
hasServerTimedOut();
|
||||
@@ -122,6 +125,9 @@ void Client::parseMessageType(Packet& packet)
|
||||
case MessageType::OnPlayerDamage:
|
||||
parsePlayerDamage(packet);
|
||||
break;
|
||||
case MessageType::OnInputCommand:
|
||||
//parsePlayerDamage(packet);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -284,21 +290,30 @@ void Client::ignoreFields(Packet& packet, const ComponentInfo& componentInfo)
|
||||
|
||||
void Client::parseSnapshot(Packet& packet)
|
||||
{
|
||||
// Read input commands
|
||||
std::size_t numInputCommands = packet.ReadPrimitive<std::size_t>();
|
||||
for (std::size_t i = 0; i < numInputCommands; ++i) {
|
||||
Events::InputCommand e;
|
||||
e.PlayerID = packet.ReadPrimitive<EntityID>();
|
||||
EntityID player = packet.ReadPrimitive<EntityID>();
|
||||
std::string command = packet.ReadString();
|
||||
float value = packet.ReadPrimitive<float>();
|
||||
if (m_ServerIDToClientID.find(player) != m_ServerIDToClientID.end()) {
|
||||
e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(player));
|
||||
e.Command = command;
|
||||
e.Value = value;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
//// Read input commands
|
||||
//std::size_t numInputCommands = packet.ReadPrimitive<std::size_t>();
|
||||
//for (std::size_t i = 0; i < numInputCommands; ++i) {
|
||||
// Events::InputCommand e;
|
||||
// e.PlayerID = packet.ReadPrimitive<EntityID>();
|
||||
// EntityID player = packet.ReadPrimitive<EntityID>();
|
||||
// std::string command = packet.ReadString();
|
||||
// float value = packet.ReadPrimitive<float>();
|
||||
// double timestamp = packet.ReadPrimitive<double>();
|
||||
// if (m_ServerIDToClientID.find(player) != m_ServerIDToClientID.end()) {
|
||||
// e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(player));
|
||||
// e.Command = command;
|
||||
// e.Value = value;
|
||||
// e.TimeStamp = timestamp;
|
||||
// m_EventBroker->Publish(e);
|
||||
// }
|
||||
//}
|
||||
|
||||
// Read timestamp
|
||||
double remoteTimestamp = packet.ReadPrimitive<double>();
|
||||
//if (abs(remoteTimestamp - m_TimeStamp) > 0.100) {
|
||||
// m_TimeStamp = remoteTimestamp;
|
||||
// LOG_INFO("Resynced remote and local timestamp");
|
||||
//}
|
||||
|
||||
// Read world state
|
||||
while (packet.DataReadSize() < packet.Size()) {
|
||||
@@ -359,6 +374,36 @@ void Client::parseSnapshot(Packet& packet)
|
||||
parseSpawnEvents();
|
||||
}
|
||||
|
||||
|
||||
void Client::parseOnInputCommand(Packet & packet)
|
||||
{
|
||||
while (packet.DataReadSize() < packet.Size()) {
|
||||
Events::InputCommand e;
|
||||
e.PlayerID = packet.ReadPrimitive<int>();
|
||||
e.Player = EntityWrapper(m_World, packet.ReadPrimitive<int>());
|
||||
e.Command = packet.ReadString();
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
e.TimeStamp = packet.ReadPrimitive<double>();
|
||||
m_EventBroker->Publish(e);
|
||||
m_ReceivedInputCommands.push_back(e);
|
||||
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::publishInputCommands()
|
||||
{
|
||||
std::vector<Events::InputCommand> notPublishedEvents;
|
||||
for (int i = 0; i < m_ReceivedInputCommands.size(); i++) {
|
||||
if (m_ReceivedInputCommands.at(i).TimeStamp < m_TimeStamp) {
|
||||
m_EventBroker->Publish(m_ReceivedInputCommands.at(i));
|
||||
}
|
||||
else {
|
||||
notPublishedEvents.push_back(m_ReceivedInputCommands.at(i));
|
||||
}
|
||||
}
|
||||
m_ReceivedInputCommands = notPublishedEvents;
|
||||
}
|
||||
|
||||
void Client::disconnect()
|
||||
{
|
||||
m_IsConnected = false;
|
||||
@@ -402,7 +447,9 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||
}
|
||||
} else {
|
||||
if (m_IsConnected) {
|
||||
m_InputCommandBuffer.push_back(e);
|
||||
Events::InputCommand setTimestamp = e;
|
||||
setTimestamp.TimeStamp = m_TimeStamp;
|
||||
m_InputCommandBuffer.push_back(setTimestamp);
|
||||
}
|
||||
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
return true;
|
||||
@@ -437,11 +484,12 @@ void Client::parsePlayerDamage(Packet& packet)
|
||||
{
|
||||
Events::PlayerDamage e;
|
||||
PlayerID victimID = packet.ReadPrimitive<EntityID>();
|
||||
if(serverClientMapsHasEntity(victimID)){
|
||||
PlayerID inflictorID = packet.ReadPrimitive<EntityID>();
|
||||
if(!serverClientMapsHasEntity(victimID) || !serverClientMapsHasEntity(inflictorID)){
|
||||
return;
|
||||
}
|
||||
e.Inflictor = EntityWrapper(m_World, m_ServerIDToClientID.at(victimID));
|
||||
e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive<EntityID>()));
|
||||
e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(inflictorID));
|
||||
e.Damage = packet.ReadPrimitive<double>();
|
||||
// Don't rebroadcast our own player damage events or we'll have an infinite loop!
|
||||
if (e.Inflictor != m_LocalPlayer) {
|
||||
@@ -515,6 +563,7 @@ void Client::sendInputCommands()
|
||||
for (int i = 0; i < m_InputCommandBuffer.size(); i++) {
|
||||
packet.WriteString(m_InputCommandBuffer[i].Command);
|
||||
packet.WritePrimitive(m_InputCommandBuffer[i].Value);
|
||||
packet.WritePrimitive(m_InputCommandBuffer[i].TimeStamp);
|
||||
}
|
||||
m_Reliable.Send(packet);
|
||||
m_InputCommandBuffer.clear();
|
||||
|
||||
@@ -9,7 +9,7 @@ Network::Network(World* world, EventBroker* eventBroker)
|
||||
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
|
||||
}
|
||||
|
||||
void Network::Update()
|
||||
void Network::Update(double dt)
|
||||
{
|
||||
updateNetworkData();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Network/Server.h"
|
||||
|
||||
Server::Server(World* world, EventBroker* eventBroker, int port)
|
||||
Server::Server(World* world, EventBroker* eventBroker, int port)
|
||||
: Network(world, eventBroker)
|
||||
{
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
@@ -26,10 +26,12 @@ Server::~Server()
|
||||
|
||||
}
|
||||
|
||||
void Server::Update()
|
||||
void Server::Update(double dt)
|
||||
{
|
||||
m_EventBroker->Process<Server>();
|
||||
m_TimeStamp += dt;
|
||||
publishInputCommands();
|
||||
PlayerDefinition pd;
|
||||
|
||||
m_Reliable.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers);
|
||||
for (auto& kv : m_ConnectedPlayers) {
|
||||
while (kv.second.TCPSocket->available()) {
|
||||
@@ -80,11 +82,9 @@ void Server::Update()
|
||||
checkForTimeOuts();
|
||||
timOutTimer = currentTime;
|
||||
}
|
||||
m_EventBroker->Process<Server>();
|
||||
if (isReadingData) {
|
||||
Network::Update();
|
||||
Network::Update(dt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Server::parseMessageType(Packet& packet)
|
||||
@@ -146,7 +146,8 @@ void Server::unreliableBroadcast(Packet& packet)
|
||||
void Server::sendSnapshot()
|
||||
{
|
||||
Packet packet(MessageType::Snapshot);
|
||||
addInputCommandsToPacket(packet);
|
||||
//addInputCommandsToPacket(packet);
|
||||
packet.WritePrimitive(m_TimeStamp/*+ somePingvalue + offset*/);
|
||||
addChildrenToPacket(packet, EntityID_Invalid);
|
||||
unreliableBroadcast(packet);
|
||||
}
|
||||
@@ -160,6 +161,7 @@ void Server::addInputCommandsToPacket(Packet& packet)
|
||||
packet.WritePrimitive(m_ConnectedPlayers.at(command.PlayerID).EntityID);
|
||||
packet.WriteString(command.Command);
|
||||
packet.WritePrimitive(command.Value);
|
||||
packet.WritePrimitive(command.TimeStamp);
|
||||
}
|
||||
m_InputCommandsToBroadcast.clear();
|
||||
}
|
||||
@@ -280,7 +282,7 @@ void Server::parseTCPConnect(Packet & packet)
|
||||
// Read packet ID
|
||||
m_PreviousPacketID = m_PacketID; // Set previous packet id
|
||||
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
|
||||
|
||||
|
||||
LOG_INFO("Parsing connections");
|
||||
// Check if player is already connected
|
||||
// Ska vara till lagd i TCPServer receive
|
||||
@@ -333,6 +335,7 @@ void Server::disconnect(PlayerID playerID)
|
||||
e.PlayerID = playerID;
|
||||
m_EventBroker->Publish(e);
|
||||
//m_World->DeleteEntity(m_ConnectedPlayers[playerID].EntityID);
|
||||
// TODO Kolla Anders crashade efter timeout med break point
|
||||
m_ConnectedPlayers[playerID].TCPSocket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
|
||||
m_ConnectedPlayers[playerID].TCPSocket->close();
|
||||
m_World->DeleteEntity(m_ConnectedPlayers[playerID].EntityID);
|
||||
@@ -375,8 +378,7 @@ bool Server::OnInputCommand(const Events::InputCommand & e)
|
||||
}
|
||||
isReadingData = !isReadingData;
|
||||
m_SaveDataTimer = std::clock();
|
||||
}
|
||||
if (e.Command == "KickPlayer" && e.Value > 0) {
|
||||
} else if (e.Command == "KickPlayer" && e.Value > 0) {
|
||||
kick(0);
|
||||
}
|
||||
|
||||
@@ -466,7 +468,9 @@ void Server::parseOnInputCommand(Packet& packet)
|
||||
e.PlayerID = player; // Set correct player id
|
||||
e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID);
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
m_EventBroker->Publish(e);
|
||||
e.TimeStamp = packet.ReadPrimitive<double>();
|
||||
/* m_EventBroker->Publish(e);*/
|
||||
m_InputCommandsToPublish.push_back(e);
|
||||
if (e.Command == "PrimaryFire" || e.Command == "Reload") {
|
||||
m_InputCommandsToBroadcast.push_back(e);
|
||||
}
|
||||
@@ -516,6 +520,20 @@ bool Server::shouldSendToClient(EntityWrapper childEntity)
|
||||
return childEntity.HasComponent("Player") || childEntity.FirstParentWithComponent("Player").Valid();
|
||||
}
|
||||
|
||||
void Server::publishInputCommands()
|
||||
{
|
||||
std::vector<Events::InputCommand> notPublishedEvents;
|
||||
for (int i = 0; i < m_InputCommandsToPublish.size(); i++) {
|
||||
if (m_InputCommandsToPublish.at(i).TimeStamp < m_TimeStamp) {
|
||||
m_EventBroker->Publish(m_InputCommandsToPublish.at(i));
|
||||
} else {
|
||||
LOG_INFO("Did not instantly publish command");
|
||||
notPublishedEvents.push_back(m_InputCommandsToPublish.at(i));
|
||||
}
|
||||
}
|
||||
m_InputCommandsToPublish = notPublishedEvents;
|
||||
}
|
||||
|
||||
PlayerID Server::GetPlayerIDFromEndpoint()
|
||||
{
|
||||
// check both tcp and udp connection
|
||||
|
||||
+2
-2
@@ -199,10 +199,10 @@ void Game::Tick()
|
||||
// Update network
|
||||
m_EventBroker->Process<MultiplayerSnapshotFilter>();
|
||||
if (m_NetworkClient != nullptr) {
|
||||
m_NetworkClient->Update();
|
||||
m_NetworkClient->Update(dt);
|
||||
}
|
||||
if (m_NetworkServer != nullptr) {
|
||||
m_NetworkServer->Update();
|
||||
m_NetworkServer->Update(dt);
|
||||
}
|
||||
//m_SoundManager->Update(dt);
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ PlayerMovementSystem::~PlayerMovementSystem()
|
||||
void PlayerMovementSystem::Update(double dt)
|
||||
{
|
||||
updateMovementControllers(dt);
|
||||
updateVelocity(dt);
|
||||
if (LocalPlayer.Valid()) {
|
||||
updateVelocity(LocalPlayer, dt);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
@@ -221,15 +223,11 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
}
|
||||
|
||||
|
||||
void PlayerMovementSystem::updateVelocity(double dt)
|
||||
void PlayerMovementSystem::updateVelocity(EntityWrapper player, double dt)
|
||||
{
|
||||
// Only apply velocity to local player
|
||||
if (!LocalPlayer.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper& cTransform = LocalPlayer["Transform"];
|
||||
ComponentWrapper& cPhysics = LocalPlayer["Physics"];
|
||||
ComponentWrapper& cTransform = player["Transform"];
|
||||
ComponentWrapper& cPhysics = player["Physics"];
|
||||
glm::vec3& velocity = cPhysics["Velocity"];
|
||||
bool isOnGround = (bool)cPhysics["IsOnGround"];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user