From 199a3e33f4752ca10fec2f36b0e91275b93bb591 Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 04:52:47 +0100 Subject: [PATCH 1/5] Implement game action for sign naming. --- src/openrct2-ui/windows/Sign.cpp | 9 +- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/SignSetNameAction.hpp | 122 ++++++++++++++++++ src/openrct2/world/Map.cpp | 69 ---------- src/openrct2/world/Map.h | 1 - 7 files changed, 131 insertions(+), 76 deletions(-) create mode 100644 src/openrct2/actions/SignSetNameAction.hpp diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 161f7491ff..6cb577b5d8 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #define WW 113 #define WH 96 @@ -316,10 +317,10 @@ static void window_sign_dropdown(rct_window *w, rct_widgetindex widgetIndex, sin */ static void window_sign_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text) { - if (widgetIndex == WIDX_SIGN_TEXT && text != nullptr) { - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 0)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 8)), *((sint32*)(text + 4))); - game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 12)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 20)), *((sint32*)(text + 16))); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 24)), GAME_COMMAND_SET_SIGN_NAME, *((sint32*)(text + 32)), *((sint32*)(text + 28))); + if (widgetIndex == WIDX_SIGN_TEXT && text != nullptr) + { + auto signSetNameAction = SignSetNameAction(w->number, text); + GameActions::Execute(&signSetNameAction); } } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index b0f57a41d9..5cb7a105da 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1747,7 +1747,7 @@ GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = { game_command_set_land_ownership, game_command_clear_scenery, game_command_set_banner_name, - game_command_set_sign_name, + nullptr, game_command_set_banner_style, game_command_set_sign_style, game_command_set_player_group, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 27276b51f4..3c78ef9582 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -83,7 +83,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_CLEAR_SCENERY, GAME_COMMAND_SET_BANNER_NAME, - GAME_COMMAND_SET_SIGN_NAME, + GAME_COMMAND_SET_SIGN_NAME, // GA GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE, GAME_COMMAND_SET_PLAYER_GROUP, diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 38c8f25726..807331c41c 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -29,6 +29,7 @@ #include "RideDemolishAction.hpp" #include "PlacePeepSpawnAction.hpp" #include "MazeSetTrackAction.hpp" +#include "SignSetNameAction.hpp" namespace GameActions { @@ -48,5 +49,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/actions/SignSetNameAction.hpp b/src/openrct2/actions/SignSetNameAction.hpp new file mode 100644 index 0000000000..83c2e12564 --- /dev/null +++ b/src/openrct2/actions/SignSetNameAction.hpp @@ -0,0 +1,122 @@ +#pragma region Copyright (c) 2014-2018 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 "../Context.h" +#include "../core/MemoryStream.h" +#include "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../world/Sprite.h" +#include "../world/Banner.h" +#include "GameAction.h" + +using namespace OpenRCT2; + +struct SignSetNameAction : public GameActionBase +{ +private: + sint32 _bannerIndex; + std::string _name; + +public: + SignSetNameAction() {} + SignSetNameAction(sint32 bannerIndex, const std::string& name) + : _bannerIndex(bannerIndex), + _name(name) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + stream << _bannerIndex << _name; + } + + GameActionResult::Ptr Query() const override + { + if (_bannerIndex >= MAX_BANNERS || _bannerIndex < 0) + { + log_warning("Invalid game command for setting sign name, banner id = %d", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + // Ensure user string space. + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (string_id != 0) + { + user_string_free(string_id); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + + return MakeResult(); + } + + GameActionResult::Ptr Execute() const override + { + rct_banner* banner = &gBanners[_bannerIndex]; + + sint32 x = banner->x << 5; + sint32 y = banner->y << 5; + + if (_name.empty() == false) + { + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (string_id != 0) + { + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = string_id; + user_string_free(prev_string_id); + + banner->flags &= ~(BANNER_FLAG_LINKED_TO_RIDE); + gfx_invalidate_screen(); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + } + else + { + // If empty name take closest ride name. + sint32 rideIndex = banner_get_closest_ride_index(x, y, 16); + if (rideIndex == -1) + { + return MakeResult(); + } + + banner->colour = rideIndex; + banner->flags |= BANNER_FLAG_LINKED_TO_RIDE; + + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = STR_DEFAULT_SIGN; + user_string_free(prev_string_id); + + gfx_invalidate_screen(); + } + + return MakeResult(); + } +}; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 2c8307b5ba..833c0d97a7 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -4250,75 +4250,6 @@ void map_clear_all_elements() } } -void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { - static char newName[128]; - - if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) - { - log_warning("Invalid game command for setting sign name, banner id = %d", *ecx); - *ebx = MONEY32_UNDEFINED; - return; - } - rct_banner* banner = &gBanners[*ecx]; - sint32 x = banner->x << 5; - sint32 y = banner->y << 5; - - sint32 nameChunkIndex = *eax & 0xFFFF; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - sint32 nameChunkOffset = nameChunkIndex - 1; - if (nameChunkOffset < 0) - nameChunkOffset = 2; - nameChunkOffset *= 12; - nameChunkOffset = std::min(nameChunkOffset, (sint32)Util::CountOf(newName) - 12); - memcpy(newName + nameChunkOffset + 0, edx, 4); - memcpy(newName + nameChunkOffset + 4, ebp, 4); - memcpy(newName + nameChunkOffset + 8, edi, 4); - - if (nameChunkIndex != 0) { - *ebx = 0; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { - *ebx = 0; - return; - } - - if (newName[0] != 0) { - rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, newName); - if (string_id != 0) { - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = string_id; - user_string_free(prev_string_id); - - banner->flags &= ~(BANNER_FLAG_LINKED_TO_RIDE); - gfx_invalidate_screen(); - } else { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - *ebx = MONEY32_UNDEFINED; - return; - } - } - else{ - sint32 rideIndex = banner_get_closest_ride_index(x, y, 16); - if (rideIndex == -1) { - *ebx = 0; - return; - } - - banner->colour = rideIndex; - banner->flags |= BANNER_FLAG_LINKED_TO_RIDE; - - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = STR_DEFAULT_SIGN; - user_string_free(prev_string_id); - gfx_invalidate_screen(); - } - - *ebx = 0; -} - void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { uint8 bannerId = *ecx & 0xFF; if (bannerId > Util::CountOf(gBanners)) { diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 760e98c8cb..d5406dd2e0 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -498,7 +498,6 @@ void game_command_place_wall(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, void game_command_place_large_scenery(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_place_park_entrance(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); -void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); void game_command_modify_tile(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp); From b45609a27873179bdbd05607ab80ed97a1003697 Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 05:17:23 +0100 Subject: [PATCH 2/5] Implement game action for park naming. --- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/ParkSetNameAction.hpp | 90 +++++++++++++++++++ src/openrct2/world/Park.cpp | 90 +------------------ src/openrct2/world/Park.h | 1 - 6 files changed, 97 insertions(+), 90 deletions(-) create mode 100644 src/openrct2/actions/ParkSetNameAction.hpp diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 5cb7a105da..7cfcbb7404 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1721,7 +1721,7 @@ GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = { game_command_set_staff_patrol, game_command_fire_staff_member, game_command_set_staff_order, - game_command_set_park_name, + nullptr, game_command_set_park_open, game_command_buy_land_rights, game_command_place_park_entrance, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 3c78ef9582..4c3c533df7 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -57,7 +57,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_STAFF_PATROL, GAME_COMMAND_FIRE_STAFF_MEMBER, GAME_COMMAND_SET_STAFF_ORDER, - GAME_COMMAND_SET_PARK_NAME, + GAME_COMMAND_SET_PARK_NAME, // GA GAME_COMMAND_SET_PARK_OPEN, GAME_COMMAND_BUY_LAND_RIGHTS, GAME_COMMAND_PLACE_PARK_ENTRANCE, // GA diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 807331c41c..c10a3cec4e 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -30,6 +30,7 @@ #include "PlacePeepSpawnAction.hpp" #include "MazeSetTrackAction.hpp" #include "SignSetNameAction.hpp" +#include "ParkSetNameAction.hpp" namespace GameActions { @@ -50,5 +51,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/actions/ParkSetNameAction.hpp b/src/openrct2/actions/ParkSetNameAction.hpp new file mode 100644 index 0000000000..704a787c93 --- /dev/null +++ b/src/openrct2/actions/ParkSetNameAction.hpp @@ -0,0 +1,90 @@ +#pragma region Copyright (c) 2014-2018 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 "../Context.h" +#include "../core/MemoryStream.h" +#include "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../world/Sprite.h" +#include "../world/Park.h" +#include "GameAction.h" + +using namespace OpenRCT2; + +struct ParkSetNameAction : public GameActionBase +{ +private: + std::string _name; + +public: + ParkSetNameAction() {} + ParkSetNameAction(const std::string& name) + : _name(name) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + stream << _name; + } + + GameActionResult::Ptr Query() const override + { + if (_name.empty()) + { + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_INVALID_RIDE_ATTRACTION_NAME); + } + + // Ensure user string space. + rct_string_id stringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER, _name.c_str()); + if (stringId != 0) + { + user_string_free(stringId); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_INVALID_NAME_FOR_PARK); + } + + return MakeResult(); + } + + GameActionResult::Ptr Execute() const override + { + rct_string_id stringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER, _name.c_str()); + if (stringId == 0) + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_INVALID_NAME_FOR_PARK); + } + + // Free the old park name. + user_string_free(gParkName); + gParkName = stringId; + + gfx_invalidate_screen(); + + return MakeResult(); + } +}; diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index abfbd9db81..053611bda1 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -41,6 +41,7 @@ #include "Sprite.h" #include "../windows/Intent.h" #include "../Context.h" +#include "../actions/ParkSetNameAction.hpp" rct_string_id gParkName; uint32 gParkNameArgs; @@ -778,93 +779,8 @@ void update_park_fences_around_tile(sint32 x, sint32 y) void park_set_name(const char *name) { - // Required else the pointer arithmetic in the game commands below could cause an access violation - char* newName = (char *)malloc(USER_STRING_MAX_LENGTH + 5); - strncpy(newName, name, USER_STRING_MAX_LENGTH); - - gGameCommandErrorTitle = STR_CANT_RENAME_PARK; - game_do_command(1, GAME_COMMAND_FLAG_APPLY, 0, *((sint32*)(newName + 0)), GAME_COMMAND_SET_PARK_NAME, *((sint32*)(newName + 8)), *((sint32*)(newName + 4))); - game_do_command(2, GAME_COMMAND_FLAG_APPLY, 0, *((sint32*)(newName + 12)), GAME_COMMAND_SET_PARK_NAME, *((sint32*)(newName + 20)), *((sint32*)(newName + 16))); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, *((sint32*)(newName + 24)), GAME_COMMAND_SET_PARK_NAME, *((sint32*)(newName + 32)), *((sint32*)(newName + 28))); - - free(newName); -} - -/** - * - * rct2: 0x00669C6D - */ -void game_command_set_park_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp) -{ - rct_string_id newUserStringId; - char oldName[128]; - static char newName[128]; - - sint32 nameChunkIndex = *eax & 0xFFFF; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - //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 = Math::Min(nameChunkOffset, (sint32)Util::CountOf(newName) - 12); - memcpy(newName + nameChunkOffset + 0, edx, 4); - memcpy(newName + nameChunkOffset + 4, ebp, 4); - memcpy(newName + nameChunkOffset + 8, edi, 4); - //} - - if (nameChunkIndex != 0) { - *ebx = 0; - return; - } - - format_string(oldName, 128, gParkName, &gParkNameArgs); - if (strcmp(oldName, newName) == 0) { - *ebx = 0; - return; - } - - if (newName[0] == 0) { - gGameCommandErrorText = STR_INVALID_RIDE_ATTRACTION_NAME; - *ebx = MONEY32_UNDEFINED; - return; - } - - newUserStringId = user_string_allocate(USER_STRING_HIGH_ID_NUMBER, newName); - if (newUserStringId == 0) { - gGameCommandErrorText = STR_INVALID_NAME_FOR_PARK; - *ebx = MONEY32_UNDEFINED; - return; - } - - if (*ebx & GAME_COMMAND_FLAG_APPLY) { - // Log park 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_PARK_NAME, args); - network_append_server_log(log_msg); - } - - // Free the old ride name - user_string_free(gParkName); - gParkName = newUserStringId; - - gfx_invalidate_screen(); - } else { - user_string_free(newUserStringId); - } - - *ebx = 0; + auto parkSetNameAction = ParkSetNameAction(name); + GameActions::Execute(&parkSetNameAction); } static money32 map_buy_land_rights_for_tile(sint32 x, sint32 y, sint32 setting, sint32 flags) { diff --git a/src/openrct2/world/Park.h b/src/openrct2/world/Park.h index 5b992ecf64..0b46ae3857 100644 --- a/src/openrct2/world/Park.h +++ b/src/openrct2/world/Park.h @@ -110,7 +110,6 @@ sint32 map_buy_land_rights(sint32 x0, sint32 y0, sint32 x1, sint32 y1, sint32 se void game_command_set_park_entrance_fee(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp); void game_command_set_park_open(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp); -void game_command_set_park_name(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp); void game_command_buy_land_rights(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp); money16 park_get_entrance_fee(); From 417a2586b6b71e9dd95e8513970e35ab2215ff3a Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 05:45:08 +0100 Subject: [PATCH 3/5] Implement game action for banner naming. --- src/openrct2-ui/windows/Banner.cpp | 9 +- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- src/openrct2/actions/BannerSetNameAction.hpp | 104 ++++++++++++++++++ .../actions/GameActionRegistration.cpp | 2 + src/openrct2/world/Banner.cpp | 77 ------------- 6 files changed, 113 insertions(+), 83 deletions(-) create mode 100644 src/openrct2/actions/BannerSetNameAction.hpp diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 864dd09ffb..b94e899254 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #define WW 113 #define WH 96 @@ -286,10 +287,10 @@ static void window_banner_dropdown(rct_window *w, rct_widgetindex widgetIndex, s */ static void window_banner_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text) { - if (widgetIndex == WIDX_BANNER_TEXT && text != nullptr) { - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 0)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 8)), *((sint32*)(text + 4))); - game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 12)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 20)), *((sint32*)(text + 16))); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((sint32*)(text + 24)), GAME_COMMAND_SET_BANNER_NAME, *((sint32*)(text + 32)), *((sint32*)(text + 28))); + if (widgetIndex == WIDX_BANNER_TEXT && text != nullptr) + { + auto bannerSetNameAction = BannerSetNameAction(w->number, text); + GameActions::Execute(&bannerSetNameAction); } } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 7cfcbb7404..08325cd684 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1746,7 +1746,7 @@ GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = { game_command_set_banner_colour, game_command_set_land_ownership, game_command_clear_scenery, - game_command_set_banner_name, + nullptr, nullptr, game_command_set_banner_style, game_command_set_sign_style, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 4c3c533df7..90741498b6 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -82,7 +82,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_BANNER_COLOUR, GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_CLEAR_SCENERY, - GAME_COMMAND_SET_BANNER_NAME, + GAME_COMMAND_SET_BANNER_NAME, // GA GAME_COMMAND_SET_SIGN_NAME, // GA GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE, diff --git a/src/openrct2/actions/BannerSetNameAction.hpp b/src/openrct2/actions/BannerSetNameAction.hpp new file mode 100644 index 0000000000..a36660245b --- /dev/null +++ b/src/openrct2/actions/BannerSetNameAction.hpp @@ -0,0 +1,104 @@ +#pragma region Copyright (c) 2014-2018 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 "../Context.h" +#include "../core/MemoryStream.h" +#include "../core/String.hpp" +#include "../drawing/Drawing.h" +#include "../localisation/StringIds.h" +#include "../ui/UiContext.h" +#include "../world/Sprite.h" +#include "../world/Banner.h" +#include "../windows/Intent.h" +#include "GameAction.h" + +using namespace OpenRCT2; + +struct BannerSetNameAction : public GameActionBase +{ +private: + sint32 _bannerIndex; + std::string _name; + +public: + BannerSetNameAction() {} + BannerSetNameAction(sint32 bannerIndex, const std::string& name) + : _bannerIndex(bannerIndex), + _name(name) + { + } + + uint16 GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser& stream) override + { + GameAction::Serialise(stream); + stream << _bannerIndex << _name; + } + + GameActionResult::Ptr Query() const override + { + if (_bannerIndex >= MAX_BANNERS || _bannerIndex < 0) + { + log_warning("Invalid game command for setting banner name, banner id = %d", _bannerIndex); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + } + + // Ensure user string space. + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str()); + if (string_id != 0) + { + user_string_free(string_id); + } + else + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + + return MakeResult(); + } + + GameActionResult::Ptr Execute() const override + { + rct_banner* banner = &gBanners[_bannerIndex]; + + utf8 *buffer = gCommonStringFormatBuffer; + utf8 *dst = buffer; + dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); + String::Set(dst, sizeof(gCommonStringFormatBuffer) - (dst - buffer), _name.c_str(), _name.size()); + + rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); + if (string_id == 0) + { + return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT); + } + + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = string_id; + user_string_free(prev_string_id); + + auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); + intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex); + context_broadcast_intent(&intent); + + return MakeResult(); + } +}; diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index c10a3cec4e..d037884b37 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -31,6 +31,7 @@ #include "MazeSetTrackAction.hpp" #include "SignSetNameAction.hpp" #include "ParkSetNameAction.hpp" +#include "BannerSetNameAction.hpp" namespace GameActions { @@ -52,5 +53,6 @@ namespace GameActions Register(); Register(); Register(); + Register(); } } diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 47aa9f0641..52bbd57b30 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -285,71 +285,6 @@ static money32 BannerPlace(sint16 x, sint16 y, uint8 pathBaseHeight, uint8 direc return bannerEntry->banner.price; } -static money32 BannerSetName(uint8 bannerIndex, - uint16 nameChunkIndex, - uint32 nameChunk1, - uint32 nameChunk2, - uint32 nameChunk3, - uint8 flags) -{ - static char newName[128]; - - if (bannerIndex >= MAX_BANNERS) - { - log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex); - return MONEY32_UNDEFINED; - } - rct_banner* banner = &gBanners[bannerIndex]; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - size_t indexToOffset[3] = { 24, 0, 12 }; - - if (nameChunkIndex > Util::CountOf(indexToOffset)) - { - log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex); - return MONEY32_UNDEFINED; - } - - size_t nameChunkOffset = std::min(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12); - std::memcpy(&newName[0 + nameChunkOffset], &nameChunk1, sizeof(uint32)); - std::memcpy(&newName[4 + nameChunkOffset], &nameChunk2, sizeof(uint32)); - std::memcpy(&newName[8 + nameChunkOffset], &nameChunk3, sizeof(uint32)); - - if (nameChunkIndex != 0) - { - return 0; - } - - if (!(flags & GAME_COMMAND_FLAG_APPLY)) - { - return 0; - } - - utf8 *buffer = gCommonStringFormatBuffer; - utf8 *dst = buffer; - dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); - String::Set(dst, 256, newName, 32); - - rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); - if (stringId != 0) - { - rct_string_id prevStringId = banner->string_idx; - banner->string_idx = stringId; - user_string_free(prevStringId); - - auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); - intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex); - context_broadcast_intent(&intent); - } - else - { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - return MONEY32_UNDEFINED; - } - - return 0; -} - static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags) { if (bannerIndex >= MAX_BANNERS) @@ -662,18 +597,6 @@ void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* ed ); } -void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) -{ - *ebx = BannerSetName( - *ecx & 0xFF, - *eax & 0xFFFF, - *edx, - *ebp, - *edi, - *ebx & 0xFF - ); -} - void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { *ebx = BannerSetStyle( From adbe35b11cd93c253c4de5a213d4d31828d6d0d3 Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Sat, 24 Mar 2018 05:50:59 +0100 Subject: [PATCH 4/5] Increment network version. --- src/openrct2/network/Network.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index a68cdee52e..8b977b7612 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 "1" +#define NETWORK_STREAM_VERSION "2" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static rct_peep* _pickup_peep = nullptr; @@ -2093,7 +2093,7 @@ bool Network::LoadMap(IStream * stream) gCheatsDisableRideValueAging = stream->ReadValue() != 0; gConfigGeneral.show_real_names_of_guests = stream->ReadValue() != 0; gCheatsIgnoreResearchStatus = stream->ReadValue() != 0; - + gLastAutoSaveUpdate = AUTOSAVE_PAUSE; result = true; } @@ -2206,7 +2206,7 @@ void Network::Client_Handle_GAME_ACTION(NetworkConnection& connection, NetworkPa if (player_id == action->GetPlayer()) { - // Only execute callbacks that belong to us, + // Only execute callbacks that belong to us, // clients can have identical network ids assigned. auto itr = _gameActionCallbacks.find(action->GetNetworkId()); if (itr != _gameActionCallbacks.end()) From bcbe6ecbff21959216e2954bb1157bef757ecd95 Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Tue, 27 Mar 2018 02:37:47 +0200 Subject: [PATCH 5/5] Remove unnecessary include --- src/openrct2/actions/BannerSetNameAction.hpp | 1 - src/openrct2/actions/ParkSetNameAction.hpp | 1 - src/openrct2/actions/SignSetNameAction.hpp | 1 - 3 files changed, 3 deletions(-) diff --git a/src/openrct2/actions/BannerSetNameAction.hpp b/src/openrct2/actions/BannerSetNameAction.hpp index a36660245b..9a54ac9d80 100644 --- a/src/openrct2/actions/BannerSetNameAction.hpp +++ b/src/openrct2/actions/BannerSetNameAction.hpp @@ -17,7 +17,6 @@ #pragma once #include "../Context.h" -#include "../core/MemoryStream.h" #include "../core/String.hpp" #include "../drawing/Drawing.h" #include "../localisation/StringIds.h" diff --git a/src/openrct2/actions/ParkSetNameAction.hpp b/src/openrct2/actions/ParkSetNameAction.hpp index 704a787c93..dc876a4933 100644 --- a/src/openrct2/actions/ParkSetNameAction.hpp +++ b/src/openrct2/actions/ParkSetNameAction.hpp @@ -17,7 +17,6 @@ #pragma once #include "../Context.h" -#include "../core/MemoryStream.h" #include "../drawing/Drawing.h" #include "../localisation/StringIds.h" #include "../ui/UiContext.h" diff --git a/src/openrct2/actions/SignSetNameAction.hpp b/src/openrct2/actions/SignSetNameAction.hpp index 83c2e12564..f911cd85b8 100644 --- a/src/openrct2/actions/SignSetNameAction.hpp +++ b/src/openrct2/actions/SignSetNameAction.hpp @@ -17,7 +17,6 @@ #pragma once #include "../Context.h" -#include "../core/MemoryStream.h" #include "../drawing/Drawing.h" #include "../localisation/StringIds.h" #include "../ui/UiContext.h"