From 0c11bbd4e708d42587e824e9274634baf05a5313 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Oct 2019 13:09:21 +0200 Subject: [PATCH 1/3] Fix #9994: Game action tick collision during server connect and map load --- src/openrct2/actions/GameAction.cpp | 17 +++++++++++++++++ src/openrct2/actions/GameAction.h | 8 ++++++++ src/openrct2/network/Network.cpp | 11 +++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index 873dcfd9b3..bce93c20d7 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -76,6 +76,7 @@ namespace GameActions static GameActionFactory _actions[GAME_COMMAND_COUNT]; static std::multiset _actionQueue; static uint32_t _nextUniqueId = 0; + static bool _suspended = false; GameActionFactory Register(uint32_t id, GameActionFactory factory) { @@ -95,6 +96,16 @@ namespace GameActions return false; } + void SuspendQueue() + { + _suspended = true; + } + + void ResumeQueue() + { + _suspended = false; + } + void Enqueue(const GameAction* ga, uint32_t tick) { auto action = Clone(ga); @@ -114,6 +125,12 @@ namespace GameActions void ProcessQueue() { + if (_suspended) + { + // Do nothing if suspended, this is usually the case between connect and map loads. + return; + } + const uint32_t currentTick = gCurrentTicks; while (_actionQueue.begin() != _actionQueue.end()) diff --git a/src/openrct2/actions/GameAction.h b/src/openrct2/actions/GameAction.h index 13a517d7aa..c5f24d2534 100644 --- a/src/openrct2/actions/GameAction.h +++ b/src/openrct2/actions/GameAction.h @@ -255,6 +255,14 @@ namespace GameActions void Register(); bool IsValidId(uint32_t id); + // Halts the queue processing until ResumeQueue is called, any calls to ProcessQueue + // will have no effect during suspension. It has no effect of actions that will not + // cross the network. + void SuspendQueue(); + + // Resumes queue processing. + void ResumeQueue(); + void Enqueue(const GameAction* ga, uint32_t tick); void Enqueue(GameAction::Ptr&& ga, uint32_t tick); void ProcessQueue(); diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index 515a8f1f17..e4499e0d33 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -417,6 +417,7 @@ void Network::Close() client_connection_list.clear(); GameActions::ClearQueue(); + GameActions::ResumeQueue(); player_list.clear(); group_list.clear(); _serverTickData.clear(); @@ -493,6 +494,11 @@ bool Network::BeginClient(const std::string& host, uint16_t port) BeginChatLog(); BeginServerLog(); + // We need to wait for the map load before we execute any actions. + // If the client has the title screen running then theres a potential + // risk of tick collision with the server map and title screen map. + GameActions::SuspendQueue(); + utf8 keyPath[MAX_PATH]; network_get_private_key_path(keyPath, sizeof(keyPath), gConfigNetwork.player_name); if (!platform_file_exists(keyPath)) @@ -2615,6 +2621,8 @@ void Network::Client_Handle_MAP([[maybe_unused]] NetworkConnection& connection, // Start of a new map load, clear the queue now as we have to buffer them // until the map is fully loaded. GameActions::ClearQueue(); + GameActions::SuspendQueue(); + _serverTickData.clear(); _clientMapLoaded = false; } @@ -2637,6 +2645,9 @@ void Network::Client_Handle_MAP([[maybe_unused]] NetworkConnection& connection, std::memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize); if (offset + chunksize == size) { + // Allow queue processing of game actions again. + GameActions::ResumeQueue(); + context_force_close_window_by_class(WC_NETWORK_STATUS); bool has_to_free = false; uint8_t* data = &chunk_buffer[0]; From 884611c20b19dbcd528657580e4b887b526d686d Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Oct 2019 13:13:44 +0200 Subject: [PATCH 2/3] Bump up network version --- src/openrct2/network/Network.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index e4499e0d33..282db25a4a 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -34,7 +34,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "17" +#define NETWORK_STREAM_VERSION "18" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; From e149b8c051368a84d5bc9650447ee43d8470732f Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Oct 2019 13:14:21 +0200 Subject: [PATCH 3/3] Update changelog.txt --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 3d1b7825e6..aab0f1c097 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -25,6 +25,7 @@ - Fix: [#9955] Resizing map in while pause mode does not work and may result in freezes. - Fix: [#9957] When using 'no money' cheat, guests complain of running out of cash. - Fix: [#9970] Wait for quarter load fails. +- Fix: [#9994] Game action tick collision during server connect and map load. - Fix: [#10017] Ghost elements influencing ride excitement. - Fix: [#10036] Do not allocate large chunks of memory for save file classification. - Improved: [#9466] Add the rain weather effect to the OpenGL renderer.