Skip to content

Commit e2b694f

Browse files
committed
Prevent hangs in networking game if system clock running backwards
1 parent 62e3f3f commit e2b694f

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

src/main_loop.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "modes/profile_world.hpp"
3434
#include "modes/world.hpp"
3535
#include "network/network_config.hpp"
36+
#include "network/network_timer_synchronizer.hpp"
3637
#include "network/protocols/game_protocol.hpp"
3738
#include "network/protocol_manager.hpp"
3839
#include "network/race_event_manager.hpp"
@@ -118,6 +119,31 @@ float MainLoop::getLimitedDt()
118119
while( 1 )
119120
{
120121
m_curr_time = StkTime::getRealTimeMs();
122+
if (m_prev_time > m_curr_time)
123+
{
124+
m_prev_time = m_curr_time;
125+
// If system time adjusted backwards, return fixed dt and
126+
// resynchronize network timer if exists in client
127+
if (STKHost::existHost())
128+
{
129+
#ifndef SERVER_ONLY
130+
if (UserConfigParams::m_artist_debug_mode &&
131+
!ProfileWorld::isNoGraphics())
132+
{
133+
core::stringw err = L"System clock running backwards in"
134+
" networking game.";
135+
MessageQueue::add(MessageQueue::MT_ERROR, err);
136+
}
137+
#endif
138+
Log::error("MainLoop", "System clock running backwards in"
139+
" networking game.");
140+
if (STKHost::get()->getNetworkTimerSynchronizer())
141+
{
142+
STKHost::get()->getNetworkTimerSynchronizer()
143+
->resynchroniseTimer();
144+
}
145+
}
146+
}
121147
dt = (float)(m_curr_time - m_prev_time);
122148
// On a server (i.e. without graphics) the frame rate can be under
123149
// 1 ms, i.e. dt = 0. Additionally, the resolution of a sleep
@@ -128,12 +154,15 @@ float MainLoop::getLimitedDt()
128154
// with clients (server time is supposed to be behind client time).
129155
// So we play it safe by adding a loop to make sure at least 1ms
130156
// (minimum time that can be handled by the integer timer) delay here.
131-
// Only exception is profile mode (typically running without graphics),
132-
// which we want to run as fast as possible.
133-
while (dt <= 0 && !ProfileWorld::isProfileMode())
157+
while (dt == 0)
134158
{
135159
StkTime::sleep(1);
136160
m_curr_time = StkTime::getRealTimeMs();
161+
if (m_prev_time > m_curr_time)
162+
{
163+
Log::error("MainLopp", "System clock keeps backwards!");
164+
m_prev_time = m_curr_time;
165+
}
137166
dt = (float)(m_curr_time - m_prev_time);
138167
}
139168

src/network/network_timer_synchronizer.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class NetworkTimerSynchronizer
5353
m_force_set_timer.store(true);
5454
}
5555
// ------------------------------------------------------------------------
56+
void resynchroniseTimer() { m_synchronised.store(false); }
57+
// ------------------------------------------------------------------------
5658
void addAndSetTime(uint32_t ping, uint64_t server_time)
5759
{
5860
if (m_synchronised.load() == true)
@@ -94,6 +96,7 @@ class NetworkTimerSynchronizer
9496
UserConfigParams::m_timer_sync_difference_tolerance)
9597
{
9698
STKHost::get()->setNetworkTimer(averaged_time);
99+
m_times.clear();
97100
m_force_set_timer.store(false);
98101
m_synchronised.store(true);
99102
Log::info("NetworkTimerSynchronizer", "Network "

0 commit comments

Comments
 (0)