Show ping of remote players in lobby

This commit is contained in:
Benau 2018-07-04 00:54:40 +08:00
parent a44ce60991
commit e1dfe2e7e0
10 changed files with 142 additions and 58 deletions

View File

@ -59,10 +59,10 @@
#include "main_loop.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "network/stk_host.hpp"
#include "physics/physics.hpp"
#include "scriptengine/property_animator.hpp"
#include "states_screens/dialogs/confirm_resolution_dialog.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track.hpp"
@ -1729,13 +1729,15 @@ void IrrDriver::displayFPS()
prev_state = current_state;
}
uint32_t ping = 0;
if (STKHost::existHost())
ping = STKHost::get()->getClientPingToServer();
if (no_trust)
{
no_trust--;
static video::SColor fpsColor = video::SColor(255, 0, 0, 0);
font->draw(StringUtils::insertValues (L"FPS: ... Ping: %dms",
NetworkingLobby::getInstance()->getServerPing()),
font->draw(StringUtils::insertValues (L"FPS: ... Ping: %dms", ping),
core::rect< s32 >(100,0,400,50), fpsColor, false);
return;
}
@ -1761,22 +1763,19 @@ void IrrDriver::displayFPS()
"Ping: %dms",
min, fps, max, SP::sp_solid_poly_count,
SP::sp_shadow_poly_count, m_last_light_bucket_distance,
m_skinning_joint,
NetworkingLobby::getInstance()->getServerPing());
m_skinning_joint, ping);
}
else
{
if (CVS->isGLSL())
{
fps_string = _("FPS: %d/%d/%d - %d KTris, Ping: %dms", min, fps,
max, SP::sp_solid_poly_count / 1000,
NetworkingLobby::getInstance()->getServerPing());
max, SP::sp_solid_poly_count / 1000, ping);
}
else
{
fps_string = _("FPS: %d/%d/%d - %d KTris, Ping: %dms", min, fps,
max, (int)roundf(kilotris),
NetworkingLobby::getInstance()->getServerPing());
max, (int)roundf(kilotris), ping);
}
}

View File

@ -57,7 +57,7 @@ private:
std::string m_kart_name;
/** The local player id relative to each peer. */
int m_local_player_id;
uint8_t m_local_player_id;
/** Score if grand prix. */
int m_score;
@ -96,7 +96,7 @@ public:
const std::string &getKartName() const { return m_kart_name; }
// ------------------------------------------------------------------------
/** Retuens the local player id for this player. */
int getLocalPlayerId() const { return m_local_player_id; }
uint8_t getLocalPlayerId() const { return m_local_player_id; }
// ------------------------------------------------------------------------
/** Returns the per-player difficulty. */
PerPlayerDifficulty getPerPlayerDifficulty() const

View File

@ -168,6 +168,10 @@ public:
int decodeString(std::string *out) const;
int decodeStringW(irr::core::stringw *out) const;
std::string getLogMessage(const std::string &indent="") const;
// ------------------------------------------------------------------------
/** Returns the internal buffer of the network string. */
std::vector<uint8_t>& getBuffer() { return m_buffer; }
// ------------------------------------------------------------------------
/** Returns a byte pointer to the content of the network string. */
char* getData() { return (char*)(m_buffer.data()); };

View File

@ -548,19 +548,21 @@ void ClientLobby::updatePlayerList(Event* event)
if (!checkDataSize(event, 1)) return;
NetworkString& data = event->data();
unsigned player_count = data.getUInt8();
std::vector<std::tuple<uint32_t, uint32_t, core::stringw, int> > players;
std::vector<std::tuple<uint32_t, uint32_t, uint32_t, core::stringw,
int> > players;
for (unsigned i = 0; i < player_count; i++)
{
std::tuple<uint32_t, uint32_t, core::stringw, int> pl;
std::tuple<uint32_t, uint32_t, uint32_t, core::stringw, int> pl;
std::get<0>(pl) = data.getUInt32();
std::get<1>(pl) = data.getUInt32();
data.decodeStringW(&std::get<2>(pl));
std::get<2>(pl) = data.getUInt8();
data.decodeStringW(&std::get<3>(pl));
// icon to be used, see NetworkingLobby::loadedFromFile
std::get<3>(pl) = data.getUInt8() == 1 /*if server owner*/ ? 0 :
std::get<4>(pl) = data.getUInt8() == 1 /*if server owner*/ ? 0 :
std::get<1>(pl) != 0 /*if online account*/ ? 1 : 2;
PerPlayerDifficulty d = (PerPlayerDifficulty)data.getUInt8();
if (d == PLAYER_DIFFICULTY_HANDICAP)
std::get<2>(pl) = _("%s (handicapped)", std::get<2>(pl));
std::get<3>(pl) = _("%s (handicapped)", std::get<3>(pl));
players.push_back(pl);
}
NetworkingLobby::getInstance()->updatePlayers(players);

