Codechange: Use lambdas instead of CommandContainer to manage station picker commands.

This commit is contained in:
Michael Lutz 2021-10-29 00:56:07 +02:00
parent a05fd7aa50
commit 996b16de70
9 changed files with 110 additions and 84 deletions

View File

@ -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. */

View File

@ -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)

View File

@ -37,13 +37,11 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID);
typedef std::vector<byte> 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);

View File

@ -460,17 +460,4 @@ template <Commands Tcmd> 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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;

View File

@ -2264,13 +2264,13 @@ static const NWidgetPart _nested_select_station_widgets[] = {
*/
template <class T>
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 <class T>
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 <class T>
void ShowSelectBaseStationIfNeeded(const CommandContainer &cmd, TileArea ta)
void ShowSelectBaseStationIfNeeded(TileArea ta, StationPickerCmdProc&& proc)
{
if (StationJoinerNeeded<T>(cmd, ta)) {
if (StationJoinerNeeded<T>(ta, proc)) {
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
new SelectStationWindow<T>(&_select_station_desc, cmd, ta);
new SelectStationWindow<T>(&_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<Station>(cmd, ta);
ShowSelectBaseStationIfNeeded<Station>(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<Waypoint>(cmd, ta);
ShowSelectBaseStationIfNeeded<Waypoint>(ta, std::move(proc));
}

View File

@ -13,6 +13,8 @@
#include "command_type.h"
#include "tilearea_type.h"
#include "window_type.h"
#include "station_type.h"
#include <functional>
/** 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<bool(bool test, StationID to_join)>;
void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc);
void ShowSelectWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc);
#endif /* STATION_GUI_H */