From 995c0d0a6b79ba4dbf51b184d1e06ea88cef6e7e Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Thu, 7 Sep 2017 01:37:03 +0200 Subject: [PATCH] Refactor SetParkEntranceFeeAction to use constructor for parameters. Add RideSetNameAction. Support of string serialisation. --- openrct2.sln | 8 +- src/openrct2/actions/GameActionCompat.cpp | 28 ++++- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/RideSetName.hpp | 117 +++++++++++++++++ .../actions/SetParkEntranceFeeAction.hpp | 15 ++- src/openrct2/core/DataSerialiserTraits.h | 23 ++++ src/openrct2/game.h | 2 +- src/openrct2/ride/ride.c | 118 ------------------ 8 files changed, 184 insertions(+), 129 deletions(-) create mode 100644 src/openrct2/actions/RideSetName.hpp diff --git a/openrct2.sln b/openrct2.sln index 8283dd4ee9..75d8a67625 100644 --- a/openrct2.sln +++ b/openrct2.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2-dll", "src\openrct2-dll\openrct2-dll.vcxproj", "{7B8DB129-79EF-417E-B372-8A18E009D261}" ProjectSection(ProjectDependencies) = postProject @@ -38,6 +38,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2-cli", "src\openrct EndProjectSection EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 @@ -105,4 +108,7 @@ Global {8DD8AB7D-2EA6-44E3-8265-BAF08E832951} = {2202A816-377D-4FA0-A7AF-7D4105F8A4FB} {B6808F71-30B4-4499-8FF6-0B1C86391842} = {2202A816-377D-4FA0-A7AF-7D4105F8A4FB} EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/src/openrct2/actions/GameActionCompat.cpp b/src/openrct2/actions/GameActionCompat.cpp index cbb7135a6f..1bcf0ea7a7 100644 --- a/src/openrct2/actions/GameActionCompat.cpp +++ b/src/openrct2/actions/GameActionCompat.cpp @@ -19,6 +19,7 @@ #include "SetParkEntranceFeeAction.hpp" #include "RideCreateAction.hpp" #include "RideSetStatus.hpp" +#include "RideSetName.hpp" extern "C" { @@ -77,17 +78,16 @@ extern "C" #pragma endregion #pragma region SetParkEntranceFeeAction - void park_set_entrance_fee(money32 value) + void park_set_entrance_fee(money32 fee) { - auto gameAction = SetParkEntranceFeeAction(); - gameAction.Fee = (money16)value; + auto gameAction = SetParkEntranceFeeAction((money16)fee); GameActions::Execute(&gameAction); } void game_command_set_park_entrance_fee(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { - auto gameAction = SetParkEntranceFeeAction(); - gameAction.Fee = (*edi & 0xFFFF); + money16 fee = (money16)(*edi & 0xFFFF); + auto gameAction = SetParkEntranceFeeAction(fee); GameActions::Execute(&gameAction); } #pragma endregion @@ -163,4 +163,22 @@ extern "C" } #pragma endregion + +#pragma region RideSetName + void ride_set_name(sint32 rideIndex, const char *name) + { + auto gameAction = RideSetNameAction(rideIndex, name); + GameActions::Execute(&gameAction); + } + + /** + * + * rct2: 0x006B578B + */ + void game_command_set_ride_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp) + { + Guard::Assert(false, "GAME_COMMAND_SET_RIDE_NAME DEPRECATED"); + } +#pragma endregion + } diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 5cbcfd4220..19260d6d12 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -19,6 +19,7 @@ #include "SetParkEntranceFeeAction.hpp" #include "RideCreateAction.hpp" #include "RideSetStatus.hpp" +#include "RideSetName.hpp" namespace GameActions { @@ -28,5 +29,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/actions/RideSetName.hpp b/src/openrct2/actions/RideSetName.hpp new file mode 100644 index 0000000000..35d83879b5 --- /dev/null +++ b/src/openrct2/actions/RideSetName.hpp @@ -0,0 +1,117 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../core/MemoryStream.h" +#include "../localisation/string_ids.h" +#include "GameAction.h" + +extern "C" +{ + #include "../cheats.h" + #include "../interface/window.h" + #include "../localisation/localisation.h" + #include "../world/park.h" +} + +struct RideSetNameAction : public GameActionBase +{ +private: + sint32 _rideIndex; + std::string _name; + +public: + RideSetNameAction() {} + RideSetNameAction(sint32 rideIndex, const std::string& name) + : _rideIndex(rideIndex), + _name(name) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + + stream << _rideIndex << _name; + } + + GameActionResult::Ptr Query() const override + { + rct_ride *ride = get_ride(_rideIndex); + 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); + } + + if (_name.empty()) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, 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); + } + user_string_free(newUserStringId); + + return std::make_unique(); + } + + GameActionResult::Ptr Execute() const override + { + rct_string_id newUserStringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER | USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (newUserStringId == 0) + { + // FIXME: Regardless of Query this can still happen, + // if the server has sent new commands before our own fired. + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); + } + + rct_ride *ride = get_ride(_rideIndex); + 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); + } + + user_string_free(ride->name); + ride->name = newUserStringId; + + gfx_invalidate_screen(); + + // Force ride list window refresh + rct_window *w = window_find_by_class(WC_RIDE_LIST); + if (w != NULL) + w->no_list_items = 0; + + auto res = std::make_unique(); + res->Position.x = ride->overall_view.x * 32 + 16; + res->Position.y = ride->overall_view.y * 32 + 16; + res->Position.z = map_element_height(res->Position.x, res->Position.y); + + return std::move(res); + } +}; + diff --git a/src/openrct2/actions/SetParkEntranceFeeAction.hpp b/src/openrct2/actions/SetParkEntranceFeeAction.hpp index cf66b49b41..f349d6c247 100644 --- a/src/openrct2/actions/SetParkEntranceFeeAction.hpp +++ b/src/openrct2/actions/SetParkEntranceFeeAction.hpp @@ -29,8 +29,15 @@ extern "C" struct SetParkEntranceFeeAction : public GameActionBase { +private: + money16 _fee; + public: - money16 Fee; + SetParkEntranceFeeAction() {} + SetParkEntranceFeeAction(money16 fee) + : _fee(fee) + { + } uint16 GetActionFlags() const override { @@ -41,7 +48,7 @@ public: { GameAction::Serialise(stream); - stream << Fee; + stream << _fee; } GameActionResult::Ptr Query() const override @@ -52,7 +59,7 @@ public: { return std::make_unique(GA_ERROR::DISALLOWED, STR_NONE); } - if (Fee < MONEY_FREE || Fee > MONEY(100,00)) + if (_fee < MONEY_FREE || _fee > MONEY(100,00)) { return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_NONE); } @@ -61,7 +68,7 @@ public: GameActionResult::Ptr Execute() const override { - gParkEntranceFee = Fee; + gParkEntranceFee = _fee; window_invalidate_by_class(WC_PARK_INFORMATION); return std::make_unique(); } diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 9c75ec61d9..307fc3ce2e 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -58,3 +58,26 @@ struct DataSerializerTraits : public DataSerializerTraitsIntegral struct DataSerializerTraits : public DataSerializerTraitsIntegral {}; + +template<> +struct DataSerializerTraits +{ + static void encode(IStream *stream, const std::string& str) + { + uint16 len = (uint16)str.size(); + len = ByteSwapBE(len); + stream->Write(&len); + stream->WriteArray(str.c_str(), len); + } + static void decode(IStream *stream, std::string& res) + { + uint16 len; + stream->Read(&len); + len = ByteSwapBE(len); + + const char* str = stream->ReadArray(len); + res.assign(str, len); + + Memory::FreeArray(str, len); + } +}; \ No newline at end of file diff --git a/src/openrct2/game.h b/src/openrct2/game.h index 99b89ddcdb..ba34836332 100644 --- a/src/openrct2/game.h +++ b/src/openrct2/game.h @@ -32,7 +32,7 @@ enum GAME_COMMAND { GAME_COMMAND_DEMOLISH_RIDE, GAME_COMMAND_SET_RIDE_STATUS, // GA GAME_COMMAND_SET_RIDE_VEHICLES, - GAME_COMMAND_SET_RIDE_NAME, + GAME_COMMAND_SET_RIDE_NAME, // GA GAME_COMMAND_SET_RIDE_SETTING, GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT, diff --git a/src/openrct2/ride/ride.c b/src/openrct2/ride/ride.c index 95af5593e4..69dcd099f3 100644 --- a/src/openrct2/ride/ride.c +++ b/src/openrct2/ride/ride.c @@ -5451,124 +5451,6 @@ sint32 ride_is_valid_for_open(sint32 rideIndex, sint32 goingToBeOpen, sint32 isA return 1; } -void ride_set_name(sint32 rideIndex, const char *name) -{ - typedef union name_union { - char as_char[4]; - sint32 as_int; - } name_union; - - name_union name_buffer[9]; - safe_strcpy((char *)name_buffer, name, sizeof(name_buffer)); - gGameCommandErrorTitle = STR_CANT_RENAME_RIDE_ATTRACTION; - game_do_command(1, (rideIndex << 8) | 1, 0, name_buffer[0].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[2].as_int, name_buffer[1].as_int); - game_do_command(2, (rideIndex << 8) | 1, 0, name_buffer[3].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[5].as_int, name_buffer[4].as_int); - game_do_command(0, (rideIndex << 8) | 1, 0, name_buffer[6].as_int, GAME_COMMAND_SET_RIDE_NAME, name_buffer[8].as_int, name_buffer[7].as_int); -} - -/** - * - * rct2: 0x006B578B - */ -void game_command_set_ride_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp) -{ - char oldName[128]; - static char newName[128]; - - sint32 rideIndex = (*ebx >> 8) & 0xFF; - if (rideIndex >= MAX_RIDES) - { - log_warning("Invalid game command for ride %u", rideIndex); - *ebx = MONEY32_UNDEFINED; - return; - } - sint32 nameChunkIndex = *eax & 0xFFFF; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - //if (*ebx & GAME_COMMAND_FLAG_APPLY) { // this check seems to be useless and causes problems in multiplayer - sint32 nameChunkOffset = nameChunkIndex - 1; - if (nameChunkOffset < 0) - nameChunkOffset = 2; - nameChunkOffset *= 12; - nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 0), edx, sizeof(uint32)); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 4), ebp, sizeof(uint32)); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 8), edi, sizeof(uint32)); - //} - - if (nameChunkIndex != 0) { - *ebx = 0; - return; - } - - Ride *ride = get_ride(rideIndex); - if (ride->type == RIDE_TYPE_NULL) - { - log_warning("Invalid game command for ride %u", rideIndex); - *ebx = MONEY32_UNDEFINED; - return; - } - format_string(oldName, 128, ride->name, &ride->name_arguments); - if (strcmp(oldName, newName) == 0) { - *ebx = 0; - return; - } - - if (newName[0] == 0) { - gGameCommandErrorText = STR_INVALID_RIDE_ATTRACTION_NAME; - *ebx = MONEY32_UNDEFINED; - return; - } - - rct_string_id newUserStringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER | USER_STRING_DUPLICATION_PERMITTED, newName); - if (newUserStringId == 0) { - *ebx = MONEY32_UNDEFINED; - return; - } - - if (*ebx & GAME_COMMAND_FLAG_APPLY) { - // Log ride rename command if we are in multiplayer and logging is enabled - if ((network_get_mode() == NETWORK_MODE_CLIENT || network_get_mode() == NETWORK_MODE_SERVER) && gConfigNetwork.log_server_actions) { - // Get player name - int player_index = network_get_player_index(game_command_playerid); - const char* player_name = network_get_player_name(player_index); - - char log_msg[256]; - char* args[3] = { - (char *) player_name, - oldName, - newName - }; - format_string(log_msg, 256, STR_LOG_RIDE_NAME, args); - network_append_server_log(log_msg); - } - - if (ride->overall_view.xy != RCT_XY8_UNDEFINED) { - rct_xyz16 coord; - coord.x = ride->overall_view.x * 32 + 16; - coord.y = ride->overall_view.y * 32 + 16; - coord.z = map_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } - - // Free the old ride name - user_string_free(ride->name); - - ride->name = newUserStringId; - - gfx_invalidate_screen(); - - // Force ride list window refresh - rct_window *w = window_find_by_class(WC_RIDE_LIST); - if (w != NULL) - w->no_list_items = 0; - } else { - user_string_free(newUserStringId); - } - - *ebx = 0; -} - /** * * rct2: 0x006CB7FB