View File

@ -1406,6 +1406,7 @@ void ServerLobby::updatePlayerList(bool force_update)
for (auto profile : all_profiles)
{
pl->addUInt32(profile->getHostId()).addUInt32(profile->getOnlineId())
.addUInt8(profile->getLocalPlayerId())
.encodeString(profile->getName());
uint8_t server_owner = 0;
if (m_server_owner_id.load() == profile->getPeer()->getHostId())

View File

@ -251,7 +251,7 @@ 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] &&
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
@ -305,6 +305,7 @@ void STKHost::init()
m_authorised = false;
m_network = NULL;
m_exit_timeout.store(std::numeric_limits<double>::max());
m_client_ping.store(0);
// Start with initialising ENet
// ============================
@ -713,19 +714,9 @@ void STKHost::mainLoop()
}
double last_ping_time = StkTime::getRealTime();
double last_ping_time_update_for_client = StkTime::getRealTime();
while (m_exit_timeout.load() > StkTime::getRealTime())
{
if (!is_server)
{
auto server_peer = getServerPeerForClient();
if (server_peer &&
StkTime::getRealTime() - server_peer->getConnectedTime() > 3.0)
{
// Back to default ping interval for client
server_peer->setPingInterval(0);
}
}
auto sl = LobbyProtocol::get<ServerLobby>();
if (direct_socket && sl && sl->waitingForPlayers())
{
@ -746,12 +737,29 @@ void STKHost::mainLoop()
1.0 / double(stk_config->m_network_state_frequeny);
need_ping = true;
}
if (need_ping)
{
m_peer_pings.getData().clear();
for (auto& p : m_peers)
{
m_peer_pings.getData()[p.second->getHostId()] =
p.second->getPing();
}
}
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);
BareNetworkString ping_packet;
ping_packet.addUInt8((uint8_t)m_peer_pings.getData().size());
for (auto& p : m_peer_pings.getData())
ping_packet.addUInt32(p.first).addUInt32(p.second);
ping_packet.getBuffer().insert(
ping_packet.getBuffer().begin(), g_ping_packet.begin(),
g_ping_packet.end());
ENetPacket* packet = enet_packet_create(ping_packet.getData(),
ping_packet.getTotalSize(), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(it->first, EVENT_CHANNEL_UNENCRYPTED, packet);
}
@ -804,8 +812,28 @@ void STKHost::mainLoop()
}
}
bool need_ping_update = false;
while (enet_host_service(host, &event, 10) != 0)
{
if (!is_server &&
last_ping_time_update_for_client < StkTime::getRealTime())
{
last_ping_time_update_for_client =
StkTime::getRealTime() + 2.0;
auto lp = LobbyProtocol::get<LobbyProtocol>();
if (lp && lp->isRacing())
{
auto p = getServerPeerForClient();
if (p)
{
m_client_ping.store(p->getPing(),
std::memory_order_relaxed);
}
need_ping_update = false;
}
else
need_ping_update = true;
}
if (event.type == ENET_EVENT_TYPE_NONE)
continue;
@ -854,6 +882,24 @@ void STKHost::mainLoop()
auto& peer = m_peers.at(event.peer);
if (isPingPacket(event.packet->data, event.packet->dataLength))
{
if (!is_server && need_ping_update)
{
m_peer_pings.lock();
m_peer_pings.getData().clear();
BareNetworkString ping_packet((char*)event.packet->data,
event.packet->dataLength);
ping_packet.skip(g_ping_packet.size());
unsigned peer_size = ping_packet.getUInt8();
for (unsigned i = 0; i < peer_size; i++)
{
unsigned host_id = ping_packet.getUInt32();
unsigned ping = ping_packet.getUInt32();
m_peer_pings.getData()[host_id] = ping;
}
m_client_ping.store(m_peer_pings.getData()[m_host_id],
std::memory_order_relaxed);
m_peer_pings.unlock();
}
enet_packet_destroy(event.packet);
continue;
}

View File

@ -25,6 +25,7 @@
#include "network/network.hpp"
#include "network/network_string.hpp"
#include "network/transport_address.hpp"
#include "utils/synchronised.hpp"
#include "irrString.h"
@ -132,6 +133,10 @@ private:
/** The private port enet socket is bound. */
uint16_t m_private_port;
Synchronised<std::map<uint32_t, uint32_t> > m_peer_pings;
std::atomic<uint32_t> m_client_ping;
// ------------------------------------------------------------------------
STKHost(bool server);
// ------------------------------------------------------------------------
@ -301,7 +306,12 @@ public:
bool isClientServer() const { return m_separate_process != NULL; }
// ------------------------------------------------------------------------
void replaceNetwork(ENetEvent& event, Network* network);
// ------------------------------------------------------------------------
std::map<uint32_t, uint32_t> getPeerPings()
{ return m_peer_pings.getAtomic(); }
// ------------------------------------------------------------------------
uint32_t getClientPingToServer() const
{ return m_client_ping.load(std::memory_order_relaxed); }
}; // class STKHost
#endif // STK_HOST_HPP

