From 9e1711c345d549ecea2d9046bd9ae7f81d12305d Mon Sep 17 00:00:00 2001 From: ZehM4tt Date: Fri, 16 Jun 2017 09:45:00 +0200 Subject: [PATCH] Fix some scenery, path placement and construction mode desyncs --- src/openrct2/network/network.h | 2 +- src/openrct2/ride/ride.c | 7 +++++++ src/openrct2/world/footpath.c | 2 +- src/openrct2/world/scenery.c | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index ee8636b922..33ad9366d0 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -56,7 +56,7 @@ extern "C" { // This define 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 "12" +#define NETWORK_STREAM_VERSION "13" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #ifdef __cplusplus diff --git a/src/openrct2/ride/ride.c b/src/openrct2/ride/ride.c index 2b19038d75..33ed714301 100644 --- a/src/openrct2/ride/ride.c +++ b/src/openrct2/ride/ride.c @@ -1090,6 +1090,13 @@ void ride_clear_for_construction(sint32 rideIndex) ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN); ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; + // Open circuit rides will go directly into building mode (creating ghosts) where it would normally clear the stats, + // however this causes desyncs since it's directly run from the window and other clients would not get it. + // To prevent these problems, unconditionally invalidate the test results on all clients in multiplayer games. + if (network_get_mode() != NETWORK_MODE_NONE) { + invalidate_test_results(rideIndex); + } + ride_remove_cable_lift(ride); ride_remove_vehicles(ride); diff --git a/src/openrct2/world/footpath.c b/src/openrct2/world/footpath.c index 5d25c5a483..df22ba5705 100644 --- a/src/openrct2/world/footpath.c +++ b/src/openrct2/world/footpath.c @@ -346,7 +346,7 @@ static money32 footpath_place_real(sint32 type, sint32 x, sint32 y, sint32 z, si return MONEY32_UNDEFINED; } - if (flags & GAME_COMMAND_FLAG_APPLY) + if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_GHOST)) footpath_interrupt_peeps(x, y, z * 8); gFootpathPrice = 0; diff --git a/src/openrct2/world/scenery.c b/src/openrct2/world/scenery.c index 8b0de310f6..cdf9bde5b1 100644 --- a/src/openrct2/world/scenery.c +++ b/src/openrct2/world/scenery.c @@ -19,6 +19,7 @@ #include "../localisation/localisation.h" #include "../scenario/scenario.h" #include "../cheats.h" +#include "../network/network.h" #include "../object_list.h" #include "Climate.h" #include "Fountain.h" @@ -80,6 +81,14 @@ void scenery_update_tile(sint32 x, sint32 y) mapElement = map_get_first_element_at(x >> 5, y >> 5); do { + // Ghosts are purely this-client-side and should not cause any interaction, + // as that may lead to a desync. + if (network_get_mode() != NETWORK_MODE_NONE) + { + if (map_element_is_ghost(mapElement)) + continue; + } + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY) { scenery_update_age(x, y, mapElement); } else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { @@ -123,8 +132,14 @@ void scenery_update_age(sint32 x, sint32 y, rct_map_element *mapElement) // Check map elements above, presumably to see if map element is blocked from rain mapElementAbove = mapElement; while (!(mapElementAbove->flags & 7)) { + mapElementAbove++; + // Ghosts are purely this-client-side and should not cause any interaction, + // as that may lead to a desync. + if (map_element_is_ghost(mapElementAbove)) + continue; + switch (map_element_get_type(mapElementAbove)) { case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE: case MAP_ELEMENT_TYPE_ENTRANCE: