aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-04-10 16:58:39 +0200
committerShauren <shauren.trinity@gmail.com>2025-04-10 16:58:39 +0200
commitf1141d363872bad3524beec29e2eca55d0a8b6ed (patch)
tree32b25c20aa5c739f6d7c3e200942a1a84afeaf44
parent70a5bb451c46329355fa5fdeb28c6e565d4242c8 (diff)
Core/Commands: Allow non-const reference arguments in chat command handlers
-rw-r--r--src/server/game/Chat/ChatCommands/ChatCommand.h22
-rw-r--r--src/server/scripts/Commands/cs_ban.cpp2
2 files changed, 17 insertions, 7 deletions
diff --git a/src/server/game/Chat/ChatCommands/ChatCommand.h b/src/server/game/Chat/ChatCommands/ChatCommand.h
index 80996348c66..b7783e4faa8 100644
--- a/src/server/game/Chat/ChatCommands/ChatCommand.h
+++ b/src/server/game/Chat/ChatCommands/ChatCommand.h
@@ -114,8 +114,10 @@ namespace Trinity::Impl::ChatCommands
}
template <typename T> struct HandlerToTuple { static_assert(Trinity::dependant_false_v<T>, "Invalid command handler signature"); };
- template <typename... Ts> struct HandlerToTuple<bool(ChatHandler*, Ts...)> { using type = std::tuple<ChatHandler*, std::remove_cvref_t<Ts>...>; };
- template <typename T> using TupleType = typename HandlerToTuple<T>::type;
+ template <typename... Ts> struct HandlerToTuple<bool(ChatHandler*, Ts...)> { using type = std::tuple<ChatHandler*, Ts...>; };
+
+ template <typename> struct ValueTupleType { };
+ template <typename... Ts> struct ValueTupleType<std::tuple<Ts...>> { using type = std::tuple<std::remove_cvref_t<Ts>...>; };
struct CommandInvoker
{
@@ -125,13 +127,14 @@ namespace Trinity::Impl::ChatCommands
{
_wrapper = [](void* handler, ChatHandler* chatHandler, std::string_view argsStr)
{
- using Tuple = TupleType<TypedHandler>;
+ using RefTuple = typename HandlerToTuple<TypedHandler>::type;
+ using ValueTuple = typename ValueTupleType<RefTuple>::type;
- Tuple arguments;
+ ValueTuple arguments;
std::get<0>(arguments) = chatHandler;
- ChatCommandResult result = ConsumeFromOffset<Tuple, 1>(arguments, chatHandler, argsStr);
+ ChatCommandResult result = ConsumeFromOffset<ValueTuple, 1>(arguments, chatHandler, argsStr);
if (result)
- return std::apply(reinterpret_cast<TypedHandler*>(handler), std::move(arguments));
+ return Invoke<RefTuple>(reinterpret_cast<TypedHandler*>(handler), arguments, std::make_index_sequence<std::tuple_size_v<RefTuple>>{});
else
{
if (result.HasErrorMessage())
@@ -161,6 +164,13 @@ namespace Trinity::Impl::ChatCommands
}
private:
+ template <typename ReferenceTuple, typename TypedHandler, typename ValueTuple, std::size_t... I>
+ static constexpr bool Invoke(TypedHandler* handler, ValueTuple& arguments, std::index_sequence<I...>)
+ {
+ // Invoke command handler preserving original reference category of each argument
+ return std::invoke(handler, std::get<I>(advstd::forward_like<std::tuple_element_t<I, ReferenceTuple>>(arguments))...);
+ }
+
using wrapper_func = bool(void*, ChatHandler*, std::string_view);
wrapper_func* _wrapper;
void* _handler;
diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp
index 7af5a820ccc..b85bc48c326 100644
--- a/src/server/scripts/Commands/cs_ban.cpp
+++ b/src/server/scripts/Commands/cs_ban.cpp
@@ -368,7 +368,7 @@ public:
return true;
}
- static bool HandleBanInfoIPCommand(ChatHandler* handler, std::string&& ip)
+ static bool HandleBanInfoIPCommand(ChatHandler* handler, std::string& ip)
{
if (!IsIPAddress(ip))
return false;