OpenTTD Source  20241120-master-g6d3adc6169
command_func.h
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 #ifndef COMMAND_FUNC_H
11 #define COMMAND_FUNC_H
12 
13 #include "command_type.h"
14 #include "network/network_type.h"
15 #include "company_type.h"
16 #include "company_func.h"
17 #include "core/backup_type.hpp"
18 #include "misc/endian_buffer.hpp"
19 #include "tile_map.h"
20 
29 
38 #define return_cmd_error(errcode) return CommandCost(errcode);
39 
40 void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data);
41 
42 bool IsValidCommand(Commands cmd);
44 const char *GetCommandName(Commands cmd);
46 
47 template <Commands Tcmd>
48 constexpr CommandFlags GetCommandFlags()
49 {
51 }
52 
58 static constexpr inline DoCommandFlag CommandFlagsToDCFlags(CommandFlags cmd_flags)
59 {
60  DoCommandFlag flags = DC_NONE;
61  if (cmd_flags & CMD_NO_WATER) flags |= DC_NO_WATER;
62  if (cmd_flags & CMD_AUTO) flags |= DC_AUTO;
63  if (cmd_flags & CMD_ALL_TILES) flags |= DC_ALL_TILES;
64  return flags;
65 }
66 
69  RecursiveCommandCounter() noexcept { _counter++; }
70  ~RecursiveCommandCounter() noexcept { _counter--; }
71 
73  bool IsTopLevel() const { return _counter == 1; }
74 private:
75  static int _counter;
76 };
77 
78 #if defined(__GNUC__) && !defined(__clang__)
79 /*
80  * We cast specialized function pointers to a generic one, but don't use the
81  * converted value to call the function, which is safe, except that GCC
82  * helpfully thinks it is not.
83  *
84  * "Any pointer to function can be converted to a pointer to a different function type.
85  * Calling the function through a pointer to a different function type is undefined,
86  * but converting such pointer back to pointer to the original function type yields
87  * the pointer to the original function." */
88 # pragma GCC diagnostic push
89 # pragma GCC diagnostic ignored "-Wcast-function-type"
90 # define SILENCE_GCC_FUNCTION_POINTER_CAST
91 #endif
92 
93 template<Commands TCmd, typename T, bool THasTile> struct CommandHelper;
94 
96 protected:
97  static void InternalDoBefore(bool top_level, bool test);
98  static void InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test);
99  static std::tuple<bool, bool, bool> InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command);
100  static void InternalPostResult(const CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd);
101  static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup<CompanyID> &cur_company);
102  static std::tuple<bool, bool, bool> InternalExecuteValidateTestAndPrepExec(CommandCost &res, CommandFlags cmd_flags, bool estimate_only, bool network_command, Backup<CompanyID> &cur_company);
103  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);
104  static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed);
105 };
106 
114 template <Commands Tcmd, typename Tret, typename... Targs>
115 struct CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), true> : protected CommandHelperBase {
116 private:
118  static inline CommandCost &ExtractCommandCost(Tret &ret)
119  {
120  if constexpr (std::is_same_v<Tret, CommandCost>) {
121  return ret;
122  } else {
123  return std::get<0>(ret);
124  }
125  }
126 
128  static inline Tret MakeResult(const CommandCost &cost)
129  {
130  Tret ret{};
131  ExtractCommandCost(ret) = cost;
132  return ret;
133  }
134 
135 public:
149  static Tret Do(DoCommandFlag flags, Targs... args)
150  {
151  if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, std::tuple<Targs...>>>) {
152  /* Do not even think about executing out-of-bounds tile-commands. */
153  TileIndex tile = std::get<0>(std::make_tuple(args...));
154  if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return MakeResult(CMD_ERROR);
155  }
156 
157  RecursiveCommandCounter counter{};
158 
159  /* Only execute the test call if it's toplevel, or we're not execing. */
160  if (counter.IsTopLevel() || !(flags & DC_EXEC)) {
161  InternalDoBefore(counter.IsTopLevel(), true);
162  Tret res = CommandTraits<Tcmd>::proc(flags & ~DC_EXEC, args...);
163  InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), true); // Can modify res.
164 
165  if (ExtractCommandCost(res).Failed() || !(flags & DC_EXEC)) return res;
166  }
167 
168  /* Execute the command here. All cost-relevant functions set the expenses type
169  * themselves to the cost object at some point. */
170  InternalDoBefore(counter.IsTopLevel(), false);
171  Tret res = CommandTraits<Tcmd>::proc(flags, args...);
172  InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), false);
173 
174  return res;
175  }
176 
182  static inline bool Post(StringID err_message, Targs... args) { return Post<CommandCallback>(err_message, nullptr, std::forward<Targs>(args)...); }
188  template <typename Tcallback>
189  static inline bool Post(Tcallback *callback, Targs... args) { return Post((StringID)0, callback, std::forward<Targs>(args)...); }
194  static inline bool Post(Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, std::forward<Targs>(args)...); }
195 
206  template <typename Tcallback>
207  static bool Post(StringID err_message, Tcallback *callback, Targs... args)
208  {
209  return InternalPost(err_message, callback, true, false, std::forward_as_tuple(args...));
210  }
211 
220  template <typename Tcallback>
221  static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple<Targs...> args)
222  {
223  return InternalPost(err_message, callback, my_cmd, true, std::move(args));
224  }
225 
233  static void SendNet(StringID err_message, CompanyID company, Targs... args)
234  {
235  auto args_tuple = std::forward_as_tuple(args...);
236 
237  ::NetworkSendCommand(Tcmd, err_message, nullptr, company, EndianBufferWriter<CommandDataBuffer>::FromValue(args_tuple));
238  }
239 
250  template <typename Tcallback>
251  static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple<Targs...> args)
252  {
253  return Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, false, location, std::move(args));
254  }
255 
256 protected:
258  template <class T>
259  static inline void SetClientIdHelper([[maybe_unused]] T &data)
260  {
261  if constexpr (std::is_same_v<ClientID, T>) {
262  if (data == INVALID_CLIENT_ID) data = CLIENT_ID_SERVER;
263  }
264  }
265 
267  template<class Ttuple, size_t... Tindices>
268  static inline void SetClientIds(Ttuple &values, std::index_sequence<Tindices...>)
269  {
270  ((SetClientIdHelper(std::get<Tindices>(values))), ...);
271  }
272 
274  template <template <typename...> typename Tt, typename T1, typename... Ts>
275  static inline Tt<Ts...> RemoveFirstTupleElement(const Tt<T1, Ts...> &tuple)
276  {
277  return std::apply([](auto &&, const auto&... args) { return std::tie(args...); }, tuple);
278  }
279 
280  template <typename Tcallback>
281  static bool InternalPost(StringID err_message, Tcallback *callback, bool my_cmd, bool network_command, std::tuple<Targs...> args)
282  {
283  /* Where to show the message? */
284  TileIndex tile{};
285  if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, decltype(args)>>) {
286  tile = std::get<0>(args);
287  }
288 
289  return InternalPost(err_message, callback, my_cmd, network_command, tile, std::move(args));
290  }
291 
292  template <typename Tcallback>
293  static bool InternalPost(StringID err_message, Tcallback *callback, bool my_cmd, bool network_command, TileIndex tile, std::tuple<Targs...> args)
294  {
295  /* Do not even think about executing out-of-bounds tile-commands. */
296  if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && (GetCommandFlags<Tcmd>() & CMD_ALL_TILES) == 0))) return false;
297 
298  auto [err, estimate_only, only_sending] = InternalPostBefore(Tcmd, GetCommandFlags<Tcmd>(), tile, err_message, network_command);
299  if (err) return false;
300 
301  /* Only set client IDs when the command does not come from the network. */
302  if (!network_command && GetCommandFlags<Tcmd>() & CMD_CLIENT_ID) SetClientIds(args, std::index_sequence_for<Targs...>{});
303 
304  Tret res = Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, network_command, tile, args);
305  InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
306 
307  if (!estimate_only && !only_sending && callback != nullptr) {
308  if constexpr (std::is_same_v<Tcallback, CommandCallback>) {
309  /* Callback that doesn't need any command arguments. */
310  callback(Tcmd, ExtractCommandCost(res), tile);
311  } else if constexpr (std::is_same_v<Tcallback, CommandCallbackData>) {
312  /* Generic callback that takes packed arguments as a buffer. */
313  if constexpr (std::is_same_v<Tret, CommandCost>) {
314  callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), {});
315  } else {
316  callback(Tcmd, ExtractCommandCost(res), EndianBufferWriter<CommandDataBuffer>::FromValue(args), EndianBufferWriter<CommandDataBuffer>::FromValue(RemoveFirstTupleElement(res)));
317  }
318  } else if constexpr (!std::is_same_v<Tret, CommandCost> && std::is_same_v<Tcallback *, typename CommandTraits<Tcmd>::RetCallbackProc>) {
319  std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res));
320  } else {
321  /* Callback with arguments. We assume that the tile is only interesting if it actually is in the command arguments. */
322  if constexpr (std::is_same_v<Tret, CommandCost>) {
323  std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd, res), args));
324  } else {
325  std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res, args));
326  }
327  }
328  }
329 
330  return ExtractCommandCost(res).Succeeded();
331  }
332 
334  template <class T>
335  static inline bool ClientIdIsSet([[maybe_unused]] T &data)
336  {
337  if constexpr (std::is_same_v<ClientID, T>) {
338  return data != INVALID_CLIENT_ID;
339  } else {
340  return true;
341  }
342  }
343 
345  template<class Ttuple, size_t... Tindices>
346  static inline bool AllClientIdsSet(Ttuple &values, std::index_sequence<Tindices...>)
347  {
348  return (ClientIdIsSet(std::get<Tindices>(values)) && ...);
349  }
350 
351  template<class Ttuple>
352  static inline Money ExtractAdditionalMoney([[maybe_unused]] Ttuple &values)
353  {
354  if constexpr (std::is_same_v<std::tuple_element_t<1, Tret>, Money>) {
355  return std::get<1>(values);
356  } else {
357  return {};
358  }
359  }
360 
361  static Tret Execute(StringID err_message, CommandCallback *callback, bool, bool estimate_only, bool network_command, TileIndex tile, std::tuple<Targs...> args)
362  {
363  /* Prevent recursion; it gives a mess over the network */
364  RecursiveCommandCounter counter{};
365  assert(counter.IsTopLevel());
366 
367  /* Command flags are used internally */
368  constexpr CommandFlags cmd_flags = GetCommandFlags<Tcmd>();
369 
370  if constexpr ((cmd_flags & CMD_CLIENT_ID) != 0) {
371  /* Make sure arguments are properly set to a ClientID also when processing external commands. */
372  assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{}));
373  }
374 
375  Backup<CompanyID> cur_company(_current_company);
376  if (!InternalExecutePrepTest(cmd_flags, tile, cur_company)) {
377  cur_company.Trash();
378  return MakeResult(CMD_ERROR);
379  }
380 
381  /* Test the command. */
382  DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
383  Tret res = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags), args));
384 
385  auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company);
386  if (exit_test) {
387  if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), true);
388  cur_company.Restore();
389  return res;
390  }
391 
392  /* If we are in network, and the command is not from the network
393  * send it to the command-queue and abort execution. */
394  if (send_net) {
396  cur_company.Restore();
397 
398  /* Don't return anything special here; no error, no costs.
399  * This way it's not handled by DoCommand and only the
400  * actual execution of the command causes messages. Also
401  * reset the storages as we've not executed the command. */
402  return {};
403  }
404 
405  if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter<CommandDataBuffer>::FromValue(args), false);
406 
407  /* Actually try and execute the command. */
408  Tret res2 = std::apply(CommandTraits<Tcmd>::proc, std::tuple_cat(std::make_tuple(flags | DC_EXEC), args));
409 
410  /* Convention: If the second result element is of type Money,
411  * this is the additional cash required for the command. */
412  Money additional_money{};
413  if constexpr (!std::is_same_v<Tret, CommandCost>) { // No short-circuiting for 'if constexpr'.
414  additional_money = ExtractAdditionalMoney(res2);
415  }
416 
417  if constexpr (std::is_same_v<Tret, CommandCost>) {
418  return InternalExecuteProcessResult(Tcmd, cmd_flags, res, res2, additional_money, tile, cur_company);
419  } else {
420  std::get<0>(res2) = InternalExecuteProcessResult(Tcmd, cmd_flags, ExtractCommandCost(res), ExtractCommandCost(res2), additional_money, tile, cur_company);
421  return res2;
422  }
423  }
424 };
425 
433 template <Commands Tcmd, typename Tret, typename... Targs>
434 struct CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), false> : CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), true>
435 {
436  /* Do not allow Post without explicit location. */
437  static inline bool Post(StringID err_message, Targs... args) = delete;
438  template <typename Tcallback>
439  static inline bool Post(Tcallback *callback, Targs... args) = delete;
440  static inline bool Post(Targs... args) = delete;
441  template <typename Tcallback>
442  static bool Post(StringID err_message, Tcallback *callback, Targs... args) = delete;
443 
450  static inline bool Post(StringID err_message, TileIndex location, Targs... args) { return Post<CommandCallback>(err_message, nullptr, location, std::forward<Targs>(args)...); }
457  template <typename Tcallback>
458  static inline bool Post(Tcallback *callback, TileIndex location, Targs... args) { return Post((StringID)0, callback, location, std::forward<Targs>(args)...); }
464  static inline bool Post(TileIndex location, Targs... args) { return Post<CommandCallback>((StringID)0, nullptr, location, std::forward<Targs>(args)...); }
465 
474  template <typename Tcallback>
475  static inline bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args)
476  {
477  return CommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...), true>::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...));
478  }
479 };
480 
481 #ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
482 # pragma GCC diagnostic pop
483 #endif
484 
485 template <Commands Tcmd>
486 using Command = CommandHelper<Tcmd, typename CommandTraits<Tcmd>::ProcType, (GetCommandFlags<Tcmd>() & CMD_LOCATION) == 0>;
487 
488 #endif /* COMMAND_FUNC_H */
Class for backupping variables and making sure they are restored later.
Common return value for all commands.
Definition: command_type.h:23
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
Endian-aware buffer adapter that always writes values in little endian order.
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
static constexpr DoCommandFlag CommandFlagsToDCFlags(CommandFlags cmd_flags)
Extracts the DC flags needed for DoCommand from the flags returned by GetCommandFlags.
Definition: command_func.h:58
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
bool IsValidCommand(Commands cmd)
This function range-checks a cmd.
Definition: command.cpp:106
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
Prepare a DoCommand to be send over the network.
Types related to commands.
void CommandCallback(Commands cmd, const CommandCost &result, TileIndex tile)
Define a callback function for the client, after the command is finished.
Definition: command_type.h:484
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_NONE
no flag is set
Definition: command_type.h:375
@ DC_AUTO
don't allow building on structures
Definition: command_type.h:377
@ DC_NO_WATER
don't allow building on water
Definition: command_type.h:379
@ DC_ALL_TILES
allow this command also on MP_VOID tiles
Definition: command_type.h:385
@ DC_EXEC
execute the given command
Definition: command_type.h:376
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
CommandFlags
Command flags for the command table _command_proc_table.
Definition: command_type.h:396
@ CMD_LOCATION
the command has implicit location argument.
Definition: command_type.h:408
@ CMD_ALL_TILES
allow this command also on MP_VOID tiles
Definition: command_type.h:401
@ CMD_AUTO
set the DC_AUTO flag on this command
Definition: command_type.h:400
@ CMD_NO_WATER
set the DC_NO_WATER flag on this command
Definition: command_type.h:403
@ CMD_CLIENT_ID
set p2 with the ClientID of the sending client.
Definition: command_type.h:404
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
Types related to companies.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Endian-aware buffer.
static void SetClientIdHelper(T &data, [[maybe_unused]] ClientID client_id)
Helper to process a single ClientID argument.
static void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
Types used for networking.
@ INVALID_CLIENT_ID
Client is not part of anything.
Definition: network_type.h:50
@ CLIENT_ID_SERVER
Servers always have this ID.
Definition: network_type.h:51
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
static bool Post(StringID err_message, TileIndex location, Targs... args)
Shortcut for Post when not using a callback.
Definition: command_func.h:450
static bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args)
Post variant that takes a TileIndex (for error window location and text effects) for commands that do...
Definition: command_func.h:475
static bool Post(Tcallback *callback, TileIndex location, Targs... args)
Shortcut for Post when not using an error message.
Definition: command_func.h:458
static bool Post(TileIndex location, Targs... args)
Shortcut for Post when not using a callback or an error message.
Definition: command_func.h:464
static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple< Targs... > args)
Top-level network safe command execution without safety checks.
Definition: command_func.h:251
static void SendNet(StringID err_message, CompanyID company, Targs... args)
Prepare a command to be send over the network.
Definition: command_func.h:233
static bool Post(StringID err_message, Targs... args)
Shortcut for the long Post when not using a callback.
Definition: command_func.h:182
static bool Post(StringID err_message, Tcallback *callback, Targs... args)
Top-level network safe command execution for the current company.
Definition: command_func.h:207
static bool AllClientIdsSet(Ttuple &values, std::index_sequence< Tindices... >)
Check if all ClientID arguments are set to valid values.
Definition: command_func.h:346
static Tret MakeResult(const CommandCost &cost)
Make a command proc result from a CommandCost.
Definition: command_func.h:128
static bool Post(Tcallback *callback, Targs... args)
Shortcut for the long Post when not using an error message.
Definition: command_func.h:189
static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple< Targs... > args)
Execute a command coming from the network.
Definition: command_func.h:221
static Tret Do(DoCommandFlag flags, Targs... args)
This function executes a given command with the parameters from the #CommandProc parameter list.
Definition: command_func.h:149
static bool ClientIdIsSet([[maybe_unused]] T &data)
Helper to process a single ClientID argument.
Definition: command_func.h:335
static void SetClientIds(Ttuple &values, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
Definition: command_func.h:268
static CommandCost & ExtractCommandCost(Tret &ret)
Extract the CommandCost from a command proc result.
Definition: command_func.h:118
static bool Post(Targs... args)
Shortcut for the long Post when not using a callback or an error message.
Definition: command_func.h:194
static Tt< Ts... > RemoveFirstTupleElement(const Tt< T1, Ts... > &tuple)
Remove the first element of a tuple.
Definition: command_func.h:275
static void SetClientIdHelper([[maybe_unused]] T &data)
Helper to process a single ClientID argument.
Definition: command_func.h:259
Defines the traits of a command.
Definition: command_type.h:453
static debug_inline uint Size()
Get the size of the map.
Definition: map_func.h:288
Helper class to keep track of command nesting level.
Definition: command_func.h:68
bool IsTopLevel() const
Are we in the top-level command execution?
Definition: command_func.h:73
Map writing/reading functions for tiles.
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161