Merge pull request #536 from imayushsaini/feature/ingame-ping

added ingame ping
This commit is contained in:
Eric Froemling 2023-01-18 14:22:43 -08:00 committed by GitHub
commit 6e48a8fc2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 96 additions and 45 deletions

View File

@ -444,6 +444,17 @@ class AdvancedSettingsWindow(ba.Window):
maxwidth=430, maxwidth=430,
) )
v -= 42
self._show_game_ping_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Show Ping',
displayname=ba.Lstr(value='Show InGame Ping'),
scale=1.0,
maxwidth=430,
)
v -= 42 v -= 42
self._disable_camera_shake_check_box = ConfigCheckBox( self._disable_camera_shake_check_box = ConfigCheckBox(
parent=self._subcontainer, parent=self._subcontainer,
@ -716,6 +727,8 @@ class AdvancedSettingsWindow(ba.Window):
sel_name = 'Benchmarks' sel_name = 'Benchmarks'
elif sel == self._kick_idle_players_check_box.widget: elif sel == self._kick_idle_players_check_box.widget:
sel_name = 'KickIdlePlayers' sel_name = 'KickIdlePlayers'
elif sel == self._show_game_ping_check_box.widget:
sel_name = 'ShowPing'
elif sel == self._disable_camera_shake_check_box.widget: elif sel == self._disable_camera_shake_check_box.widget:
sel_name = 'DisableCameraShake' sel_name = 'DisableCameraShake'
elif ( elif (
@ -776,6 +789,8 @@ class AdvancedSettingsWindow(ba.Window):
sel = self._benchmarks_button sel = self._benchmarks_button
elif sel_name == 'KickIdlePlayers': elif sel_name == 'KickIdlePlayers':
sel = self._kick_idle_players_check_box.widget sel = self._kick_idle_players_check_box.widget
elif sel_name == 'ShowPing':
sel = self._show_game_ping_check_box.widget
elif sel_name == 'DisableCameraShake': elif sel_name == 'DisableCameraShake':
sel = self._disable_camera_shake_check_box.widget sel = self._disable_camera_shake_check_box.widget
elif ( elif (

View File

@ -222,6 +222,7 @@ void AppConfig::SetupEntries() {
bool_entries_[BoolID::kAlwaysUseInternalKeyboard] = bool_entries_[BoolID::kAlwaysUseInternalKeyboard] =
BoolEntry("Always Use Internal Keyboard", g_buildconfig.iircade_build()); BoolEntry("Always Use Internal Keyboard", g_buildconfig.iircade_build());
bool_entries_[BoolID::kShowFPS] = BoolEntry("Show FPS", false); bool_entries_[BoolID::kShowFPS] = BoolEntry("Show FPS", false);
bool_entries_[BoolID::kShowPing] = BoolEntry("Show Ping", false);
bool_entries_[BoolID::kTVBorder] = bool_entries_[BoolID::kTVBorder] =
BoolEntry("TV Border", g_platform->IsRunningOnTV()); BoolEntry("TV Border", g_platform->IsRunningOnTV());
bool_entries_[BoolID::kKeyboardP2Enabled] = bool_entries_[BoolID::kKeyboardP2Enabled] =

View File

@ -61,6 +61,7 @@ class AppConfig {
kKickIdlePlayers, kKickIdlePlayers,
kAlwaysUseInternalKeyboard, kAlwaysUseInternalKeyboard,
kShowFPS, kShowFPS,
kShowPing,
kTVBorder, kTVBorder,
kKeyboardP2Enabled, kKeyboardP2Enabled,
kEnablePackageMods, kEnablePackageMods,

View File

@ -277,6 +277,47 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
c.Submit(); c.Submit();
} }
if (show_ping_) {
float ping{};
char ping_str[32];
if (ConnectionToHost* connection_to_host =
g_logic->connections()->connection_to_host()) {
if (connection_to_host->can_communicate()) {
ping = connection_to_host->current_ping();
snprintf(ping_str, sizeof(ping_str), "%.0f ms", ping);
if (ping_str != ping_string_) {
ping_string_ = ping_str;
if (!ping_text_group_.exists()) {
ping_text_group_ = Object::New<TextGroup>();
}
ping_text_group_->SetText(ping_string_);
}
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(0.5f, 0.9f, 0.5f, 1.0f);
if (ping > 100.0f) {
c.SetColor(0.8f, 0.8f, 0.0f, 1.0f);
}
if (ping > 500.0f) {
c.SetColor(0.9f, 0.2f, 0.2f, 1.0f);
}
int text_elem_count = ping_text_group_->GetElementCount();
for (int e = 0; e < text_elem_count; e++) {
c.SetTexture(ping_text_group_->GetElementTexture(e));
c.SetFlatness(1.0f);
c.PushTransform();
c.Translate(14.0f + (show_fps_ ? 30.0f : 0.0f), 0.1f,
kScreenMessageZDepth);
c.Scale(0.7f, 0.7f);
c.DrawMesh(ping_text_group_->GetElementMesh(e));
c.PopTransform();
}
c.Submit();
}
}
}
if (show_net_info_) { if (show_net_info_) {
char net_info_str[128]; char net_info_str[128];
int64_t in_count = 0; int64_t in_count = 0;
@ -287,8 +328,6 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
int64_t out_size_compressed = 0; int64_t out_size_compressed = 0;
int64_t resends = 0; int64_t resends = 0;
int64_t resends_size = 0; int64_t resends_size = 0;
bool do_ping = false;
float ping{};
bool show = false; bool show = false;
// Add in/out data for any host connection. // Add in/out data for any host connection.
@ -304,7 +343,6 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
outCount += connection_to_host->GetMessagesOutPerSecond(); outCount += connection_to_host->GetMessagesOutPerSecond();
resends += connection_to_host->GetMessageResendsPerSecond(); resends += connection_to_host->GetMessageResendsPerSecond();
resends_size += connection_to_host->GetBytesResentPerSecond(); resends_size += connection_to_host->GetBytesResentPerSecond();
ping = connection_to_host->average_ping();
} else { } else {
int connected_count = 0; int connected_count = 0;
for (auto&& i : g_logic->connections()->connections_to_clients()) { for (auto&& i : g_logic->connections()->connections_to_clients()) {
@ -321,40 +359,21 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
outCount += client->GetMessagesOutPerSecond(); outCount += client->GetMessagesOutPerSecond();
resends += client->GetMessageResendsPerSecond(); resends += client->GetMessageResendsPerSecond();
resends_size += client->GetBytesResentPerSecond(); resends_size += client->GetBytesResentPerSecond();
ping += client->average_ping();
}
// We want an average for ping.
if (connected_count > 0) {
ping /= static_cast<float>(connected_count);
} }
} }
if (show) { if (show) {
if (do_ping) { snprintf(net_info_str, sizeof(net_info_str),
snprintf(net_info_str, sizeof(net_info_str), "in: %d/%d/%d\nout: %d/%d/%d\nrpt: %d/%d",
"ping: %f\nin: %d/%d/%d\nout: %d/%d/%d\nrpt: " static_cast_check_fit<int>(in_size),
"%d/%d", static_cast_check_fit<int>(in_size_compressed),
ping, static_cast_check_fit<int>(in_size), static_cast_check_fit<int>(in_count),
static_cast_check_fit<int>(in_size_compressed), static_cast_check_fit<int>(out_size),
static_cast_check_fit<int>(in_count), static_cast_check_fit<int>(out_size_compressed),
static_cast_check_fit<int>(out_size), static_cast_check_fit<int>(outCount),
static_cast_check_fit<int>(out_size_compressed), static_cast_check_fit<int>(resends_size),
static_cast_check_fit<int>(outCount), static_cast_check_fit<int>(resends));
static_cast_check_fit<int>(resends_size),
static_cast_check_fit<int>(resends));
} else {
snprintf(net_info_str, sizeof(net_info_str),
"in: %d/%d/%d\nout: %d/%d/%d\nrpt: %d/%d",
static_cast_check_fit<int>(in_size),
static_cast_check_fit<int>(in_size_compressed),
static_cast_check_fit<int>(in_count),
static_cast_check_fit<int>(out_size),
static_cast_check_fit<int>(out_size_compressed),
static_cast_check_fit<int>(outCount),
static_cast_check_fit<int>(resends_size),
static_cast_check_fit<int>(resends));
}
net_info_str[sizeof(net_info_str) - 1] = 0; // in case we overran.. net_info_str[sizeof(net_info_str) - 1] = 0; // in case we overran..
if (net_info_str != net_info_string_) { if (net_info_str != net_info_string_) {
net_info_string_ = net_info_str; net_info_string_ = net_info_str;
@ -371,9 +390,7 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
c.SetTexture(net_info_text_group_->GetElementTexture(e)); c.SetTexture(net_info_text_group_->GetElementTexture(e));
c.SetFlatness(1.0f); c.SetFlatness(1.0f);
c.PushTransform(); c.PushTransform();
c.Translate(4.0f, c.Translate(4.0f, (show_fps_ ? 66.0f : 40.0f), kScreenMessageZDepth);
(show_fps_ ? 66.0f : 40.0f) + (do_ping ? 17.0f : 0.0f),
kScreenMessageZDepth);
c.Scale(0.7f, 0.7f); c.Scale(0.7f, 0.7f);
c.DrawMesh(net_info_text_group_->GetElementMesh(e)); c.DrawMesh(net_info_text_group_->GetElementMesh(e));
c.PopTransform(); c.PopTransform();

View File

@ -206,7 +206,7 @@ class Graphics {
float upper_top) -> void; float upper_top) -> void;
auto ReleaseFadeEndCommand() -> void; auto ReleaseFadeEndCommand() -> void;
auto set_show_fps(bool val) -> void { show_fps_ = val; } auto set_show_fps(bool val) -> void { show_fps_ = val; }
auto set_show_ping(bool val) -> void { show_ping_ = val; }
// FIXME - move to graphics_server // FIXME - move to graphics_server
auto set_tv_border(bool val) -> void { auto set_tv_border(bool val) -> void {
assert(InLogicThread()); assert(InLogicThread());
@ -358,11 +358,13 @@ class Graphics {
Object::Ref<ImageMesh> progress_bar_top_mesh_; Object::Ref<ImageMesh> progress_bar_top_mesh_;
Object::Ref<ImageMesh> load_dot_mesh_; Object::Ref<ImageMesh> load_dot_mesh_;
Object::Ref<TextGroup> fps_text_group_; Object::Ref<TextGroup> fps_text_group_;
Object::Ref<TextGroup> ping_text_group_;
Object::Ref<TextGroup> net_info_text_group_; Object::Ref<TextGroup> net_info_text_group_;
Object::Ref<SpriteMesh> shadow_blotch_mesh_; Object::Ref<SpriteMesh> shadow_blotch_mesh_;
Object::Ref<SpriteMesh> shadow_blotch_soft_mesh_; Object::Ref<SpriteMesh> shadow_blotch_soft_mesh_;
Object::Ref<SpriteMesh> shadow_blotch_soft_obj_mesh_; Object::Ref<SpriteMesh> shadow_blotch_soft_obj_mesh_;
std::string fps_string_; std::string fps_string_;
std::string ping_string_;
std::string net_info_string_; std::string net_info_string_;
std::vector<uint16_t> blotch_indices_; std::vector<uint16_t> blotch_indices_;
std::vector<VertexSprite> blotch_verts_; std::vector<VertexSprite> blotch_verts_;
@ -371,6 +373,7 @@ class Graphics {
std::vector<uint16_t> blotch_soft_obj_indices_; std::vector<uint16_t> blotch_soft_obj_indices_;
std::vector<VertexSprite> blotch_soft_obj_verts_; std::vector<VertexSprite> blotch_soft_obj_verts_;
bool show_fps_{}; bool show_fps_{};
bool show_ping_{};
bool show_net_info_{}; bool show_net_info_{};
bool tv_border_{}; bool tv_border_{};
bool floor_reflection_{}; bool floor_reflection_{};

View File

@ -24,6 +24,9 @@ const int kPacketPruneTime = 10000;
// How long to go between pruning our packets. // How long to go between pruning our packets.
const int kPacketPruneInterval = 1000; const int kPacketPruneInterval = 1000;
// How long to go between updating current ping.
const int kPingUpdateInterval = 2000;
Connection::Connection() { Connection::Connection() {
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
creation_time_ = last_average_update_time_ = GetRealTime(); creation_time_ = last_average_update_time_ = GetRealTime();
@ -84,11 +87,11 @@ void Connection::HandleResends(millisecs_t real_time,
if (j != out_messages_.end()) { if (j != out_messages_.end()) {
ReliableMessageOut& msg(j->second); ReliableMessageOut& msg(j->second);
if (!msg.acked) { if (!msg.acked) {
float smoothing = 0.95f; // Dont update too fast.
average_ping_ = if (real_time - last_ping_update_time_ > kPingUpdateInterval) {
smoothing * average_ping_ current_ping_ = static_cast<float>(real_time - msg.first_send_time);
+ (1.0f - smoothing) last_ping_update_time_ = real_time;
* static_cast<float>(real_time - msg.first_send_time); }
} }
msg.acked = true; msg.acked = true;
} }
@ -385,6 +388,15 @@ void Connection::Update() {
SendGamePacket(data); SendGamePacket(data);
} }
if (can_communicate()
&& real_time - last_ping_update_time_ > kPingUpdateInterval + 1000) {
// Send a reliable message if ping not updated in a while.
std::vector<uint8_t> data(1);
data[0] = BA_PACKET_SIMPLE_PING;
SendReliableMessage(data);
}
// Occasionally prune our in and out messages. // Occasionally prune our in and out messages.
if (real_time - last_prune_time_ > kPacketPruneInterval) { if (real_time - last_prune_time_ > kPacketPruneInterval) {
last_prune_time_ = real_time; last_prune_time_ = real_time;

View File

@ -63,7 +63,7 @@ class Connection : public Object {
auto GetBytesResentPerSecond() const -> int64_t { auto GetBytesResentPerSecond() const -> int64_t {
return last_resend_bytes_out_; return last_resend_bytes_out_;
} }
auto average_ping() const -> float { return average_ping_; } auto current_ping() const -> float { return current_ping_; }
auto can_communicate() const -> bool { return can_communicate_; } auto can_communicate() const -> bool { return can_communicate_; }
auto peer_spec() const -> const PlayerSpec& { return peer_spec_; } auto peer_spec() const -> const PlayerSpec& { return peer_spec_; }
void HandleGamePacketCompressed(const std::vector<uint8_t>& data); void HandleGamePacketCompressed(const std::vector<uint8_t>& data);
@ -106,7 +106,7 @@ class Connection : public Object {
// Leaf classes should set this when they start dying. // Leaf classes should set this when they start dying.
// This prevents any SendGamePacketCompressed() calls from happening. // This prevents any SendGamePacketCompressed() calls from happening.
bool connection_dying_{}; bool connection_dying_{};
float average_ping_{}; float current_ping_{};
int64_t last_resend_bytes_out_{}; int64_t last_resend_bytes_out_{};
int64_t last_bytes_out_{}; int64_t last_bytes_out_{};
int64_t last_bytes_out_compressed_{}; int64_t last_bytes_out_compressed_{};
@ -132,7 +132,7 @@ class Connection : public Object {
bool errored_{}; bool errored_{};
millisecs_t last_prune_time_{}; millisecs_t last_prune_time_{};
millisecs_t last_ack_send_time_{}; millisecs_t last_ack_send_time_{};
millisecs_t last_ping_update_time_{};
// These are explicitly 16 bit values. // These are explicitly 16 bit values.
uint16_t next_out_message_num_ = kFirstConnectionStateNum; uint16_t next_out_message_num_ = kFirstConnectionStateNum;
uint16_t next_out_unreliable_message_num_{}; uint16_t next_out_unreliable_message_num_{};

View File

@ -1292,6 +1292,8 @@ void Logic::ApplyConfig() {
chat_muted_ = g_app_config->Resolve(AppConfig::BoolID::kChatMuted); chat_muted_ = g_app_config->Resolve(AppConfig::BoolID::kChatMuted);
g_graphics->set_show_fps(g_app_config->Resolve(AppConfig::BoolID::kShowFPS)); g_graphics->set_show_fps(g_app_config->Resolve(AppConfig::BoolID::kShowFPS));
g_graphics->set_show_ping(
g_app_config->Resolve(AppConfig::BoolID::kShowPing));
// Set tv border (for both client and server). // Set tv border (for both client and server).
// FIXME: this should exist either on the client or the server; not both. // FIXME: this should exist either on the client or the server; not both.