Compare commits

...

2 Commits

Author SHA1 Message Date
Jocke b547938928 timestep logic added, but is not used. 2016-02-19 13:24:06 +01:00
Jocke d1832c1741 WIP Timestamps 2016-02-17 17:07:17 +01:00
9 changed files with 117 additions and 51 deletions
+2
View File
@@ -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;
};
}
+7 -8
View File
@@ -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
+3 -1
View File
@@ -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;
+3 -1
View File
@@ -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;
+67 -19
View File
@@ -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,8 +74,9 @@ void Client::Update()
sendInputCommands();
m_TimeSinceSentInputs = std::clock();
}
// HACK: Send absolute player positions for now to avoid desync until we have reliable messages
//sendLocalPlayerTransform();
// 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;
@@ -516,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();
+1 -1
View File
@@ -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();
}
+28 -9
View File
@@ -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,9 +82,8 @@ void Server::Update()
checkForTimeOuts();
timOutTimer = currentTime;
}
m_EventBroker->Process<Server>();
if (isReadingData) {
Network::Update();
Network::Update(dt);
}
}
@@ -118,7 +119,7 @@ void Server::parseMessageType(Packet& packet)
parseOnPlayerDamage(packet);
break;
case MessageType::PlayerTransform:
// parsePlayerTransform(packet);
parsePlayerTransform(packet);
break;
default:
break;
@@ -145,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);
}
@@ -159,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();
}
@@ -332,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);
@@ -374,8 +378,7 @@ bool Server::OnInputCommand(const Events::InputCommand & e)
}
isReadingData = !isReadingData;
m_SaveDataTimer = std::clock();
}
else if (e.Command == "KickPlayer" && e.Value > 0) {
} else if (e.Command == "KickPlayer" && e.Value > 0) {
kick(0);
}
@@ -465,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);
}
@@ -515,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
View File
@@ -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);
+2 -8
View File
@@ -16,14 +16,8 @@ PlayerMovementSystem::~PlayerMovementSystem()
void PlayerMovementSystem::Update(double dt)
{
updateMovementControllers(dt);
if (IsServer) {
for (auto& kv : m_PlayerInputControllers) {
updateVelocity(kv.first, dt);
}
} else {
if (LocalPlayer.Valid()) {
updateVelocity(LocalPlayer, dt);
}
if (LocalPlayer.Valid()) {
updateVelocity(LocalPlayer, dt);
}
}