From 3e85e833a707e6b781d00eae09c9465bacbf1d69 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 30 Nov 2021 00:52:23 +0100 Subject: [PATCH] Codechange: Add support for additional command result values. --- src/ai/ai_instance.cpp | 6 +- src/command_func.h | 97 +++++++++++++++++++++++--------- src/command_type.h | 13 ++++- src/game/game_instance.cpp | 6 +- src/network/network_command.cpp | 2 +- src/script/api/script_object.cpp | 10 ++++ src/script/api/script_object.hpp | 36 ++++++++++-- src/script/script_instance.cpp | 3 +- src/script/script_instance.hpp | 3 +- src/script/script_storage.hpp | 1 + 10 files changed, 136 insertions(+), 41 deletions(-) diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index e137745f19..0e8355d733 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -18,6 +18,7 @@ #include "ai.hpp" #include "../script/script_storage.hpp" +#include "../script/script_cmd.h" #include "ai_info.hpp" #include "ai_instance.hpp" @@ -96,8 +97,9 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version) * @param result The result of the command. * @param tile The tile on which the command was executed. * @param data Command data as given to Command<>::Post. + * @param result_data Additional returned data from the command. */ -void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data) +void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data) { /* * The company might not exist anymore. Check for this. @@ -108,7 +110,7 @@ void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const Command const Company *c = Company::GetIfValid(_current_company); if (c == nullptr || c->ai_instance == nullptr) return; - if (c->ai_instance->DoCommandCallback(result, tile, data, cmd)) { + if (c->ai_instance->DoCommandCallback(result, tile, data, std::move(result_data), cmd)) { c->ai_instance->Continue(); } } diff --git a/src/command_func.h b/src/command_func.h index 9219fd2b5f..117fed9177 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -111,10 +111,30 @@ protected: * Templated wrapper that exposes the command parameter arguments * for the various Command::Do/Post calls. * @tparam Tcmd The command-id to execute. + * @tparam Tret Return type of the command. * @tparam Targs The command parameter types. */ -template -struct CommandHelper : protected CommandHelperBase { +template +struct CommandHelper : protected CommandHelperBase { +private: + /** Extract the \c CommandCost from a command proc result. */ + static inline CommandCost &ExtractCommandCost(Tret &ret) + { + if constexpr (std::is_same_v) { + return ret; + } else { + return std::get<0>(ret); + } + } + + /** Make a command proc result from a \c CommandCost. */ + static inline Tret MakeResult(const CommandCost &cost) + { + Tret ret{}; + ExtractCommandCost(ret) = cost; + return ret; + } + public: /** * This function executes a given command with the parameters from the #CommandProc parameter list. @@ -129,12 +149,12 @@ public: * @see CommandProc * @return the cost */ - static CommandCost Do(DoCommandFlag flags, Targs... args) + static Tret Do(DoCommandFlag flags, Targs... args) { if constexpr (std::is_same_v>>) { /* Do not even think about executing out-of-bounds tile-commands. */ TileIndex tile = std::get<0>(std::make_tuple(args...)); - if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR; + if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return MakeResult(CMD_ERROR); } RecursiveCommandCounter counter{}; @@ -142,17 +162,17 @@ public: /* Only execute the test call if it's toplevel, or we're not execing. */ if (counter.IsTopLevel() || !(flags & DC_EXEC)) { InternalDoBefore(counter.IsTopLevel(), true); - CommandCost res = CommandTraits::proc(flags & ~DC_EXEC, args...); - InternalDoAfter(res, flags, counter.IsTopLevel(), true); // Can modify res. + Tret res = CommandTraits::proc(flags & ~DC_EXEC, args...); + InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), true); // Can modify res. - if (res.Failed() || !(flags & DC_EXEC)) return res; + if (ExtractCommandCost(res).Failed() || !(flags & DC_EXEC)) return res; } /* Execute the command here. All cost-relevant functions set the expenses type * themselves to the cost object at some point. */ InternalDoBefore(counter.IsTopLevel(), false); - CommandCost res = CommandTraits::proc(flags, args...); - InternalDoAfter(res, flags, counter.IsTopLevel(), false); + Tret res = CommandTraits::proc(flags, args...); + InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), false); return res; } @@ -237,7 +257,7 @@ public: * @return the command cost of this function. */ template - static CommandCost Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple args) + static Tret Unsafe(StringID err_message, Tcallback *callback, bool my_cmd, bool estimate_only, TileIndex location, std::tuple args) { return Execute(err_message, reinterpret_cast(callback), my_cmd, estimate_only, false, location, std::move(args)); } @@ -259,6 +279,13 @@ protected: ((SetClientIdHelper(std::get(values))), ...); } + /** Remove the first element of a tuple. */ + template