From 996b16de707c449a83676c614edbd5a81d37b253 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 29 Oct 2021 00:56:07 +0200 Subject: [PATCH] Codechange: Use lambdas instead of CommandContainer to manage station picker commands. --- src/airport_gui.cpp | 17 +++++++++++++++-- src/command.cpp | 26 -------------------------- src/command_func.h | 2 -- src/command_type.h | 13 ------------- src/dock_gui.cpp | 22 ++++++++++++++++------ src/rail_gui.cpp | 44 ++++++++++++++++++++++++++++++++++++++------ src/road_gui.cpp | 26 +++++++++++++++++++------- src/station_gui.cpp | 36 ++++++++++++++++-------------------- src/station_gui.h | 8 ++++++-- 9 files changed, 110 insertions(+), 84 deletions(-) diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 41fde9b8ce..65c59784b5 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -26,7 +26,9 @@ #include "hotkeys.h" #include "vehicle_func.h" #include "gui.h" +#include "command_func.h" #include "airport_cmd.h" +#include "station_cmd.h" #include "widgets/airport_widget.h" @@ -61,8 +63,19 @@ static void PlaceAirport(TileIndex tile) uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex(); p1 |= _selected_airport_layout << 8; - CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT, STR_ERROR_CAN_T_BUILD_AIRPORT_HERE, CcBuildAirport, "" }; - ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE)); + + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_AIRPORT)), CMD_BUILD_AIRPORT, tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_AIRPORT, STR_ERROR_CAN_T_BUILD_AIRPORT_HERE, CcBuildAirport, tile, p1, p2_final); + } + }; + + ShowSelectStationIfNeeded(TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE), proc); } /** Airport build toolbar window handler. */ diff --git a/src/command.cpp b/src/command.cpp index 788c71989c..e9ae695285 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -163,20 +163,6 @@ bool IsCommandAllowedWhilePaused(Commands cmd) static int _docommand_recursive = 0; - -/** - * Shorthand for calling the long DoCommand with a container. - * - * @param container Container with (almost) all information - * @param flags Flags for the command and how to execute the command - * @see CommandProc - * @return the cost - */ -CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags) -{ - return DoCommand(flags, container->cmd, container->tile, container->p1, container->p2, container->text); -} - /*! * This function executes a given command with the parameters from the #CommandProc parameter list. * Depending on the flags parameter it execute or test a command. @@ -326,18 +312,6 @@ static bool DoCommandP(Commands cmd, StringID err_message, CommandCallback *call return res.Succeeded(); } -/** - * Shortcut for the long DoCommandP when having a container with the data. - * @param container the container with information. - * @param my_cmd indicator if the command is from a company or server (to display error messages for a user) - * @param network_command execute the command without sending it on the network - * @return true if the command succeeded, else false - */ -bool DoCommandP(const CommandContainer *container, bool my_cmd, bool network_command) -{ - return DoCommandP(container->cmd, container->err_msg, container->callback, my_cmd, network_command, container->tile, container->p1, container->p2, container->text); -} - /** * Shortcut for the long DoCommandP when not using a callback or error message. * @param cmd The command to execute (a CMD_* value) diff --git a/src/command_func.h b/src/command_func.h index 0d000755c8..0b539746d9 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -37,13 +37,11 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID); typedef std::vector CommandDataBuffer; CommandCost DoCommand(DoCommandFlag flags, Commands cmd, TileIndex tile, uint32 p1, uint32 p2, const std::string &text = {}); -CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags); bool DoCommandP(Commands cmd, StringID err_message, CommandCallback *callback, TileIndex tile, uint32 p1, uint32 p2, const std::string &text = {}); bool DoCommandP(Commands cmd, StringID err_message, TileIndex tile, uint32 p1, uint32 p2, const std::string &text = {}); bool DoCommandP(Commands cmd, CommandCallback *callback, TileIndex tile, uint32 p1, uint32 p2, const std::string &text = {}); bool DoCommandP(Commands cmd, TileIndex tile, uint32 p1, uint32 p2, const std::string &text = {}); -bool DoCommandP(const CommandContainer *container, bool my_cmd = true, bool network_command = false); bool InjectNetworkCommand(Commands cmd, StringID err_message, CommandCallback *callback, bool my_cmd, TileIndex tile, uint32 p1, uint32 p2, const std::string &text); diff --git a/src/command_type.h b/src/command_type.h index 3a15087b9a..cc5e97795e 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -460,17 +460,4 @@ template struct CommandTraits; */ typedef void CommandCallback(const CommandCost &result, Commands cmd, TileIndex tile, uint32 p1, uint32 p2, const std::string &text); -/** - * Structure for buffering the build command when selecting a station to join. - */ -struct CommandContainer { - TileIndex tile; ///< tile command being executed on. - uint32 p1; ///< parameter p1. - uint32 p2; ///< parameter p2. - Commands cmd; ///< command being executed. - StringID err_msg; ///< string ID of error message to use. - CommandCallback *callback; ///< any callback function executed upon successful completion of the command. - std::string text; ///< possible text sent for name changes etc. -}; - #endif /* COMMAND_TYPE_H */ diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 52b1483815..da7e0518f4 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -27,6 +27,7 @@ #include "zoom_func.h" #include "tunnelbridge_cmd.h" #include "dock_cmd.h" +#include "station_cmd.h" #include "widgets/dock_widget.h" @@ -205,16 +206,25 @@ struct BuildDocksToolbarWindow : Window { break; case WID_DT_STATION: { // Build station button - uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join - - /* tile is always the land tile, so need to evaluate _thd.pos */ - CommandContainer cmdcont = { tile, _ctrl_pressed, p2, CMD_BUILD_DOCK, STR_ERROR_CAN_T_BUILD_DOCK_HERE, CcBuildDocks, "" }; - /* Determine the watery part of the dock. */ DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile); - ShowSelectStationIfNeeded(cmdcont, TileArea(tile, tile_to)); + uint32 p1 = _ctrl_pressed; + uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join + + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_DOCK)), CMD_BUILD_DOCK, tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_DOCK, STR_ERROR_CAN_T_BUILD_DOCK_HERE, CcBuildDocks, tile, p1, p2_final); + } + }; + + ShowSelectStationIfNeeded(TileArea(tile, tile_to), proc); break; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 7cf1b0059f..76d51ccb2c 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -36,6 +36,8 @@ #include "sortlist_type.h" #include "stringfilter_type.h" #include "string_func.h" +#include "station_cmd.h" +#include "waypoint_cmd.h" #include "station_map.h" #include "tunnelbridge_map.h" @@ -198,8 +200,18 @@ static void PlaceRail_Station(TileIndex tile) int h = _settings_client.gui.station_platlength; if (!_railstation.orientation) Swap(w, h); - CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_RAIL_STATION, STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, "" }; - ShowSelectStationIfNeeded(cmdcont, TileArea(tile, w, h)); + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_RAIL_STATION)), CMD_BUILD_RAIL_STATION, tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_RAIL_STATION, STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, tile, p1, p2_final); + } + }; + + ShowSelectStationIfNeeded(TileArea(tile, w, h), proc); } } @@ -724,8 +736,18 @@ struct BuildRailToolbarWindow : Window { uint32 p1 = _cur_railtype | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 6 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24; uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16; - CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT, STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT, CcPlaySound_CONSTRUCTION_RAIL, "" }; - ShowSelectWaypointIfNeeded(cmdcont, ta); + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_RAIL_WAYPOINT)), CMD_BUILD_RAIL_WAYPOINT, ta.tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_RAIL_WAYPOINT, STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT, CcPlaySound_CONSTRUCTION_RAIL, ta.tile, p1, p2_final); + } + }; + + ShowSelectWaypointIfNeeded(ta, proc); } } break; @@ -883,8 +905,18 @@ static void HandleStationPlacement(TileIndex start, TileIndex end) uint32 p1 = _cur_railtype | _railstation.orientation << 6 | numtracks << 8 | platlength << 16 | _ctrl_pressed << 24; uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16; - CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_STATION, STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, "" }; - ShowSelectStationIfNeeded(cmdcont, ta); + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_RAIL_STATION)), CMD_BUILD_RAIL_STATION, ta.tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_RAIL_STATION, STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, ta.tile, p1, p2_final); + } + }; + + ShowSelectStationIfNeeded(ta, proc); } /** Enum referring to the Hotkeys in the build rail station window */ diff --git a/src/road_gui.cpp b/src/road_gui.cpp index eedcc8f59c..00ea29042d 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -31,6 +31,7 @@ #include "strings_func.h" #include "core/geometry_func.hpp" #include "date_func.h" +#include "station_cmd.h" #include "widgets/road_widget.h" @@ -179,12 +180,14 @@ void CcRoadStop(const CommandCost &result, Commands cmd, TileIndex tile, uint32 * @param p2 bit 0: 0 For bus stops, 1 for truck stops. * bit 2: Allow stations directly adjacent to other stations. * bit 5..10: The roadtypes. - * @param cmd Command to use. * @param err_msg Error message to show. * @see CcRoadStop() */ -static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, Commands cmd, StringID err_msg) +static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, StringID err_msg) { + TileArea ta(start_tile, end_tile); + uint32 p1 = (uint32)(ta.w | ta.h << 8); + uint8 ddir = _road_station_picker_orientation; SB(p2, 16, 16, INVALID_STATION); // no station to join @@ -194,9 +197,18 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, C } p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4. - TileArea ta(start_tile, end_tile); - CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, err_msg, CcRoadStop, "" }; - ShowSelectStationIfNeeded(cmdcont, ta); + auto proc = [=](bool test, StationID to_join) -> bool { + if (test) { + return DoCommand(CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_ROAD_STOP)), CMD_BUILD_ROAD_STOP, ta.tile, p1, p2).Succeeded(); + } else { + uint32 p2_final = p2; + if (to_join != INVALID_STATION) SB(p2_final, 16, 16, to_join); + + return DoCommandP(CMD_BUILD_ROAD_STOP, err_msg, CcRoadStop, ta.tile, p1, p2_final); + } + }; + + ShowSelectStationIfNeeded(ta, proc); } /** @@ -684,7 +696,7 @@ struct BuildRoadToolbarWindow : Window { TileArea ta(start_tile, end_tile); DoCommandP(CMD_REMOVE_ROAD_STOP, this->rti->strings.err_remove_station[ROADSTOP_BUS], CcPlaySound_CONSTRUCTION_OTHER, ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS); } else { - PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP, this->rti->strings.err_build_station[ROADSTOP_BUS]); + PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_BUS, this->rti->strings.err_build_station[ROADSTOP_BUS]); } } break; @@ -696,7 +708,7 @@ struct BuildRoadToolbarWindow : Window { TileArea ta(start_tile, end_tile); DoCommandP(CMD_REMOVE_ROAD_STOP, this->rti->strings.err_remove_station[ROADSTOP_TRUCK], CcPlaySound_CONSTRUCTION_OTHER, ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK); } else { - PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP, this->rti->strings.err_build_station[ROADSTOP_TRUCK]); + PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_TRUCK, this->rti->strings.err_build_station[ROADSTOP_TRUCK]); } } break; diff --git a/src/station_gui.cpp b/src/station_gui.cpp index e1229fe3d1..2e04e7ac44 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -2264,13 +2264,13 @@ static const NWidgetPart _nested_select_station_widgets[] = { */ template struct SelectStationWindow : Window { - CommandContainer select_station_cmd; ///< Command to build new station + StationPickerCmdProc select_station_proc; TileArea area; ///< Location of new station Scrollbar *vscroll; - SelectStationWindow(WindowDesc *desc, const CommandContainer &cmd, TileArea ta) : + SelectStationWindow(WindowDesc *desc, TileArea ta, StationPickerCmdProc&& proc) : Window(desc), - select_station_cmd(cmd), + select_station_proc(std::move(proc)), area(ta) { this->CreateNestedTree(); @@ -2341,12 +2341,8 @@ struct SelectStationWindow : Window { if (distant_join && st_index >= _stations_nearby_list.size()) return; - /* Insert station to be joined into stored command */ - SB(this->select_station_cmd.p2, 16, 16, - (distant_join ? _stations_nearby_list[st_index] : NEW_STATION)); - /* Execute stored Command */ - DoCommandP(&this->select_station_cmd); + this->select_station_proc(false, distant_join ? _stations_nearby_list[st_index] : NEW_STATION); /* Close Window; this might cause double frees! */ CloseWindowById(WC_SELECT_STATION, 0); @@ -2412,7 +2408,7 @@ static WindowDesc _select_station_desc( * @return whether we need to show the station selection window. */ template -static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta) +static bool StationJoinerNeeded(TileArea ta, const StationPickerCmdProc &proc) { /* Only show selection if distant join is enabled in the settings */ if (!_settings_game.station.distant_join_stations) return false; @@ -2430,7 +2426,7 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta) if (!_ctrl_pressed) return false; /* Now check if we could build there */ - if (DoCommand(&cmd, CommandFlagsToDCFlags(GetCommandFlags(cmd.cmd))).Failed()) return false; + if (!proc(true, INVALID_STATION)) return false; /* Test for adjacent station or station below selection. * If adjacent-stations is disabled and we are building next to a station, do not show the selection window. @@ -2446,32 +2442,32 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta) * @tparam the class to find stations for */ template -void ShowSelectBaseStationIfNeeded(const CommandContainer &cmd, TileArea ta) +void ShowSelectBaseStationIfNeeded(TileArea ta, StationPickerCmdProc&& proc) { - if (StationJoinerNeeded(cmd, ta)) { + if (StationJoinerNeeded(ta, proc)) { if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); - new SelectStationWindow(&_select_station_desc, cmd, ta); + new SelectStationWindow(&_select_station_desc, ta, std::move(proc)); } else { - DoCommandP(&cmd); + proc(false, INVALID_STATION); } } /** * Show the station selection window when needed. If not, build the station. - * @param cmd Command to build the station. * @param ta Area to build the station in + * @param proc Function called to execute the build command. */ -void ShowSelectStationIfNeeded(const CommandContainer &cmd, TileArea ta) +void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc) { - ShowSelectBaseStationIfNeeded(cmd, ta); + ShowSelectBaseStationIfNeeded(ta, std::move(proc)); } /** * Show the waypoint selection window when needed. If not, build the waypoint. - * @param cmd Command to build the waypoint. * @param ta Area to build the waypoint in + * @param proc Function called to execute the build command. */ -void ShowSelectWaypointIfNeeded(const CommandContainer &cmd, TileArea ta) +void ShowSelectWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc) { - ShowSelectBaseStationIfNeeded(cmd, ta); + ShowSelectBaseStationIfNeeded(ta, std::move(proc)); } diff --git a/src/station_gui.h b/src/station_gui.h index ac2fa2fc32..9bed30b672 100644 --- a/src/station_gui.h +++ b/src/station_gui.h @@ -13,6 +13,8 @@ #include "command_type.h" #include "tilearea_type.h" #include "window_type.h" +#include "station_type.h" +#include /** Types of cargo to display for station coverage. */ @@ -25,7 +27,9 @@ enum StationCoverageType { int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageType sct, int rad, bool supplies); void CheckRedrawStationCoverage(const Window *w); -void ShowSelectStationIfNeeded(const CommandContainer &cmd, TileArea ta); -void ShowSelectWaypointIfNeeded(const CommandContainer &cmd, TileArea ta); +using StationPickerCmdProc = std::function; + +void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc); +void ShowSelectWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc); #endif /* STATION_GUI_H */