From a4267990b868b2a15865361371c66bd5814aa42a Mon Sep 17 00:00:00 2001 From: zsilencer Date: Thu, 30 Jul 2015 08:34:17 -0600 Subject: [PATCH] detect desyncs --- src/network/network.cpp | 25 +++++++++++++++++++++++-- src/network/network.h | 3 +++ src/windows/network_status.c | 4 ++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 9770721cba..1df19ad80b 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -470,6 +470,17 @@ void Network::SendPacketToClients(NetworkPacket& packet) } } +bool Network::CheckSRAND(uint32 tick, uint32 srand0) +{ + if (tick == server_srand0_tick) { + server_srand0_tick = 0; + if (srand0 != server_srand0) { + return false; + } + } + return true; +} + void Network::Client_Send_AUTH(const char* gameversion, const char* name, const char* password) { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); @@ -532,7 +543,7 @@ void Network::Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx void Network::Server_Send_TICK() { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_TICK << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); + *packet << (uint32)NETWORK_COMMAND_TICK << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32); SendPacketToClients(*packet); } @@ -769,6 +780,7 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac pause_toggle(); game_command_queue.clear(); server_tick = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); + server_srand0_tick = 0; window_network_status_open("Loaded new map from network"); } SDL_RWclose(rw); @@ -826,7 +838,12 @@ int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet) { - packet >> server_tick; + uint32 srand0; + packet >> server_tick >> srand0; + if (server_srand0_tick == 0) { + server_srand0 = srand0; + server_srand0_tick = server_tick; + } return 1; } @@ -905,6 +922,10 @@ int network_begin_server(int port) void network_update() { gNetwork.Update(); + if (!gNetwork.CheckSRAND(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32), RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32))) { + window_network_status_open("Network desync detected"); + gNetwork.Close(); + } } int network_get_mode() diff --git a/src/network/network.h b/src/network/network.h index 286d725b39..392e8ecff1 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -135,6 +135,7 @@ public: NetworkPlayer* GetPlayerByID(int id); const char* FormatChat(NetworkPlayer* fromplayer, const char* text); void SendPacketToClients(NetworkPacket& packet); + bool CheckSRAND(uint32 tick, uint32 srand0); void Client_Send_AUTH(const char* gameversion, const char* name, const char* password); void Server_Send_MAP(); @@ -179,6 +180,8 @@ private: uint32 last_tick_sent_time; uint32 last_ping_sent_time; uint32 server_tick; + uint32 server_srand0; + uint32 server_srand0_tick; uint8 player_id; std::list> client_connection_list; std::multiset game_command_queue; diff --git a/src/windows/network_status.c b/src/windows/network_status.c index 441d93ebce..e0c5af29a0 100644 --- a/src/windows/network_status.c +++ b/src/windows/network_status.c @@ -79,6 +79,8 @@ void window_network_status_open(const char* text) { rct_window* window; + strncpy(window_network_status_text, text, sizeof(window_network_status_text)); + // Check if window is already open window = window_bring_to_front_by_class(WC_NETWORK_STATUS); if (window != NULL) @@ -86,8 +88,6 @@ void window_network_status_open(const char* text) window = window_create_centred(320, 90, &window_network_status_events, WC_NETWORK_STATUS, WF_10 | WF_TRANSPARENT); - strncpy(window_network_status_text, text, sizeof(window_network_status_text)); - window->widgets = window_network_status_widgets; window->enabled_widgets = 1 << WIDX_CLOSE; window_init_scroll_widgets(window);