Codechange: Template script command calls.
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
#include "../../misc/countedptr.hpp"
|
||||
#include "../../road_type.h"
|
||||
#include "../../rail_type.h"
|
||||
#include "../../command_type.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../command_func.h"
|
||||
|
||||
#include "script_types.hpp"
|
||||
#include "../script_suspend.hpp"
|
||||
@@ -67,10 +68,32 @@ public:
|
||||
static class ScriptInstance *GetActiveInstance();
|
||||
|
||||
protected:
|
||||
template<Commands TCmd, typename T> struct ScriptDoCommandHelper;
|
||||
|
||||
/**
|
||||
* Executes a raw DoCommand for the script.
|
||||
* Templated wrapper that exposes the command parameter arguments
|
||||
* on the various DoCommand calls.
|
||||
* @tparam Tcmd The command-id to execute.
|
||||
* @tparam Targs The command parameter types.
|
||||
*/
|
||||
static bool DoCommand(TileIndex tile, uint32 p1, uint32 p2, Commands cmd, const char *text = nullptr, Script_SuspendCallbackProc *callback = nullptr);
|
||||
template <Commands Tcmd, typename... Targs>
|
||||
struct ScriptDoCommandHelper<Tcmd, CommandCost(*)(DoCommandFlag, Targs...)> {
|
||||
static bool Do(Script_SuspendCallbackProc *callback, Targs... args)
|
||||
{
|
||||
return Execute(callback, std::forward_as_tuple(args...));
|
||||
}
|
||||
|
||||
static bool Do(Targs... args)
|
||||
{
|
||||
return Execute(nullptr, std::forward_as_tuple(args...));
|
||||
}
|
||||
|
||||
private:
|
||||
static bool Execute(Script_SuspendCallbackProc *callback, std::tuple<Targs...> args);
|
||||
};
|
||||
|
||||
template <Commands Tcmd>
|
||||
using Command = ScriptDoCommandHelper<Tcmd, typename ::CommandTraits<Tcmd>::ProcType>;
|
||||
|
||||
/**
|
||||
* Store the latest command executed by the script.
|
||||
@@ -299,6 +322,58 @@ private:
|
||||
* @param story_page_id The new StoryPageID.
|
||||
*/
|
||||
static void SetNewStoryPageElementID(StoryPageElementID story_page_element_id);
|
||||
|
||||
/* Helper functions for DoCommand. */
|
||||
static std::tuple<bool, bool, bool> DoCommandPrep();
|
||||
static bool DoCommandProcessResult(const CommandCost &res, Script_SuspendCallbackProc *callback, bool estimate_only);
|
||||
static CommandCallback *GetDoCommandCallback();
|
||||
};
|
||||
|
||||
namespace ScriptObjectInternal {
|
||||
/** Validate a single string argument coming from network. */
|
||||
template <class T>
|
||||
static inline void SanitizeSingleStringHelper(T &data)
|
||||
{
|
||||
if constexpr (std::is_same_v<std::string, T>) {
|
||||
/* The string must be valid, i.e. not contain special codes. Since some
|
||||
* can be made with GSText, make sure the control codes are removed. */
|
||||
data = ::StrMakeValid(data, SVS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper function to perform validation on command data strings. */
|
||||
template<class Ttuple, size_t... Tindices>
|
||||
static inline void SanitizeStringsHelper(Ttuple &values, std::index_sequence<Tindices...>)
|
||||
{
|
||||
((SanitizeSingleStringHelper(std::get<Tindices>(values))), ...);
|
||||
}
|
||||
}
|
||||
|
||||
template <Commands Tcmd, typename... Targs>
|
||||
bool ScriptObject::ScriptDoCommandHelper<Tcmd, CommandCost(*)(DoCommandFlag, Targs...)>::Execute(Script_SuspendCallbackProc *callback, std::tuple<Targs...> args)
|
||||
{
|
||||
auto [err, estimate_only, networking] = ScriptObject::DoCommandPrep();
|
||||
if (err) return false;
|
||||
|
||||
if ((::GetCommandFlags<Tcmd>() & CMD_STR_CTRL) == 0) {
|
||||
ScriptObjectInternal::SanitizeStringsHelper(args, std::index_sequence_for<Targs...>{});
|
||||
}
|
||||
|
||||
TileIndex tile{};
|
||||
if constexpr (std::is_same_v<TileIndex, std::tuple_element_t<0, decltype(args)>>) {
|
||||
tile = std::get<0>(args);
|
||||
}
|
||||
|
||||
/* Only set p2 when the command does not come from the network. */
|
||||
if ((::GetCommandFlags<Tcmd>() & CMD_CLIENT_ID) != 0 && std::get<2>(args) == 0) std::get<2>(args) = UINT32_MAX;
|
||||
|
||||
/* Store the command for command callback validation. */
|
||||
if (!estimate_only && networking) ScriptObject::SetLastCommand(tile, EndianBufferWriter<CommandDataBuffer>::FromValue(args), Tcmd);
|
||||
|
||||
/* Try to perform the command. */
|
||||
CommandCost res = std::apply(&DoCommandPInternal, std::tuple_cat(std::make_tuple(Tcmd, (StringID)0, networking ? ScriptObject::GetDoCommandCallback() : nullptr, false, estimate_only, false), args));
|
||||
|
||||
return ScriptObject::DoCommandProcessResult(res, callback, estimate_only);
|
||||
}
|
||||
|
||||
#endif /* SCRIPT_OBJECT_HPP */
|
||||
|
Reference in New Issue
Block a user