OpenTTD Source  20241108-master-g80f628063a
command.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD 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, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "landscape.h"
12 #include "error.h"
13 #include "gui.h"
14 #include "command_func.h"
15 #include "network/network_type.h"
16 #include "network/network.h"
17 #include "genworld.h"
18 #include "strings_func.h"
19 #include "texteff.hpp"
20 #include "town.h"
22 #include "company_func.h"
23 #include "company_base.h"
24 #include "signal_func.h"
25 #include "core/backup_type.hpp"
26 #include "object_base.h"
27 #include "autoreplace_cmd.h"
28 #include "company_cmd.h"
29 #include "depot_cmd.h"
30 #include "economy_cmd.h"
31 #include "engine_cmd.h"
32 #include "goal_cmd.h"
33 #include "group_cmd.h"
34 #include "industry_cmd.h"
35 #include "league_cmd.h"
36 #include "landscape_cmd.h"
37 #include "misc_cmd.h"
38 #include "news_cmd.h"
39 #include "object_cmd.h"
40 #include "order_cmd.h"
41 #include "rail_cmd.h"
42 #include "road_cmd.h"
43 #include "roadveh_cmd.h"
44 #include "settings_cmd.h"
45 #include "signs_cmd.h"
46 #include "station_cmd.h"
47 #include "story_cmd.h"
48 #include "subsidy_cmd.h"
49 #include "terraform_cmd.h"
50 #include "timetable_cmd.h"
51 #include "town_cmd.h"
52 #include "train_cmd.h"
53 #include "tree_cmd.h"
54 #include "tunnelbridge_cmd.h"
55 #include "vehicle_cmd.h"
56 #include "viewport_cmd.h"
57 #include "water_cmd.h"
58 #include "waypoint_cmd.h"
59 #include "misc/endian_buffer.hpp"
60 #include "string_func.h"
61 
62 #include "table/strings.h"
63 
64 #include "safeguards.h"
65 
66 
67 int RecursiveCommandCounter::_counter = 0;
68 
69 
76 struct CommandInfo {
77  const char *name;
80 };
81 /* Helpers to generate the master command table from the command traits. */
82 template <typename T>
83 inline constexpr CommandInfo CommandFromTrait() noexcept { return { T::name, T::flags, T::type }; };
84 
85 template<typename T, T... i>
86 inline constexpr auto MakeCommandsFromTraits(std::integer_sequence<T, i...>) noexcept {
87  return std::array<CommandInfo, sizeof...(i)>{{ CommandFromTrait<CommandTraits<static_cast<Commands>(i)>>()... }};
88 }
89 
97 static constexpr auto _command_proc_table = MakeCommandsFromTraits(std::make_integer_sequence<std::underlying_type_t<Commands>, CMD_END>{});
98 
99 
107 {
108  return cmd < _command_proc_table.size();
109 }
110 
119 {
120  assert(IsValidCommand(cmd));
121 
122  return _command_proc_table[cmd].flags;
123 }
124 
132 const char *GetCommandName(Commands cmd)
133 {
134  assert(IsValidCommand(cmd));
135 
136  return _command_proc_table[cmd].name;
137 }
138 
145 {
146  /* Lookup table for the command types that are allowed for a given pause level setting. */
147  static const int command_type_lookup[] = {
157  };
158  static_assert(lengthof(command_type_lookup) == CMDT_END);
159 
160  assert(IsValidCommand(cmd));
161  return _game_mode == GM_EDITOR || command_type_lookup[_command_proc_table[cmd].type] <= _settings_game.construction.command_pause_level;
162 }
163 
169 void CommandHelperBase::InternalDoBefore(bool top_level, bool test)
170 {
171  if (top_level) _cleared_object_areas.clear();
172  if (test) SetTownRatingTestMode(true);
173 }
174 
182 void CommandHelperBase::InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test)
183 {
184  if (test) {
185  SetTownRatingTestMode(false);
186 
187  if (res.Succeeded() && top_level && !(flags & DC_QUERY_COST) && !(flags & DC_BANKRUPT)) {
188  CheckCompanyHasMoney(res); // CheckCompanyHasMoney() modifies 'res' to an error if it fails.
189  }
190  } else {
191  /* If top-level, subtract the money. */
192  if (res.Succeeded() && top_level && !(flags & DC_BANKRUPT)) {
194  }
195  }
196 }
197 
207 std::tuple<bool, bool, bool> CommandHelperBase::InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command)
208 {
209  /* Cost estimation is generally only done when the
210  * local user presses shift while doing something.
211  * However, in case of incoming network commands,
212  * map generation or the pause button we do want
213  * to execute. */
214  bool estimate_only = _shift_pressed && IsLocalCompany() && !_generating_world && !network_command && !(flags & CMD_NO_EST);
215 
216  /* We're only sending the command, so don't do
217  * fancy things for 'success'. */
218  bool only_sending = _networking && !network_command;
219 
220  if (_pause_mode != PM_UNPAUSED && !IsCommandAllowedWhilePaused(cmd) && !estimate_only) {
221  ShowErrorMessage(err_message, STR_ERROR_NOT_ALLOWED_WHILE_PAUSED, WL_INFO, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
222  return { true, estimate_only, only_sending };
223  } else {
224  return { false, estimate_only, only_sending };
225  }
226 }
227 
237 void CommandHelperBase::InternalPostResult(const CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd)
238 {
239  int x = TileX(tile) * TILE_SIZE;
240  int y = TileY(tile) * TILE_SIZE;
241 
242  if (res.Failed()) {
243  /* Only show the error when it's for us. */
244  if (estimate_only || (IsLocalCompany() && err_message != 0 && my_cmd)) {
245  ShowErrorMessage(err_message, x, y, res);
246  }
247  } else if (estimate_only) {
248  ShowEstimatedCostOrIncome(res.GetCost(), x, y);
249  } else if (!only_sending && tile != 0 && IsLocalCompany() && _game_mode != GM_EDITOR) {
250  /* Only show the cost animation when we did actually
251  * execute the command, i.e. we're not sending it to
252  * the server, when it has cost the local company
253  * something. Furthermore in the editor there is no
254  * concept of cost, so don't show it there either. */
256  }
257 }
258 
260 void CommandHelperBase::LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
261 {
262  Debug(desync, 1, "{}: {:08x}; {:02x}; {:02x}; {:08x}; {:08x}; {} ({})", failed ? "cmdf" : "cmd", (uint32_t)TimerGameEconomy::date.base(), TimerGameEconomy::date_fract, (int)_current_company, cmd, err_message, FormatArrayAsHex(args), GetCommandName(cmd));
263 }
264 
272 {
273  /* Always execute server and spectator commands as spectator */
274  bool exec_as_spectator = (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) != 0;
275 
276  /* If the company isn't valid it may only do server command or start a new company!
277  * The server will ditch any server commands a client sends to it, so effectively
278  * this guards the server from executing functions for an invalid company. */
279  if (_game_mode == GM_NORMAL && !exec_as_spectator && !Company::IsValidID(_current_company) && !(_current_company == OWNER_DEITY && (cmd_flags & CMD_DEITY) != 0)) {
280  return false;
281  }
282 
283  if (exec_as_spectator) cur_company.Change(COMPANY_SPECTATOR);
284 
285  /* Enter test mode. */
286  _cleared_object_areas.clear();
287  SetTownRatingTestMode(true);
289  return true;
290 }
291 
301 std::tuple<bool, bool, bool> CommandHelperBase::InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, [[maybe_unused]] Backup<CompanyID> &cur_company)
302 {
304  SetTownRatingTestMode(false);
305 
306  /* Make sure we're not messing things up here. */
307  assert((cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) != 0 ? _current_company == COMPANY_SPECTATOR : cur_company.Verify());
308 
309  /* If the command fails, we're doing an estimate
310  * or the player does not have enough money
311  * (unless it's a command where the test and
312  * execution phase might return different costs)
313  * we bail out here. */
314  bool test_and_exec_can_differ = (cmd_flags & CMD_NO_TEST) != 0;
315  if (res.Failed() || estimate_only || (!test_and_exec_can_differ && !CheckCompanyHasMoney(res))) {
316  return { true, !_networking || _generating_world || network_command, false };
317  }
318 
319  bool send_net = _networking && !_generating_world && !network_command;
320 
321  if (!send_net) {
322  /* Prepare for command execution. */
323  _cleared_object_areas.clear();
325  }
326 
327  return { false, _debug_desync_level >= 1, send_net };
328 }
329 
341 CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, [[maybe_unused]] const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup<CompanyID> &cur_company)
342 {
344 
345  if (cmd == CMD_COMPANY_CTRL) {
346  cur_company.Trash();
347  /* We are a new company -> Switch to new local company.
348  * We were closed down -> Switch to spectator
349  * Some other company opened/closed down -> The outside function will switch back */
351  } else {
352  /* Make sure nothing bad happened, like changing the current company. */
353  assert((cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) != 0 ? _current_company == COMPANY_SPECTATOR : cur_company.Verify());
354  cur_company.Restore();
355  }
356 
357  /* If the test and execution can differ we have to check the
358  * return of the command. Otherwise we can check whether the
359  * test and execution have yielded the same result,
360  * i.e. cost and error state are the same. */
361  bool test_and_exec_can_differ = (cmd_flags & CMD_NO_TEST) != 0;
362  if (!test_and_exec_can_differ) {
363  assert(res_test.GetCost() == res_exec.GetCost() && res_test.Failed() == res_exec.Failed()); // sanity check
364  } else if (res_exec.Failed()) {
365  return res_exec;
366  }
367 
368  /* If we're needing more money and we haven't done
369  * anything yet, ask for the money! */
370  if (extra_cash != 0 && res_exec.GetCost() == 0) {
371  /* It could happen we removed rail, thus gained money, and deleted something else.
372  * So make sure the signal buffer is empty even in this case */
374  SetDParam(0, extra_cash);
375  return CommandCost(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
376  }
377 
378  /* update last build coordinate of company. */
379  if (tile != 0) {
381  if (c != nullptr) c->last_build_coordinate = tile;
382  }
383 
384  SubtractMoneyFromCompany(res_exec);
385 
386  /* Record if there was a command issues during pause; ignore pause/other setting related changes. */
388 
389  /* update signals if needed */
391 
392  return res_exec;
393 }
394 
395 
402 {
403  this->AddCost(ret.cost);
404  if (this->success && !ret.success) {
405  this->message = ret.message;
406  this->success = false;
407  }
408 }
409 
415 uint32_t CommandCost::textref_stack[16];
416 
422 void CommandCost::UseTextRefStack(const GRFFile *grffile, uint num_registers)
423 {
424  extern TemporaryStorageArray<int32_t, 0x110> _temp_store;
425 
426  assert(num_registers < lengthof(textref_stack));
427  this->textref_stack_grffile = grffile;
428  this->textref_stack_size = num_registers;
429  for (uint i = 0; i < num_registers; i++) {
430  textref_stack[i] = _temp_store.GetValue(0x100 + i);
431  }
432 }
Command definitions related to autoreplace.
Class for backupping variables and making sure they are restored later.
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:63
Money cost
The cost of this action.
Definition: command_type.h:25
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
uint textref_stack_size
Number of uint32_t values to put on the TextRefStack for the error message.
Definition: command_type.h:29
void UseTextRefStack(const GRFFile *grffile, uint num_registers)
Activate usage of the NewGRF TextRefStack for the error message.
Definition: command.cpp:422
static uint32_t textref_stack[16]
Values to put on the TextRefStack for the error message.
Definition: command_type.h:32
StringID message
Warning message for when success is unset.
Definition: command_type.h:26
bool Failed() const
Did this command fail?
Definition: command_type.h:171
const GRFFile * textref_stack_grffile
NewGRF providing the TextRefStack content.
Definition: command_type.h:28
bool success
Whether the command went fine up to this moment.
Definition: command_type.h:27
static std::tuple< bool, bool, bool > InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command)
Decide what to do with the command depending on current game state.
Definition: command.cpp:207
static void InternalDoBefore(bool top_level, bool test)
Prepare for calling a command proc.
Definition: command.cpp:169
static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
Helper to make a desync log for a command.
Definition: command.cpp:260
static CommandCost InternalExecuteProcessResult(Commands cmd, CommandFlags cmd_flags, const CommandCost &res_test, const CommandCost &res_exec, Money extra_cash, TileIndex tile, Backup< CompanyID > &cur_company)
Process the result of a command test run and execution run.
Definition: command.cpp:341
static void InternalPostResult(const CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd)
Process result of executing a command, possibly displaying any error to the player.
Definition: command.cpp:237
static std::tuple< bool, bool, bool > InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup< CompanyID > &cur_company)
Validate result of test run and prepare for real execution.
Definition: command.cpp:301
static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup< CompanyID > &cur_company)
Prepare for the test run of a command proc call.
Definition: command.cpp:271
static void InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test)
Process result after calling a command proc.
Definition: command.cpp:182
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
CommandFlags GetCommandFlags(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the flags which belongs to the given co...
Definition: command.cpp:118
bool IsCommandAllowedWhilePaused(Commands cmd)
Returns whether the command is allowed while the game is paused.
Definition: command.cpp:144
const char * GetCommandName(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the name which belongs to the given com...
Definition: command.cpp:132
bool IsValidCommand(Commands cmd)
This function range-checks a cmd.
Definition: command.cpp:106
static constexpr auto _command_proc_table
The master command table.
Definition: command.cpp:97
Functions related to commands.
@ CMDPL_NO_LANDSCAPING
No landscaping actions may be executed.
Definition: command_type.h:431
@ CMDPL_ALL_ACTIONS
All actions may be executed.
Definition: command_type.h:432
@ CMDPL_NO_ACTIONS
No user actions may be executed.
Definition: command_type.h:429
@ CMDPL_NO_CONSTRUCTION
No construction actions may be executed.
Definition: command_type.h:430
CommandType
Types of commands we have.
Definition: command_type.h:413
@ CMDT_END
Magic end marker.
Definition: command_type.h:424
@ CMDT_SERVER_SETTING
Pausing/removing companies/server settings.
Definition: command_type.h:421
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:382
@ DC_QUERY_COST
query cost only, don't build.
Definition: command_type.h:378
std::vector< uint8_t > CommandDataBuffer
Storage buffer for serialized command data.
Definition: command_type.h:470
Commands
List of commands.
Definition: command_type.h:187
@ CMD_COMPANY_CTRL
used in multiplayer to create a new companies etc.
Definition: command_type.h:300
@ CMD_END
Must ALWAYS be on the end of this list!! (period)
Definition: command_type.h:366
CommandFlags
Command flags for the command table _command_proc_table.
Definition: command_type.h:396
@ CMD_NO_EST
the command is never estimated.
Definition: command_type.h:407
@ CMD_SPECTATOR
the command may be initiated by a spectator
Definition: command_type.h:398
@ CMD_NO_TEST
the command's output may differ between test and execute due to town rating changes etc.
Definition: command_type.h:402
@ CMD_SERVER
the command can only be initiated by the server
Definition: command_type.h:397
@ CMD_DEITY
the command may be executed by COMPANY_DEITY
Definition: command_type.h:405
Definition of stuff that is very close to a company, like the company struct itself.
bool CheckCompanyHasMoney(CommandCost &cost)
Verify whether the company can pay the bill.
void SubtractMoneyFromCompany(const CommandCost &cost)
Subtract money from the _current_company, if the company is valid.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Command definitions related to companies.
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
Definition: company_func.h:47
@ COMPANY_SPECTATOR
The client is spectating.
Definition: company_type.h:35
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
Command definitions related to depots.
Command definitions related to the economy.
Endian-aware buffer.
Command definitions related to engines.
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition: error.h:24
bool _generating_world
Whether we are generating the map or not.
Definition: genworld.cpp:67
Functions related to world/map generation.
bool _shift_pressed
Is Shift pressed?
Definition: gfx.cpp:39
PauseMode _pause_mode
The current pause mode.
Definition: gfx.cpp:50
Command definitions related to goals.
Command definitions related to engine groups.
GUI functions that shouldn't be here.
void ShowEstimatedCostOrIncome(Money cost, int x, int y)
Display estimated costs.
Definition: misc_gui.cpp:551
Command definitions related to industries.
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition: landscape.cpp:303
Functions related to OTTD's landscape.
Command definitions related to landscape (slopes etc.).
Command definitions related to league tables.
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
Miscellaneous command definitions.
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
Display animated income or costs on the map.
Definition: misc_gui.cpp:570
bool _networking
are we in networking mode?
Definition: network.cpp:65
Basic functions/variables used all over the place.
Types used for networking.
@ PSM_LEAVE_TESTMODE
Leave command test mode, revert to previous mode.
@ PSM_LEAVE_COMMAND
Leave command scope, revert to previous mode.
@ PSM_ENTER_COMMAND
Enter command scope, changes will be permanent.
@ PSM_ENTER_TESTMODE
Enter command test mode, changes will be temporary.
Command definitions related to news messages.
Base for all objects.
Command definitions related to objects.
@ PM_COMMAND_DURING_PAUSE
A game paused, and a command executed during the pause; resets on autosave.
Definition: openttd.h:77
@ PM_UNPAUSED
A normal unpaused game.
Definition: openttd.h:69
Command definitions related to orders.
Command definitions for rail.
Road related functions.
Command definitions related to road vehicles.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
Command definitions related to settings.
static SigSegState UpdateSignalsInBuffer(Owner owner)
Updates blocks in _globset buffer.
Definition: signal.cpp:482
Functions related to signals.
Command definitions related to signs.
Command definitions related to stations.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
Command definitions related to stories.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition: string.cpp:81
Functions related to low-level strings.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
void Trash()
Trash the backup.
bool Verify() const
Check whether the variable is currently equals the backup.
void Change(const U &new_value)
Change the value of the variable.
Definition: backup_type.hpp:82
void Restore()
Restore the variable.
static void SwitchMode(PersistentStorageMode mode, bool ignore_prev_mode=false)
Clear temporary changes made since the last call to SwitchMode, and set whether subsequent changes sh...
Define a command with the flags which belongs to it.
Definition: command.cpp:76
const char * name
A human readable name for the procedure.
Definition: command.cpp:77
CommandType type
The type of command.
Definition: command.cpp:79
CommandFlags flags
The (command) flags to that apply to this command.
Definition: command.cpp:78
TileIndex last_build_coordinate
Coordinate of the last build thing by this company.
Definition: company_base.h:92
uint8_t command_pause_level
level/amount of commands that can't be executed while paused
Dynamic data of a loaded NewGRF.
Definition: newgrf.h:108
ConstructionSettings construction
construction of things in-game
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
Class for temporary storage of data.
Command definitions related to subsidies.
Command definitions related to terraforming.
Functions related to text effects.
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
Definition of the game-economy-timer.
Command definitions related to timetables.
Base of the town class.
void SetTownRatingTestMode(bool mode)
Switch the town rating to test-mode, to allow commands to be tested without affecting current ratings...
Definition: town_cmd.cpp:3911
Command definitions related to towns.
Command definitions related to trains.
Command definitions related to tree tiles.
Command definitions related to tunnels and bridges.
Command definitions for vehicles.
Command definitions related to viewports.
Command definitions related to water tiles.
Command definitions related to waypoints.