View File

@ -20,9 +20,7 @@
#include "config/user_config.hpp"
#include "network/crypto.hpp"
#include "network/event.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/network_player_profile.hpp"
#include "network/stk_host.hpp"
#include "network/transport_address.hpp"
#include "utils/log.hpp"
@ -39,12 +37,6 @@ STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
m_host_id = host_id;
m_connected_time = (float)StkTime::getRealTime();
m_validated.store(false);
if (NetworkConfig::get()->isClient())
{
// This allow client to get the correct ping as fast as possible
// reset to default (0) will be done in STKHost::mainloop after 3 sec
setPingInterval(10);
}
} // STKPeer
//-----------------------------------------------------------------------------

View File

@ -17,6 +17,7 @@
#include "states_screens/networking_lobby.hpp"
#include <algorithm>
#include <string>
#include "config/user_config.hpp"
@ -38,7 +39,6 @@
#include "network/protocols/lobby_protocol.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/network_user_dialog.hpp"
#include "utils/translation.hpp"
@ -135,6 +135,7 @@ void NetworkingLobby::init()
{
Screen::init();
m_ping_update_timer = 0.0f;
m_cur_starting_timer = m_start_threshold = m_start_timeout =
m_server_max_player = std::numeric_limits<float>::max();
m_timeout_message->setVisible(false);
@ -269,8 +270,6 @@ void NetworkingLobby::onUpdate(float delta)
}
else
{
if (m_server_peer.expired() && STKHost::existHost())
m_server_peer = STKHost::get()->getServerPeerForClient();
core::stringw total_msg;
for (auto& string : m_server_info)
{
@ -280,26 +279,47 @@ void NetworkingLobby::onUpdate(float delta)
m_text_bubble->setText(total_msg, true);
}
m_ping_update_timer += delta;
if (m_player_list && m_ping_update_timer > 2.0f)
{
m_ping_update_timer = 0.0f;
updatePlayerPings();
}
if (STKHost::get()->isAuthorisedToControl())
{
m_start_button->setVisible(true);
}
//I18N: In the networking lobby, display ping when connected
const uint32_t ping = getServerPing();
const uint32_t ping = STKHost::get()->getClientPingToServer();
if (ping != 0)
m_header->setText(_("Lobby (ping: %dms)", ping), false);
} // onUpdate
// ----------------------------------------------------------------------------
uint32_t NetworkingLobby::getServerPing() const
void NetworkingLobby::updatePlayerPings()
{
if (auto p = m_server_peer.lock())
auto peer_pings = STKHost::get()->getPeerPings();
for (auto& p : m_player_names)
{
return p->getPing();
core::stringw name_with_ping = p.second.first;
auto host_online_ids = StringUtils::splitToUInt(p.first, '_');
if (host_online_ids.size() != 3)
continue;
unsigned ping = 0;
uint32_t host_id = host_online_ids[0];
if (peer_pings.find(host_id) != peer_pings.end())
ping = peer_pings.at(host_id);
if (ping != 0)
{
name_with_ping = StringUtils::insertValues(L"%s (%dms)",
name_with_ping, ping);
}
else
continue;
m_player_list->renameItem(p.first, name_with_ping, p.second.second);
}
return 0;
} // getServerPing
} // updatePlayerPings
// ----------------------------------------------------------------------------
void NetworkingLobby::sendChat(irr::core::stringw text)
@ -336,12 +356,13 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
{
auto host_online_ids = StringUtils::splitToUInt
(m_player_list->getSelectionInternalName(), '_');
if (host_online_ids.size() != 2)
if (host_online_ids.size() != 3)
{
return;
}
new NetworkUserDialog(host_online_ids[0], host_online_ids[1],
m_player_list->getSelectionLabel());
m_player_names.at(
m_player_list->getSelectionInternalName()).first);
} // click on a user
else if (name == m_send_button->m_properties[PROP_ID])
{
@ -389,13 +410,15 @@ bool NetworkingLobby::onEscapePressed()
// ----------------------------------------------------------------------------
void NetworkingLobby::updatePlayers(const std::vector<std::tuple<uint32_t,
uint32_t, core::stringw, int> >& p)
uint32_t, uint32_t, core::stringw,
int> >& p)
{
// In GUI-less server this function will be called without proper
// initialisation
if (!m_player_list)
return;
m_player_list->clear();
m_player_names.clear();
if (p.empty())
return;
@ -410,9 +433,12 @@ void NetworkingLobby::updatePlayers(const std::vector<std::tuple<uint32_t,
}
const std::string internal_name =
StringUtils::toString(std::get<0>(q)) + "_" +
StringUtils::toString(std::get<1>(q));
m_player_list->addItem(internal_name, std::get<2>(q), std::get<3>(q));
StringUtils::toString(std::get<1>(q)) + "_" +
StringUtils::toString(std::get<2>(q));
m_player_list->addItem(internal_name, std::get<3>(q), std::get<4>(q));
m_player_names[internal_name] = { std::get<3>(q), std::get<4>(q) };
}
updatePlayerPings();
} // updatePlayers
// ----------------------------------------------------------------------------
@ -447,6 +473,7 @@ void NetworkingLobby::cleanAddedPlayers()
if (!m_player_list)
return;
m_player_list->clear();
m_player_names.clear();
} // cleanAddedPlayers
// ----------------------------------------------------------------------------

