10 #ifndef COMMAND_FUNC_H
11 #define COMMAND_FUNC_H
38 #define return_cmd_error(errcode) return CommandCost(errcode);
48 template <Commands Tcmd>
79 #if defined(__GNUC__) && !defined(__clang__)
89 # pragma GCC diagnostic push
90 # pragma GCC diagnostic ignored "-Wcast-function-type"
91 # define SILENCE_GCC_FUNCTION_POINTER_CAST
94 template<Commands TCmd,
typename T,
bool THasTile>
struct CommandHelper;
115 template <
Commands Tcmd,
typename Tret,
typename... Targs>
121 if constexpr (std::is_same_v<Tret, CommandCost>) {
124 return std::get<0>(ret);
132 ExtractCommandCost(ret) = cost;
152 if constexpr (std::is_same_v<
TileIndex, std::tuple_element_t<0, std::tuple<Targs...>>>) {
154 TileIndex tile = std::get<0>(std::make_tuple(args...));
161 if (counter.IsTopLevel() || !(flags &
DC_EXEC)) {
162 InternalDoBefore(counter.IsTopLevel(),
true);
164 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(),
true);
166 if (ExtractCommandCost(res).Failed() || !(flags &
DC_EXEC))
return res;
171 InternalDoBefore(counter.IsTopLevel(),
false);
173 InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(),
false);
183 static inline bool Post(
StringID err_message, Targs... args) {
return Post<CommandCallback>(err_message,
nullptr, std::forward<Targs>(args)...); }
189 template <
typename Tcallback>
190 static inline bool Post(Tcallback *callback, Targs... args) {
return Post((
StringID)0, callback, std::forward<Targs>(args)...); }
195 static inline bool Post(Targs... args) {
return Post<CommandCallback>((
StringID)0,
nullptr, std::forward<Targs>(args)...); }
207 template <
typename Tcallback>
208 static bool Post(
StringID err_message, Tcallback *callback, Targs... args)
210 return InternalPost(err_message, callback,
true,
false, std::forward_as_tuple(args...));
221 template <
typename Tcallback>
222 static bool PostFromNet(
StringID err_message, Tcallback *callback,
bool my_cmd, std::tuple<Targs...> args)
224 return InternalPost(err_message, callback, my_cmd,
true, std::move(args));
236 auto args_tuple = std::forward_as_tuple(args...);
251 template <
typename Tcallback>
252 static Tret
Unsafe(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool estimate_only,
TileIndex location, std::tuple<Targs...> args)
254 return Execute(err_message,
reinterpret_cast<CommandCallback *
>(callback), my_cmd, estimate_only,
false, location, std::move(args));
262 if constexpr (std::is_same_v<ClientID, T>) {
268 template<
class Ttuple,
size_t... Tindices>
269 static inline void SetClientIds(Ttuple &values, std::index_sequence<Tindices...>)
275 template <
template <
typename...>
typename Tt,
typename T1,
typename... Ts>
278 return std::apply([](
auto &&,
const auto&... args) {
return std::tie(args...); }, tuple);
281 template <
typename Tcallback>
282 static bool InternalPost(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool network_command, std::tuple<Targs...> args)
286 if constexpr (std::is_same_v<
TileIndex, std::tuple_element_t<0, decltype(args)>>) {
287 tile = std::get<0>(args);
290 return InternalPost(err_message, callback, my_cmd, network_command, tile, std::move(args));
293 template <
typename Tcallback>
294 static bool InternalPost(
StringID err_message, Tcallback *callback,
bool my_cmd,
bool network_command,
TileIndex tile, std::tuple<Targs...> args)
299 auto [err, estimate_only, only_sending] = InternalPostBefore(Tcmd, GetCommandFlags<Tcmd>(), tile, err_message, network_command);
300 if (err)
return false;
303 if (!network_command && GetCommandFlags<Tcmd>() &
CMD_CLIENT_ID)
SetClientIds(args, std::index_sequence_for<Targs...>{});
305 Tret res = Execute(err_message,
reinterpret_cast<CommandCallback *
>(callback), my_cmd, estimate_only, network_command, tile, args);
306 InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
308 if (!estimate_only && !only_sending && callback !=
nullptr) {
309 if constexpr (std::is_same_v<Tcallback, CommandCallback>) {
311 callback(Tcmd, ExtractCommandCost(res), tile);
312 }
else if constexpr (std::is_same_v<Tcallback, CommandCallbackData>) {
314 if constexpr (std::is_same_v<Tret, CommandCost>) {
320 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res));
323 if constexpr (std::is_same_v<Tret, CommandCost>) {
324 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd, res), args));
326 std::apply(callback, std::tuple_cat(std::make_tuple(Tcmd), res, args));
331 return ExtractCommandCost(res).Succeeded();
338 if constexpr (std::is_same_v<ClientID, T>) {
346 template<
class Ttuple,
size_t... Tindices>
349 return (ClientIdIsSet(std::get<Tindices>(values)) && ...);
352 template<
class Ttuple>
353 static inline Money ExtractAdditionalMoney(Ttuple &values)
355 if constexpr (std::is_same_v<std::tuple_element_t<1, Tret>,
Money>) {
356 return std::get<1>(values);
362 static Tret Execute(
StringID err_message,
CommandCallback *callback,
bool my_cmd,
bool estimate_only,
bool network_command,
TileIndex tile, std::tuple<Targs...> args)
366 assert(counter.IsTopLevel());
369 constexpr
CommandFlags cmd_flags = GetCommandFlags<Tcmd>();
373 assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{}));
377 if (!InternalExecutePrepTest(cmd_flags, tile, cur_company)) {
386 auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company);
389 cur_company.Restore();
397 cur_company.Restore();
413 Money additional_money{};
414 if constexpr (!std::is_same_v<Tret, CommandCost>) {
415 additional_money = ExtractAdditionalMoney(res2);
418 if constexpr (std::is_same_v<Tret, CommandCost>) {
419 return InternalExecuteProcessResult(Tcmd, cmd_flags, res, res2, additional_money, tile, cur_company);
421 std::get<0>(res2) = InternalExecuteProcessResult(Tcmd, cmd_flags, ExtractCommandCost(res), ExtractCommandCost(res2), additional_money, tile, cur_company);
434 template <
Commands Tcmd,
typename Tret,
typename... Targs>
438 static inline bool Post(
StringID err_message, Targs... args) =
delete;
439 template <
typename Tcallback>
440 static inline bool Post(Tcallback *callback, Targs... args) =
delete;
441 static inline bool Post(Targs... args) =
delete;
442 template <
typename Tcallback>
443 static bool Post(
StringID err_message, Tcallback *callback, Targs... args) =
delete;
451 static inline bool Post(
StringID err_message,
TileIndex location, Targs... args) {
return Post<CommandCallback>(err_message,
nullptr, location, std::forward<Targs>(args)...); }
458 template <
typename Tcallback>
459 static inline bool Post(Tcallback *callback,
TileIndex location, Targs... args) {
return Post((
StringID)0, callback, location, std::forward<Targs>(args)...); }
465 static inline bool Post(
TileIndex location, Targs... args) {
return Post<CommandCallback>((
StringID)0,
nullptr, location, std::forward<Targs>(args)...); }
475 template <
typename Tcallback>
478 return CommandHelper<Tcmd, Tret(*)(
DoCommandFlag, Targs...),
true>::InternalPost(err_message, callback,
true,
false, location, std::forward_as_tuple(args...));
482 #ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
483 # pragma GCC diagnostic pop
486 template <Commands Tcmd>