From 6e1521caec90ae6fb84fa221c9d74191319225e7 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 9 Oct 2017 15:50:49 +0100 Subject: [PATCH] Reintroduce error messages when trying to open invalid rides (#6381) * Reintroduce error messages when trying to open invalid rides Mistake made during action refactor. I've added the ability to specify the error title and error args as well in the result constructor. In addition the set status will now perform a query to check if it is valid preventing error messages hitting the server. * Bring error message setting into the function This prevents any other function corrupting the message args. Looking at you update ride window. * Increment network version for error message fix on set status * Reintroduce the error title to set ride name * Try not to introduce bugs due to inverting logic --- src/openrct2/actions/GameAction.cpp | 15 +++++++ src/openrct2/actions/GameAction.h | 4 +- src/openrct2/actions/RideSetName.hpp | 8 ++-- src/openrct2/actions/RideSetStatus.hpp | 55 ++++++++++++++++++++++++-- src/openrct2/network/network.h | 2 +- 5 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/openrct2/actions/GameAction.cpp b/src/openrct2/actions/GameAction.cpp index 6641c4a63e..26a2dab4af 100644 --- a/src/openrct2/actions/GameAction.cpp +++ b/src/openrct2/actions/GameAction.cpp @@ -37,6 +37,21 @@ GameActionResult::GameActionResult(GA_ERROR error, rct_string_id message) ErrorMessage = message; } +GameActionResult::GameActionResult(GA_ERROR error, rct_string_id title, rct_string_id message) +{ + Error = error; + ErrorTitle = title; + ErrorMessage = message; +} + +GameActionResult::GameActionResult(GA_ERROR error, rct_string_id title, rct_string_id message, uint8 * args) +{ + Error = error; + ErrorTitle = title; + ErrorMessage = message; + Memory::CopyArray(ErrorMessageArgs, args, Util::CountOf(ErrorMessageArgs)); +} + namespace GameActions { static GameActionFactory _actions[GAME_COMMAND_COUNT]; diff --git a/src/openrct2/actions/GameAction.h b/src/openrct2/actions/GameAction.h index 3c0d3de1d9..439b019c18 100644 --- a/src/openrct2/actions/GameAction.h +++ b/src/openrct2/actions/GameAction.h @@ -73,13 +73,15 @@ public: GA_ERROR Error = GA_ERROR::OK; rct_string_id ErrorTitle = (rct_string_id)-1; rct_string_id ErrorMessage = (rct_string_id)-1; - uint8 ErrorMessageArgs[8] = { 0 }; + uint8 ErrorMessageArgs[12] = { 0 }; rct_xyz32 Position = { 0 }; money32 Cost = 0; uint16 ExpenditureType = 0; GameActionResult(); GameActionResult(GA_ERROR error, rct_string_id message); + GameActionResult(GA_ERROR error, rct_string_id title, rct_string_id message); + GameActionResult(GA_ERROR error, rct_string_id title, rct_string_id message, uint8 * args); GameActionResult(const GameActionResult&) = delete; virtual ~GameActionResult() {}; }; diff --git a/src/openrct2/actions/RideSetName.hpp b/src/openrct2/actions/RideSetName.hpp index 4309735738..ba86a9aacc 100644 --- a/src/openrct2/actions/RideSetName.hpp +++ b/src/openrct2/actions/RideSetName.hpp @@ -57,19 +57,19 @@ public: if (ride->type == RIDE_TYPE_NULL) { log_warning("Invalid game command for ride %u", _rideIndex); - return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_CANT_RENAME_RIDE_ATTRACTION, STR_NONE); } if (_name.empty()) { - return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_ATTRACTION_NAME); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_CANT_RENAME_RIDE_ATTRACTION, STR_INVALID_RIDE_ATTRACTION_NAME); } rct_string_id newUserStringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER | USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); if (newUserStringId == 0) { // TODO: Probably exhausted, introduce new error. - return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); + return std::make_unique(GA_ERROR::UNKNOWN, STR_CANT_RENAME_RIDE_ATTRACTION, STR_NONE); } user_string_free(newUserStringId); @@ -84,7 +84,7 @@ public: if (ride->type == RIDE_TYPE_NULL) { log_warning("Invalid game command for ride %u", _rideIndex); - return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_CANT_RENAME_RIDE_ATTRACTION, STR_NONE); } user_string_free(ride->name); diff --git a/src/openrct2/actions/RideSetStatus.hpp b/src/openrct2/actions/RideSetStatus.hpp index cc140abb69..e45816b321 100644 --- a/src/openrct2/actions/RideSetStatus.hpp +++ b/src/openrct2/actions/RideSetStatus.hpp @@ -25,6 +25,13 @@ #include "../world/park.h" #include "../ride/ride.h" +static rct_string_id _StatusErrorTitles[] = +{ + STR_CANT_CLOSE, + STR_CANT_OPEN, + STR_CANT_TEST +}; + struct RideSetStatusAction : public GameActionBase { private: @@ -53,10 +60,41 @@ public: GameActionResult::Ptr Query() const override { + GameActionResult::Ptr res = std::make_unique(); + Ride *ride = get_ride(_rideIndex); + res->ErrorTitle = _StatusErrorTitles[_status]; + set_format_arg_on(res->ErrorMessageArgs, 6, rct_string_id, ride->name); + set_format_arg_on(res->ErrorMessageArgs, 8, uint32, ride->name_arguments); + if (_rideIndex >= MAX_RIDES || _rideIndex < 0) { log_warning("Invalid game command for ride %u", _rideIndex); - return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_SELECTION_OF_OBJECTS); + res->Error = GA_ERROR::INVALID_PARAMETERS; + res->ErrorMessage = STR_INVALID_SELECTION_OF_OBJECTS; + return res; + } + + if (_status != ride->status) + { + if (_status == RIDE_STATUS_TESTING) + { + if (!ride_is_valid_for_test(_rideIndex, _status == RIDE_STATUS_OPEN, 0)) + { + log_warning("Ride %u not valid for test", _rideIndex); + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = gGameCommandErrorText; + return res; + } + } + else if (_status == RIDE_STATUS_OPEN) { + if (!ride_is_valid_for_open(_rideIndex, _status == RIDE_STATUS_OPEN, 0)) + { + log_warning("Ride %u not valid for open", _rideIndex); + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = gGameCommandErrorText; + return res; + } + } } return std::make_unique(); } @@ -67,11 +105,16 @@ public: res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; Ride *ride = get_ride(_rideIndex); + res->ErrorTitle = _StatusErrorTitles[_status]; + set_format_arg_on(res->ErrorMessageArgs, 6, rct_string_id, ride->name); + set_format_arg_on(res->ErrorMessageArgs, 8,uint32, ride->name_arguments); if (ride->type == RIDE_TYPE_NULL) { log_warning("Invalid game command for ride %u", _rideIndex); - return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_SELECTION_OF_OBJECTS); + res->Error = GA_ERROR::INVALID_PARAMETERS; + res->ErrorMessage = STR_INVALID_SELECTION_OF_OBJECTS; + return res; } if (ride->overall_view.xy != RCT_XY8_UNDEFINED) @@ -119,13 +162,17 @@ public: { if (!ride_is_valid_for_test(_rideIndex, _status == RIDE_STATUS_OPEN, 1)) { - //*ebx = MONEY32_UNDEFINED; + log_warning("Ride %u not valid for test", _rideIndex); + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = gGameCommandErrorText; return res; } } else if (!ride_is_valid_for_open(_rideIndex, _status == RIDE_STATUS_OPEN, 1)) { - //*ebx = MONEY32_UNDEFINED; + log_warning("Ride %u not valid for open", _rideIndex); + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = gGameCommandErrorText; return res; } diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index ae3893834f..c6bc647cf6 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -51,7 +51,7 @@ typedef struct GameAction GameAction; // 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 "8" +#define NETWORK_STREAM_VERSION "9" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #ifdef __cplusplus