From d5cb25206c76febbfb313741008643dbbbd98447 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 18 Sep 2025 16:57:34 +0200 Subject: [PATCH] Fix possible `sendPlayerPos` desync situation --- src/client/client.cpp | 25 ++++++++++++++++++------- src/client/client.h | 1 + 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index b1dfa59931..88fe0cc7ad 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -566,9 +566,8 @@ void Client::step(float dtime) { float &counter = m_playerpos_send_timer; counter += dtime; - if((m_state == LC_Ready) && (counter >= m_recommended_send_interval)) - { - counter = 0.0; + if (m_state == LC_Ready && counter >= m_recommended_send_interval) { + counter = 0; sendPlayerPos(); } } @@ -1403,7 +1402,7 @@ void Client::sendPlayerPos() f32 movement_speed = player->control.movement_speed; f32 movement_dir = player->control.movement_direction; - if ( + bool identical = ( player->last_position == player->getPosition() && player->last_speed == player->getSpeed() && player->last_pitch == player->getPitch() && @@ -1413,8 +1412,19 @@ void Client::sendPlayerPos() player->last_camera_inverted == camera_inverted && player->last_wanted_range == wanted_range && player->last_movement_speed == movement_speed && - player->last_movement_dir == movement_dir) - return; + player->last_movement_dir == movement_dir); + + if (identical) { + // Since the movement info is sent non-reliable an unfortunate desync might + // occur if we stop sending and the last packet gets lost or re-ordered. + // To make this situation less likely we stop sending duplicate packets + // only after a delay. + m_playerpos_repeat_count++; + if (m_playerpos_repeat_count >= 5) + return; + } else { + m_playerpos_repeat_count = 0; + } player->last_position = player->getPosition(); player->last_speed = player->getSpeed(); @@ -1778,7 +1788,8 @@ float Client::mediaReceiveProgress() return 1.0; // downloader only exists when not yet done } -void Client::drawLoadScreen(const std::wstring &text, float dtime, int percent) { +void Client::drawLoadScreen(const std::wstring &text, float dtime, int percent) +{ m_rendering_engine->run(); m_rendering_engine->draw_load_screen(text, guienv, m_tsrc, dtime, percent); } diff --git a/src/client/client.h b/src/client/client.h index 303f51fd4f..408b8d5ce8 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -476,6 +476,7 @@ private: float m_connection_reinit_timer = 0.1f; float m_avg_rtt_timer = 0.0f; float m_playerpos_send_timer = 0.0f; + int m_playerpos_repeat_count = 0; IntervalLimiter m_map_timer_and_unload_interval; IWritableTextureSource *m_tsrc;