Send our own reliable packet for a more accurate ping
This commit is contained in:
parent
de8730dbfc
commit
a44ce60991
@ -57,7 +57,7 @@ digraph interaction {
|
|||||||
"REQUESTING_CONNECTION" -> "?? TO BE DONE ??" [label="Connection refused by server"]
|
"REQUESTING_CONNECTION" -> "?? TO BE DONE ??" [label="Connection refused by server"]
|
||||||
"CONNECTED" -> "KART_SELECTION" [label="Server tells us to start kart selection"]
|
"CONNECTED" -> "KART_SELECTION" [label="Server tells us to start kart selection"]
|
||||||
"KART_SELECTION" -> "SELECTING_KARTS" [label="Show kart selection screen"]
|
"KART_SELECTION" -> "SELECTING_KARTS" [label="Show kart selection screen"]
|
||||||
"SELECTING_KARTS" -> "PLAYING" [label="Server sends start race message"]
|
"SELECTING_KARTS" -> "RACING" [label="Server sends start race message"]
|
||||||
}
|
}
|
||||||
\enddot
|
\enddot
|
||||||
Note that some states are actually managed outside of the client lobby. For
|
Note that some states are actually managed outside of the client lobby. For
|
||||||
@ -313,14 +313,6 @@ void ClientLobby::update(int ticks)
|
|||||||
m_state.store(REQUESTING_CONNECTION);
|
m_state.store(REQUESTING_CONNECTION);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REQUESTING_CONNECTION:
|
|
||||||
break;
|
|
||||||
case CONNECTED:
|
|
||||||
break;
|
|
||||||
case SELECTING_ASSETS:
|
|
||||||
break;
|
|
||||||
case PLAYING:
|
|
||||||
break;
|
|
||||||
case RACE_FINISHED:
|
case RACE_FINISHED:
|
||||||
if (!RaceEventManager::getInstance()->protocolStopped() ||
|
if (!RaceEventManager::getInstance()->protocolStopped() ||
|
||||||
!GameProtocol::emptyInstance())
|
!GameProtocol::emptyInstance())
|
||||||
@ -332,6 +324,10 @@ void ClientLobby::update(int ticks)
|
|||||||
m_state.store(EXITING);
|
m_state.store(EXITING);
|
||||||
requestTerminate();
|
requestTerminate();
|
||||||
break;
|
break;
|
||||||
|
case REQUESTING_CONNECTION:
|
||||||
|
case CONNECTED:
|
||||||
|
case SELECTING_ASSETS:
|
||||||
|
case RACING:
|
||||||
case EXITING:
|
case EXITING:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -656,7 +652,7 @@ void ClientLobby::connectionRefused(Event* event)
|
|||||||
*/
|
*/
|
||||||
void ClientLobby::startGame(Event* event)
|
void ClientLobby::startGame(Event* event)
|
||||||
{
|
{
|
||||||
m_state.store(PLAYING);
|
m_state.store(RACING);
|
||||||
// Triggers the world finite state machine to go from WAIT_FOR_SERVER_PHASE
|
// Triggers the world finite state machine to go from WAIT_FOR_SERVER_PHASE
|
||||||
// to READY_PHASE.
|
// to READY_PHASE.
|
||||||
World::getWorld()->setReadyToRace();
|
World::getWorld()->setReadyToRace();
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2018 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef CLIENT_LOBBY_HPP
|
#ifndef CLIENT_LOBBY_HPP
|
||||||
#define CLIENT_LOBBY_HPP
|
#define CLIENT_LOBBY_HPP
|
||||||
|
|
||||||
@ -42,7 +60,7 @@ private:
|
|||||||
REQUESTING_CONNECTION,
|
REQUESTING_CONNECTION,
|
||||||
CONNECTED, // means in the lobby room
|
CONNECTED, // means in the lobby room
|
||||||
SELECTING_ASSETS, // in the kart selection or tracks screen
|
SELECTING_ASSETS, // in the kart selection or tracks screen
|
||||||
PLAYING, // racing
|
RACING, // racing
|
||||||
RACE_FINISHED, // race result shown
|
RACE_FINISHED, // race result shown
|
||||||
DONE,
|
DONE,
|
||||||
EXITING
|
EXITING
|
||||||
@ -79,9 +97,11 @@ public:
|
|||||||
{ return m_state.load() == CONNECTED; }
|
{ return m_state.load() == CONNECTED; }
|
||||||
virtual void asynchronousUpdate() OVERRIDE {}
|
virtual void asynchronousUpdate() OVERRIDE {}
|
||||||
virtual bool allPlayersReady() const OVERRIDE
|
virtual bool allPlayersReady() const OVERRIDE
|
||||||
{ return m_state.load() >= PLAYING; }
|
{ return m_state.load() >= RACING; }
|
||||||
bool waitingForServerRespond() const
|
bool waitingForServerRespond() const
|
||||||
{ return m_state.load() == REQUESTING_CONNECTION; }
|
{ return m_state.load() == REQUESTING_CONNECTION; }
|
||||||
|
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENT_LOBBY_HPP
|
#endif // CLIENT_LOBBY_HPP
|
||||||
|
@ -116,6 +116,7 @@ public:
|
|||||||
virtual void loadWorld();
|
virtual void loadWorld();
|
||||||
virtual bool waitingForPlayers() const = 0;
|
virtual bool waitingForPlayers() const = 0;
|
||||||
virtual bool allPlayersReady() const = 0;
|
virtual bool allPlayersReady() const = 0;
|
||||||
|
virtual bool isRacing() const = 0;
|
||||||
GameSetup* getGameSetup() const { return m_game_setup; }
|
GameSetup* getGameSetup() const { return m_game_setup; }
|
||||||
|
|
||||||
}; // class LobbyProtocol
|
}; // class LobbyProtocol
|
||||||
|
@ -1366,6 +1366,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
|||||||
server_info->addUInt8(LE_SERVER_INFO);
|
server_info->addUInt8(LE_SERVER_INFO);
|
||||||
m_game_setup->addServerInfo(server_info);
|
m_game_setup->addServerInfo(server_info);
|
||||||
peer->sendPacket(server_info);
|
peer->sendPacket(server_info);
|
||||||
|
delete server_info;
|
||||||
|
|
||||||
NetworkString* message_ack = getNetworkString(4);
|
NetworkString* message_ack = getNetworkString(4);
|
||||||
message_ack->setSynchronous(true);
|
message_ack->setSynchronous(true);
|
||||||
@ -1377,12 +1378,6 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
|||||||
peer->sendPacket(message_ack);
|
peer->sendPacket(message_ack);
|
||||||
delete message_ack;
|
delete message_ack;
|
||||||
|
|
||||||
// Make sure it will always ping at least the frequency of state exchange
|
|
||||||
// so enet will not ping when we exchange state but keep ping elsewhere
|
|
||||||
// then in lobby the ping seen will be correct
|
|
||||||
peer->setPingInterval(110);
|
|
||||||
delete server_info;
|
|
||||||
|
|
||||||
m_peers_ready[peer] = std::make_pair(false, 0.0);
|
m_peers_ready[peer] = std::make_pair(false, 0.0);
|
||||||
for (std::shared_ptr<NetworkPlayerProfile> npp : peer->getPlayerProfiles())
|
for (std::shared_ptr<NetworkPlayerProfile> npp : peer->getPlayerProfiles())
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
//
|
||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2018 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef SERVER_LOBBY_HPP
|
#ifndef SERVER_LOBBY_HPP
|
||||||
#define SERVER_LOBBY_HPP
|
#define SERVER_LOBBY_HPP
|
||||||
|
|
||||||
@ -219,6 +237,7 @@ public:
|
|||||||
virtual bool waitingForPlayers() const OVERRIDE;
|
virtual bool waitingForPlayers() const OVERRIDE;
|
||||||
virtual bool allPlayersReady() const OVERRIDE
|
virtual bool allPlayersReady() const OVERRIDE
|
||||||
{ return m_state.load() >= WAIT_FOR_RACE_STARTED; }
|
{ return m_state.load() >= WAIT_FOR_RACE_STARTED; }
|
||||||
|
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
|
||||||
|
|
||||||
}; // class ServerLobby
|
}; // class ServerLobby
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "network/stk_host.hpp"
|
#include "network/stk_host.hpp"
|
||||||
|
|
||||||
|
#include "config/stk_config.hpp"
|
||||||
#include "config/user_config.hpp"
|
#include "config/user_config.hpp"
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "network/event.hpp"
|
#include "network/event.hpp"
|
||||||
@ -241,23 +242,19 @@ std::shared_ptr<LobbyProtocol> STKHost::create(SeparateProcess* p)
|
|||||||
* LocalPlayerController for each kart. Each remote player gets a
|
* LocalPlayerController for each kart. Each remote player gets a
|
||||||
* NULL ActivePlayer (the ActivePlayer is only used for assigning the input
|
* NULL ActivePlayer (the ActivePlayer is only used for assigning the input
|
||||||
* device to each kart, achievements and highscores, so it's not needed for
|
* device to each kart, achievements and highscores, so it's not needed for
|
||||||
* remote players). It will also start the LatencyProtocol,
|
* remote players). It will also start the RaceEventManager and then load the
|
||||||
* RaceEventManager and then load the world.
|
* world.
|
||||||
|
|
||||||
* TODO:
|
|
||||||
* Once the server has received all
|
|
||||||
* messages in notifyEventAsynchronous(), it will call startCountdown()
|
|
||||||
* in the LatencyProtocol. The LatencyProtocol is
|
|
||||||
* sending regular (once per second) pings to the clients and measure
|
|
||||||
* the averate latency. Upon starting the countdown this information
|
|
||||||
* is included in the ping request, so the clients can start the countdown
|
|
||||||
* at that stage as well.
|
|
||||||
*
|
|
||||||
* Once the countdown is 0 (or below), the Synchronization Protocol will
|
|
||||||
* start the protocols: KartUpdateProtocol, GameProtocol,
|
|
||||||
* GameEventsProtocol. Then the LatencyProtocol is terminated
|
|
||||||
* which indicates to the main loop to start the actual game.
|
|
||||||
*/
|
*/
|
||||||
|
// ============================================================================
|
||||||
|
constexpr std::array<uint8_t, 5> g_ping_packet {{ 255, 'p', 'i', 'n', 'g' }};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
constexpr bool isPingPacket(unsigned char* data, size_t length)
|
||||||
|
{
|
||||||
|
return length == g_ping_packet.size() && data[0] == g_ping_packet[0] &&
|
||||||
|
data[1] == g_ping_packet[1] && data[2] == g_ping_packet[2] &&
|
||||||
|
data[3] == g_ping_packet[3] && data[4] == g_ping_packet[4];
|
||||||
|
} // isPingPacket
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
/** The constructor for a server or client.
|
/** The constructor for a server or client.
|
||||||
@ -715,6 +712,7 @@ void STKHost::mainLoop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double last_ping_time = StkTime::getRealTime();
|
||||||
while (m_exit_timeout.load() > StkTime::getRealTime())
|
while (m_exit_timeout.load() > StkTime::getRealTime())
|
||||||
{
|
{
|
||||||
if (!is_server)
|
if (!is_server)
|
||||||
@ -737,11 +735,28 @@ void STKHost::mainLoop()
|
|||||||
if (is_server)
|
if (is_server)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> peer_lock(m_peers_mutex);
|
std::unique_lock<std::mutex> peer_lock(m_peers_mutex);
|
||||||
// Remove peer which has not been validated after a specific time
|
|
||||||
// It is validated when the first connection request has finished
|
|
||||||
const float timeout = UserConfigParams::m_validation_timeout;
|
const float timeout = UserConfigParams::m_validation_timeout;
|
||||||
|
bool need_ping = false;
|
||||||
|
if (sl && !sl->isRacing() &&
|
||||||
|
last_ping_time < StkTime::getRealTime())
|
||||||
|
{
|
||||||
|
// If not racing, send an reliable packet at the same rate with
|
||||||
|
// state exchange to keep enet ping accurate
|
||||||
|
last_ping_time = StkTime::getRealTime() +
|
||||||
|
1.0 / double(stk_config->m_network_state_frequeny);
|
||||||
|
need_ping = true;
|
||||||
|
}
|
||||||
for (auto it = m_peers.begin(); it != m_peers.end();)
|
for (auto it = m_peers.begin(); it != m_peers.end();)
|
||||||
{
|
{
|
||||||
|
if (need_ping)
|
||||||
|
{
|
||||||
|
ENetPacket* packet = enet_packet_create(g_ping_packet.data(),
|
||||||
|
g_ping_packet.size(), ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_peer_send(it->first, EVENT_CHANNEL_UNENCRYPTED, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove peer which has not been validated after a specific time
|
||||||
|
// It is validated when the first connection request has finished
|
||||||
if (!it->second->isValidated() &&
|
if (!it->second->isValidated() &&
|
||||||
(float)StkTime::getRealTime() >
|
(float)StkTime::getRealTime() >
|
||||||
it->second->getConnectedTime() + timeout)
|
it->second->getConnectedTime() + timeout)
|
||||||
@ -837,6 +852,11 @@ void STKHost::mainLoop()
|
|||||||
if (!stk_event && m_peers.find(event.peer) != m_peers.end())
|
if (!stk_event && m_peers.find(event.peer) != m_peers.end())
|
||||||
{
|
{
|
||||||
auto& peer = m_peers.at(event.peer);
|
auto& peer = m_peers.at(event.peer);
|
||||||
|
if (isPingPacket(event.packet->data, event.packet->dataLength))
|
||||||
|
{
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stk_event = new Event(&event, peer);
|
stk_event = new Event(&event, peer);
|
||||||
|
Loading…
Reference in New Issue
Block a user