From 2906cb8c891a9b2871c3ecc946dfbc426604bd8b Mon Sep 17 00:00:00 2001 From: frutiemax Date: Wed, 29 Sep 2021 11:46:03 -0400 Subject: [PATCH] Fix #14474: Map size can be synced in multiplayer (#15312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #14474: Map size can be synced in multiplayer * Bump up network version Co-authored-by: ζeh Matt <5415177+ZehMatt@users.noreply.github.com> --- OpenRCT2.xcodeproj/project.pbxproj | 8 ++ src/openrct2-ui/windows/Map.cpp | 40 ++-------- src/openrct2/Game.h | 1 + src/openrct2/actions/ChangeMapSizeAction.cpp | 77 +++++++++++++++++++ src/openrct2/actions/ChangeMapSizeAction.h | 30 ++++++++ .../actions/GameActionRegistration.cpp | 2 + src/openrct2/libopenrct2.vcxproj | 2 + src/openrct2/network/NetworkAction.cpp | 1 + src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/world/Map.cpp | 8 +- 10 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 src/openrct2/actions/ChangeMapSizeAction.cpp create mode 100644 src/openrct2/actions/ChangeMapSizeAction.h diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index b53a9e1c1d..2277e03052 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -803,6 +803,8 @@ C8D612EB56BD4214BEC0F7FF /* GroupVector.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F4D523B8782E4C458AF1490D /* GroupVector.hpp */; }; B2F44E535BD14A03BE8B9D14 /* ZipStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F28A181D311D4E078FDB090C /* ZipStream.hpp */; }; 7CDC7EE9B12E40FB9FE78546 /* Crypt.OpenRCT2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4248E4E4394842D4AF6119DA /* Crypt.OpenRCT2.cpp */; }; + 4653963391E945D397BCCA0C /* ChangeMapSizeAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76CE81CEAF7F4538976F7C4C /* ChangeMapSizeAction.cpp */; }; + F1BE1CB5525C4FF794A3F3CE /* ChangeMapSizeAction.h in Headers */ = {isa = PBXBuildFile; fileRef = C49050C073DB4CB980E1EC5A /* ChangeMapSizeAction.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1909,6 +1911,8 @@ F4D523B8782E4C458AF1490D /* GroupVector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GroupVector.hpp; path = src/openrct2/core/GroupVector.hpp; sourceTree = SOURCE_ROOT; }; F28A181D311D4E078FDB090C /* ZipStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZipStream.hpp; path = src/openrct2/core/ZipStream.hpp; sourceTree = SOURCE_ROOT; }; 4248E4E4394842D4AF6119DA /* Crypt.OpenRCT2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Crypt.OpenRCT2.cpp; path = src/openrct2/core/Crypt.OpenRCT2.cpp; sourceTree = SOURCE_ROOT; }; + 76CE81CEAF7F4538976F7C4C /* ChangeMapSizeAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ChangeMapSizeAction.cpp; path = src/openrct2/actions/ChangeMapSizeAction.cpp; sourceTree = SOURCE_ROOT; }; + C49050C073DB4CB980E1EC5A /* ChangeMapSizeAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChangeMapSizeAction.h; path = src/openrct2/actions/ChangeMapSizeAction.h; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2225,6 +2229,8 @@ 66A10FC3257F1E2E00DD651A /* WaterRaiseAction.h */, 66A10FC7257F1E2E00DD651A /* WaterSetHeightAction.cpp */, 66A10FC8257F1E2F00DD651A /* WaterSetHeightAction.h */, + 76CE81CEAF7F4538976F7C4C /* ChangeMapSizeAction.cpp */, + C49050C073DB4CB980E1EC5A /* ChangeMapSizeAction.h */, ); path = actions; sourceTree = ""; @@ -3665,6 +3671,7 @@ E6C71B6165224F65AA87E65B /* RideUseSystem.h in Headers */, C8D612EB56BD4214BEC0F7FF /* GroupVector.hpp in Headers */, B2F44E535BD14A03BE8B9D14 /* ZipStream.hpp in Headers */, + F1BE1CB5525C4FF794A3F3CE /* ChangeMapSizeAction.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4488,6 +4495,7 @@ 6C90BE01D190493295071B23 /* ScTile.cpp in Sources */, 258C212125F84FA2B4C3BCAE /* RideUseSystem.cpp in Sources */, 7CDC7EE9B12E40FB9FE78546 /* Crypt.OpenRCT2.cpp in Sources */, + 4653963391E945D397BCCA0C /* ChangeMapSizeAction.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/openrct2-ui/windows/Map.cpp b/src/openrct2-ui/windows/Map.cpp index f0a7d65b61..f04b0f44ce 100644 --- a/src/openrct2-ui/windows/Map.cpp +++ b/src/openrct2-ui/windows/Map.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -655,17 +656,8 @@ static void window_map_textinput(rct_window* w, rct_widgetindex widgetIndex, cha size += 2; size = std::clamp(size, MINIMUM_MAP_SIZE_TECHNICAL, MAXIMUM_MAP_SIZE_TECHNICAL); - int32_t currentSize = gMapSize; - while (size < currentSize) - { - map_window_decrease_map_size(); - currentSize--; - } - while (size > currentSize) - { - map_window_increase_map_size(); - currentSize++; - } + auto changeMapSizeAction = ChangeMapSizeAction(size); + GameActions::Execute(&changeMapSizeAction); w->Invalidate(); } break; @@ -1370,17 +1362,8 @@ static void window_map_set_peep_spawn_tool_down(const ScreenCoordsXY& screenCoor */ static void map_window_increase_map_size() { - if (gMapSize >= MAXIMUM_MAP_SIZE_TECHNICAL) - { - context_show_error(STR_CANT_INCREASE_MAP_SIZE_ANY_FURTHER, STR_NONE, {}); - return; - } - - gMapSize++; - map_extend_boundary_surface(); - window_map_init_map(); - window_map_centre_on_view_point(); - gfx_invalidate_screen(); + auto increaseMapSizeAction = ChangeMapSizeAction(gMapSize + 1); + GameActions::Execute(&increaseMapSizeAction); } /** @@ -1389,17 +1372,8 @@ static void map_window_increase_map_size() */ static void map_window_decrease_map_size() { - if (gMapSize < 16) - { - context_show_error(STR_CANT_DECREASE_MAP_SIZE_ANY_FURTHER, STR_NONE, {}); - return; - } - - gMapSize--; - map_remove_out_of_range_elements(); - window_map_init_map(); - window_map_centre_on_view_point(); - gfx_invalidate_screen(); + auto decreaseMapSizeAction = ChangeMapSizeAction(gMapSize - 1); + GameActions::Execute(&decreaseMapSizeAction); } static constexpr const uint16_t WaterColour = MapColour(PALETTE_INDEX_195); diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 897f6eb518..107a66e207 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -103,6 +103,7 @@ enum class GameCommand : int32_t GuestSetFlags, // GA SetDate, // GA Custom, // GA + ChangeMapSize, Count, }; diff --git a/src/openrct2/actions/ChangeMapSizeAction.cpp b/src/openrct2/actions/ChangeMapSizeAction.cpp new file mode 100644 index 0000000000..fb55284220 --- /dev/null +++ b/src/openrct2/actions/ChangeMapSizeAction.cpp @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "ChangeMapSizeAction.h" + +#include "../Context.h" +#include "../drawing/IDrawingEngine.h" +#include "../ui/UiContext.h" +#include "../ui/WindowManager.h" +#include "../windows/Intent.h" + +ChangeMapSizeAction::ChangeMapSizeAction(const int32_t targetSize) + : _targetSize(targetSize) +{ +} + +uint16_t ChangeMapSizeAction::GetActionFlags() const +{ + return GameAction::GetActionFlags() | GameActions::Flags::AllowWhilePaused; +} + +void ChangeMapSizeAction::Serialise(DataSerialiser& stream) +{ + GameAction::Serialise(stream); + stream << DS_TAG(_targetSize); +} + +GameActions::Result::Ptr ChangeMapSizeAction::Query() const +{ + if (_targetSize >= MAXIMUM_MAP_SIZE_TECHNICAL) + { + return std::make_unique( + GameActions::Status::InvalidParameters, STR_CANT_INCREASE_MAP_SIZE_ANY_FURTHER, STR_NONE); + } + if (_targetSize < 16) + { + return std::make_unique( + GameActions::Status::InvalidParameters, STR_CANT_DECREASE_MAP_SIZE_ANY_FURTHER, STR_NONE); + } + return std::make_unique(); +} + +GameActions::Result::Ptr ChangeMapSizeAction::Execute() const +{ + while (gMapSize != _targetSize) + { + if (_targetSize < gMapSize) + { + gMapSize--; + map_remove_out_of_range_elements(); + } + else + { + gMapSize++; + map_extend_boundary_surface(); + } + } + + auto* ctx = OpenRCT2::GetContext(); + auto uiContext = ctx->GetUiContext(); + auto* windowManager = uiContext->GetWindowManager(); + + windowManager->BroadcastIntent(Intent(INTENT_ACTION_MAP)); + gfx_invalidate_screen(); + return std::make_unique(); +} + +void ChangeMapSizeAction::AcceptParameters(GameActionParameterVisitor& visitor) +{ + visitor.Visit("targetSize", _targetSize); +} diff --git a/src/openrct2/actions/ChangeMapSizeAction.h b/src/openrct2/actions/ChangeMapSizeAction.h new file mode 100644 index 0000000000..93d3e021fc --- /dev/null +++ b/src/openrct2/actions/ChangeMapSizeAction.h @@ -0,0 +1,30 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../world/Map.h" +#include "GameAction.h" + +DEFINE_GAME_ACTION(ChangeMapSizeAction, GameCommand::ChangeMapSize, GameActions::Result) +{ +public: + ChangeMapSizeAction() = default; + ChangeMapSizeAction(const int32_t targetSize); + + void AcceptParameters(GameActionParameterVisitor & visitor) override; + uint16_t GetActionFlags() const override; + + void Serialise(DataSerialiser & stream) override; + GameActions::Result::Ptr Query() const override; + GameActions::Result::Ptr Execute() const override; + +private: + int32_t _targetSize; +}; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 872883540c..e48bfa8d73 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -13,6 +13,7 @@ #include "BannerSetColourAction.h" #include "BannerSetNameAction.h" #include "BannerSetStyleAction.h" +#include "ChangeMapSizeAction.h" #include "ClearAction.h" #include "ClimateSetAction.h" #include "CustomAction.h" @@ -172,6 +173,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); #ifdef ENABLE_SCRIPTING Register(); #endif diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 128fabe6d8..94467bebb8 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -58,6 +58,7 @@ + @@ -505,6 +506,7 @@ + diff --git a/src/openrct2/network/NetworkAction.cpp b/src/openrct2/network/NetworkAction.cpp index 99e6e8c2c2..005de69e7c 100644 --- a/src/openrct2/network/NetworkAction.cpp +++ b/src/openrct2/network/NetworkAction.cpp @@ -200,6 +200,7 @@ const std::array(NetworkPermission::Count)> N GameCommand::PlaceParkEntrance, GameCommand::RemoveParkEntrance, GameCommand::PlacePeepSpawn, + GameCommand::ChangeMapSize, }, }, NetworkAction{ diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index ee2555fdc6..5ecd915704 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -38,7 +38,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 "10" +#define NETWORK_STREAM_VERSION "11" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 7f9be950eb..eb3ddb0e4c 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1752,7 +1752,7 @@ static void clear_element_at(const CoordsXY& loc, TileElement** elementPtr) break; } auto parkEntranceRemoveAction = ParkEntranceRemoveAction(CoordsXYZ{ seqLoc, element->GetBaseZ() }); - auto result = GameActions::Execute(&parkEntranceRemoveAction); + auto result = GameActions::ExecuteNested(&parkEntranceRemoveAction); // If asking nicely did not work, forcibly remove this to avoid an infinite loop. if (result->Error != GameActions::Status::Ok) { @@ -1764,7 +1764,7 @@ static void clear_element_at(const CoordsXY& loc, TileElement** elementPtr) { CoordsXYZD wallLocation = { loc.x, loc.y, element->GetBaseZ(), element->GetDirection() }; auto wallRemoveAction = WallRemoveAction(wallLocation); - auto result = GameActions::Execute(&wallRemoveAction); + auto result = GameActions::ExecuteNested(&wallRemoveAction); // If asking nicely did not work, forcibly remove this to avoid an infinite loop. if (result->Error != GameActions::Status::Ok) { @@ -1776,7 +1776,7 @@ static void clear_element_at(const CoordsXY& loc, TileElement** elementPtr) { auto removeSceneryAction = LargeSceneryRemoveAction( { loc.x, loc.y, element->GetBaseZ(), element->GetDirection() }, element->AsLargeScenery()->GetSequenceIndex()); - auto result = GameActions::Execute(&removeSceneryAction); + auto result = GameActions::ExecuteNested(&removeSceneryAction); // If asking nicely did not work, forcibly remove this to avoid an infinite loop. if (result->Error != GameActions::Status::Ok) { @@ -1788,7 +1788,7 @@ static void clear_element_at(const CoordsXY& loc, TileElement** elementPtr) { auto bannerRemoveAction = BannerRemoveAction( { loc.x, loc.y, element->GetBaseZ(), element->AsBanner()->GetPosition() }); - auto result = GameActions::Execute(&bannerRemoveAction); + auto result = GameActions::ExecuteNested(&bannerRemoveAction); // If asking nicely did not work, forcibly remove this to avoid an infinite loop. if (result->Error != GameActions::Status::Ok) {