View File

@ -20,11 +20,12 @@
#include "guiengine/screen.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include <map>
#include <memory>
#include <tuple>
#include <utility>
class Server;
class STKPeer;
namespace GUIEngine
{
@ -62,8 +63,10 @@ private:
NetworkingLobby();
float m_ping_update_timer;
std::map<std::string, std::pair<core::stringw, /*icon*/int> >
m_player_names;
std::shared_ptr<Server> m_joined_server;
std::weak_ptr<STKPeer> m_server_peer;
std::vector<core::stringw> m_server_info;
int m_server_info_height;
@ -93,6 +96,7 @@ private:
}
void sendChat(irr::core::stringw text);
void updatePlayerPings();
public:
@ -125,11 +129,10 @@ public:
m_server_info.clear();
}
void updatePlayers(const std::vector<std::tuple<uint32_t/*host id*/,
uint32_t/*online id*/, core::stringw/*player name*/,
int/*icon id*/> >& p);
uint32_t/*online id*/, uint32_t/*local player id*/,
core::stringw/*player name*/, int/*icon id*/> >& p);
void addSplitscreenPlayer(irr::core::stringw name);
void cleanAddedPlayers();
uint32_t getServerPing() const;
void initAutoStartTimer(bool grand_prix_started, float start_threshold,
float start_timeout, unsigned server_max_player);
void setStartingTimerTo(float t) { m_cur_starting_timer = t; }