37template <Commands Tcmd>
68#if defined(__GNUC__) && !defined(__clang__)
78# pragma GCC diagnostic push
79# pragma GCC diagnostic ignored "-Wcast-function-type"
80# define SILENCE_GCC_FUNCTION_POINTER_CAST
104template <
Commands Tcmd,
typename Tret,
typename... Targs>
110 if constexpr (std::is_same_v<Tret, CommandCost>) {
113 return std::get<0>(ret);
121 ExtractCommandCost(ret) = cost;
141 if constexpr (std::is_same_v<
TileIndex, std::tuple_element_t<0, std::tuple<Targs...>>>) {
143 TileIndex tile = std::get<0>(std::make_tuple(args...));
150 if (counter.IsTopLevel() || !(flags &
DC_EXEC)) {
151 InternalDoBefore(counter.IsTopLevel(),
true);
153 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(),
true);
155 if (ExtractCommandCost(res).Failed() || !(flags &
DC_EXEC))
return res;
160 InternalDoBefore(counter.IsTopLevel(),
false);
162 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(),
false);
172 static inline bool Post(
StringID err_message, Targs... args) {
return Post<CommandCallback>(err_message,
nullptr, std::forward<Targs>(args)...); }
178 template <
typename Tcallback>
179 static inline bool Post(Tcallback *callback, Targs... args) {
return Post((
StringID)0, callback, std::forward<Targs>(args)...); }
184 static inline bool Post(Targs... args) {
return Post<CommandCallback>((
StringID)0,
nullptr, std::forward<Targs>(args)...); }
196 template <
typename Tcallback>
197 static bool Post(
StringID err_message, Tcallback *callback, Targs... args)
199 return InternalPost(err_message, callback,
true,
false, std::forward_as_tuple(args...));
210 template <
typename Tcallback>
211 static bool PostFromNet(
StringID err_message, Tcallback *callback,
bool my_cmd, std::tuple<Targs...> args)
213 return InternalPost(err_message, callback, my_cmd,
true, std::move(args));
225 auto args_tuple = std::forward_as_tuple(args...);
240 template <
typename Tcallback>
241 static Tret
Unsafe(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool estimate_only,
TileIndex location, std::tuple<Targs...> args)
243 return Execute(err_message,
reinterpret_cast<CommandCallback *
>(
reinterpret_cast<void(*)()
>(callback)), my_cmd, estimate_only,
false, location, std::move(args));
251 if constexpr (std::is_same_v<ClientID, T>) {
257 template<
class Ttuple,
size_t... Tindices>
258 static inline void SetClientIds(Ttuple &values, std::index_sequence<Tindices...>)
264 template <
template <
typename...>
typename Tt,
typename T1,
typename... Ts>
267 return std::apply([](
auto &&,
const auto&... args) {
return std::tie(args...); }, tuple);
270 template <
typename Tcallback>
271 static bool InternalPost(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool network_command, std::tuple<Targs...> args)
275 if constexpr (std::is_same_v<
TileIndex, std::tuple_element_t<0,
decltype(args)>>) {
276 tile = std::get<0>(args);
279 return InternalPost(err_message, callback, my_cmd, network_command, tile, std::move(args));
282 template <
typename Tcallback>
283 static bool InternalPost(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool network_command,
TileIndex tile, std::tuple<Targs...> args)
288 auto [err, estimate_only, only_sending] = InternalPostBefore(Tcmd, GetCommandFlags<Tcmd>(), tile, err_message, network_command);
289 if (err)
return false;
292 if (!network_command && GetCommandFlags<Tcmd>() &
CMD_CLIENT_ID)
SetClientIds(args, std::index_sequence_for<Targs...>{});
294 Tret res = Execute(err_message,
reinterpret_cast<CommandCallback *
>(
reinterpret_cast<void(*)()
>(callback)), my_cmd, estimate_only, network_command, tile, args);
295 InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
297 if (!estimate_only && !only_sending && callback !=
nullptr) {
298 if constexpr (std::is_same_v<Tcallback, CommandCallback>) {
300 callback(Tcmd, ExtractCommandCost(res), tile);
301 }
else if constexpr (std::is_same_v<Tcallback, CommandCallbackData>) {
303 if constexpr (std::is_same_v<Tret, CommandCost>) {
308 }
else if constexpr (!std::is_same_v<Tret, CommandCost> && std::is_same_v<Tcallback *, typename CommandTraits<Tcmd>::RetCallbackProc>) {
309 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res));
312 if constexpr (std::is_same_v<Tret, CommandCost>) {
313 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd, res), args));
315 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res, args));
320 return ExtractCommandCost(res).Succeeded();
327 if constexpr (std::is_same_v<ClientID, T>) {
335 template<
class Ttuple,
size_t... Tindices>
338 return (ClientIdIsSet(std::get<Tindices>(values)) && ...);
341 template<
class Ttuple>
342 static inline Money ExtractAdditionalMoney([[maybe_unused]] Ttuple &values)
344 if constexpr (std::is_same_v<std::tuple_element_t<1, Tret>,
Money>) {
345 return std::get<1>(values);
351 static Tret Execute(
StringID err_message,
CommandCallback *callback,
bool,
bool estimate_only,
bool network_command,
TileIndex tile, std::tuple<Targs...> args)
355 assert(counter.IsTopLevel());
358 constexpr CommandFlags cmd_flags = GetCommandFlags<Tcmd>();
362 assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{}));
366 if (!InternalExecutePrepTest(cmd_flags, tile, cur_company)) {
375 auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company);
378 cur_company.Restore();
386 cur_company.Restore();
402 Money additional_money{};
403 if constexpr (!std::is_same_v<Tret, CommandCost>) {
404 additional_money = ExtractAdditionalMoney(res2);
407 if constexpr (std::is_same_v<Tret, CommandCost>) {
408 return InternalExecuteProcessResult(Tcmd, cmd_flags, res, res2, additional_money, tile, cur_company);
410 std::get<0>(res2) = InternalExecuteProcessResult(Tcmd, cmd_flags, ExtractCommandCost(res), ExtractCommandCost(res2), additional_money, tile, cur_company);
423template <
Commands Tcmd,
typename Tret,
typename... Targs>
427 static inline bool Post(
StringID err_message, Targs... args) =
delete;
428 template <
typename Tcallback>
429 static inline bool Post(Tcallback *callback, Targs... args) =
delete;
430 static inline bool Post(Targs... args) =
delete;
431 template <
typename Tcallback>
432 static bool Post(
StringID err_message, Tcallback *callback, Targs... args) =
delete;
440 static inline bool Post(
StringID err_message,
TileIndex location, Targs... args) {
return Post<CommandCallback>(err_message,
nullptr, location, std::forward<Targs>(args)...); }
447 template <
typename Tcallback>
448 static inline bool Post(Tcallback *callback,
TileIndex location, Targs... args) {
return Post((
StringID)0, callback, location, std::forward<Targs>(args)...); }
454 static inline bool Post(
TileIndex location, Targs... args) {
return Post<CommandCallback>((
StringID)0,
nullptr, location, std::forward<Targs>(args)...); }
464 template <
typename Tcallback>
467 return CommandHelper<Tcmd, Tret(*)(
DoCommandFlag, Targs...),
true>::InternalPost(err_message, callback,
true,
false, location, std::forward_as_tuple(args...));
471#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
472# pragma GCC diagnostic pop
475template <Commands Tcmd>
Class for backupping variables and making sure they are restored later.
Common return value for all commands.
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.
static void InternalDoBefore(bool top_level, bool test)
Prepare for calling a command proc.
static void LogCommandExecution(Commands cmd, StringID err_message, const CommandDataBuffer &args, bool failed)
Helper to make a desync log for a command.
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.
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.
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.
static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup< CompanyID > &cur_company)
Prepare for the test run of a command proc call.
static void InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test)
Process result after calling a command proc.
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...
bool IsCommandAllowedWhilePaused(Commands cmd)
Returns whether the command is allowed while the game is paused.
const char * GetCommandName(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the name which belongs to the given com...
static constexpr DoCommandFlag CommandFlagsToDCFlags(CommandFlags cmd_flags)
Extracts the DC flags needed for DoCommand from the flags returned by GetCommandFlags.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
bool IsValidCommand(Commands cmd)
This function range-checks a cmd.
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.
DoCommandFlag
List of flags for a command.
@ DC_AUTO
don't allow building on structures
@ DC_NO_WATER
don't allow building on water
@ DC_ALL_TILES
allow this command also on MP_VOID tiles
@ DC_EXEC
execute the given command
std::vector< uint8_t > CommandDataBuffer
Storage buffer for serialized command data.
Commands
List of commands.
CommandFlags
Command flags for the command table _command_proc_table.
@ CMD_LOCATION
the command has implicit location argument.
@ CMD_ALL_TILES
allow this command also on MP_VOID tiles
@ CMD_AUTO
set the DC_AUTO flag on this command
@ CMD_NO_WATER
set the DC_NO_WATER flag on this command
@ CMD_CLIENT_ID
set p2 with the ClientID of the sending client.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
Types related to companies.
Owner
Enum for all companies/owners.
static void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
static void SetClientIdHelper(T &data, ClientID client_id)
Helper to process a single ClientID argument.
Types used for networking.
@ INVALID_CLIENT_ID
Client is not part of anything.
@ CLIENT_ID_SERVER
Servers always have this ID.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Class to backup a specific variable and restore it later.
static bool Post(StringID err_message, TileIndex location, Targs... args)
Shortcut for Post when not using a callback.
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...
static bool Post(Tcallback *callback, TileIndex location, Targs... args)
Shortcut for Post when not using an error message.
static bool Post(TileIndex location, Targs... args)
Shortcut for Post when not using a callback or an error message.
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.
static void SendNet(StringID err_message, CompanyID company, Targs... args)
Prepare a command to be send over the network.
static bool Post(StringID err_message, Targs... args)
Shortcut for the long Post when not using a callback.
static bool Post(StringID err_message, Tcallback *callback, Targs... args)
Top-level network safe command execution for the current company.
static bool AllClientIdsSet(Ttuple &values, std::index_sequence< Tindices... >)
Check if all ClientID arguments are set to valid values.
static Tret MakeResult(const CommandCost &cost)
Make a command proc result from a CommandCost.
static bool Post(Tcallback *callback, Targs... args)
Shortcut for the long Post when not using an error message.
static bool PostFromNet(StringID err_message, Tcallback *callback, bool my_cmd, std::tuple< Targs... > args)
Execute a command coming from the network.
static Tret Do(DoCommandFlag flags, Targs... args)
This function executes a given command with the parameters from the #CommandProc parameter list.
static void SetClientIds(Ttuple &values, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
static bool Post(Targs... args)
Shortcut for the long Post when not using a callback or an error message.
static CommandCost & ExtractCommandCost(Tret &ret)
Extract the CommandCost from a command proc result.
static void SetClientIdHelper(T &data)
Helper to process a single ClientID argument.
static bool ClientIdIsSet(T &data)
Helper to process a single ClientID argument.
static Tt< Ts... > RemoveFirstTupleElement(const Tt< T1, Ts... > &tuple)
Remove the first element of a tuple.
Defines the traits of a command.
static debug_inline uint Size()
Get the size of the map.
Helper class to keep track of command nesting level.
bool IsTopLevel() const
Are we in the top-level command execution?
Map writing/reading functions for tiles.
bool IsValidTile(Tile tile)
Checks if a tile is valid.
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.