Add custom command support
This commit is contained in:
parent
306625aa80
commit
a7f60aeae2
124
src/client/component/command.cpp
Normal file
124
src/client/component/command.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "command.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/memory.hpp>
|
||||||
|
|
||||||
|
#include <game/game.hpp>
|
||||||
|
|
||||||
|
namespace command
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, command_param_function>& get_command_map()
|
||||||
|
{
|
||||||
|
static std::unordered_map<std::string, command_param_function> command_map{};
|
||||||
|
return command_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_custom_command()
|
||||||
|
{
|
||||||
|
const params params{};
|
||||||
|
|
||||||
|
auto& map = get_command_map();
|
||||||
|
const auto entry = map.find(params[0]);
|
||||||
|
if (entry != map.end())
|
||||||
|
{
|
||||||
|
entry->second(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
game::CmdArgs* get_cmd_args()
|
||||||
|
{
|
||||||
|
return game::Sys_GetTLS()->cmdArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_whitelist_stub()
|
||||||
|
{
|
||||||
|
game::cmd_function_s* current_function = game::cmd_functions;
|
||||||
|
while (current_function)
|
||||||
|
{
|
||||||
|
current_function->autoComplete = 1;
|
||||||
|
current_function = current_function->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
command::add("bruuh", [](const params& p)
|
||||||
|
{
|
||||||
|
MessageBoxA(0, p.join(0).data(), 0, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable whitelist
|
||||||
|
utils::hook::jump(0x14133CF70_g, update_whitelist_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
params::params()
|
||||||
|
: nesting_(get_cmd_args()->nesting)
|
||||||
|
{
|
||||||
|
assert(this->nesting_ < game::CMD_MAX_NESTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
int params::size() const
|
||||||
|
{
|
||||||
|
return get_cmd_args()->argc[this->nesting_];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* params::get(const int index) const
|
||||||
|
{
|
||||||
|
if (index >= this->size())
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_cmd_args()->argv[this->nesting_][index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string params::join(const int index) const
|
||||||
|
{
|
||||||
|
std::string result = {};
|
||||||
|
|
||||||
|
for (auto i = index; i < this->size(); i++)
|
||||||
|
{
|
||||||
|
if (i > index) result.append(" ");
|
||||||
|
result.append(this->get(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(std::string command, command_function function)
|
||||||
|
{
|
||||||
|
add(std::move(command), [f = std::move(function)](const params&)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(std::string command, command_param_function function)
|
||||||
|
{
|
||||||
|
auto& map = get_command_map();
|
||||||
|
const auto reregister = map.contains(command);
|
||||||
|
|
||||||
|
if (!reregister)
|
||||||
|
{
|
||||||
|
auto& allocator = *utils::memory::get_allocator();
|
||||||
|
auto* cmd_function = allocator.allocate<game::cmd_function_s>();
|
||||||
|
const auto* cmd_string = allocator.duplicate_string(command);
|
||||||
|
|
||||||
|
game::Cmd_AddCommandInternal(cmd_string, execute_custom_command, cmd_function);
|
||||||
|
cmd_function->autoComplete = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
map[std::move(command)] = std::move(function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(command::component)
|
28
src/client/component/command.hpp
Normal file
28
src/client/component/command.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace command
|
||||||
|
{
|
||||||
|
class params
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
params();
|
||||||
|
|
||||||
|
int size() const;
|
||||||
|
const char* get(int index) const;
|
||||||
|
std::string join(int index) const;
|
||||||
|
|
||||||
|
const char* operator[](const int index) const
|
||||||
|
{
|
||||||
|
return this->get(index); //
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int nesting_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using command_function = std::function<void()>;
|
||||||
|
using command_param_function = std::function<void(const params&)>;
|
||||||
|
|
||||||
|
void add(std::string command, command_function function);
|
||||||
|
void add(std::string command, command_param_function function);
|
||||||
|
}
|
@ -439,6 +439,7 @@ namespace game
|
|||||||
const char* autoCompleteDir;
|
const char* autoCompleteDir;
|
||||||
const char* autoCompleteExt;
|
const char* autoCompleteExt;
|
||||||
xcommand_t function;
|
xcommand_t function;
|
||||||
|
int autoComplete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdArgs
|
struct CmdArgs
|
||||||
|
@ -17,12 +17,17 @@ namespace game
|
|||||||
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x1421499C0};
|
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x1421499C0};
|
||||||
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8BD0};
|
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8BD0};
|
||||||
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7DD0};
|
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7DD0};
|
||||||
WEAK symbol<void(uint32_t localClientNum, eModes fromMode, eModes toMode, uint32_t flags)> Com_SwitchMode{0x14214AF30 };
|
WEAK symbol<void(uint32_t localClientNum, eModes fromMode, eModes toMode, uint32_t flags)> Com_SwitchMode{
|
||||||
|
0x14214AF30
|
||||||
|
};
|
||||||
|
|
||||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0};
|
WEAK symbol<void(uint32_t localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0};
|
||||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
||||||
0x1420ED530
|
0x1420ED530
|
||||||
};
|
};
|
||||||
|
WEAK symbol<void(uint32_t localClientNum, ControllerIndex_t controllerIndex, const char* text, bool fromRemoteConsol)> Cmd_ExecuteSingleCommand{
|
||||||
|
0x1420EDC20
|
||||||
|
};
|
||||||
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0};
|
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0};
|
||||||
|
|
||||||
// DB
|
// DB
|
||||||
@ -57,7 +62,8 @@ namespace game
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
WEAK symbol<void(const char*, int, const void*, float, float, float, float, float, const float*, int)> R_AddCmdDrawText{
|
WEAK symbol<void(const char*, int, const void*, float, float, float, float, float, const float*, int)>
|
||||||
|
R_AddCmdDrawText{
|
||||||
0x141CD98D0
|
0x141CD98D0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,14 +91,6 @@ namespace game
|
|||||||
// Global game definitions
|
// Global game definitions
|
||||||
constexpr auto CMD_MAX_NESTING = 8;
|
constexpr auto CMD_MAX_NESTING = 8;
|
||||||
|
|
||||||
struct cmd_args_t
|
|
||||||
{
|
|
||||||
CmdArgs* operator->() const
|
|
||||||
{
|
|
||||||
return Sys_GetTLS()->cmdArgs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Re-implementations
|
// Re-implementations
|
||||||
eModes Com_SessionMode_GetMode();
|
eModes Com_SessionMode_GetMode();
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,8 @@ namespace utils::hook
|
|||||||
void un_move();
|
void un_move();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<std::pair<void*, void*>> iat(const nt::library& library, const std::string& target_library, const std::string& process, void* stub);
|
std::optional<std::pair<void*, void*>> iat(const nt::library& library, const std::string& target_library,
|
||||||
|
const std::string& process, void* stub);
|
||||||
|
|
||||||
void nop(void* place, size_t length);
|
void nop(void* place, size_t length);
|
||||||
void nop(size_t place, size_t length);
|
void nop(size_t place, size_t length);
|
||||||
|
@ -22,13 +22,13 @@ namespace utils
|
|||||||
void* allocate(size_t length);
|
void* allocate(size_t length);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T* allocate()
|
T* allocate()
|
||||||
{
|
{
|
||||||
return this->allocate_array<T>(1);
|
return this->allocate_array<T>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T* allocate_array(const size_t count = 1)
|
T* allocate_array(const size_t count = 1)
|
||||||
{
|
{
|
||||||
return static_cast<T*>(this->allocate(count * sizeof(T)));
|
return static_cast<T*>(this->allocate(count * sizeof(T)));
|
||||||
}
|
}
|
||||||
@ -47,13 +47,13 @@ namespace utils
|
|||||||
static void* allocate(size_t length);
|
static void* allocate(size_t length);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T* allocate()
|
static T* allocate()
|
||||||
{
|
{
|
||||||
return allocate_array<T>(1);
|
return allocate_array<T>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T* allocate_array(const size_t count = 1)
|
static T* allocate_array(const size_t count = 1)
|
||||||
{
|
{
|
||||||
return static_cast<T*>(allocate(count * sizeof(T)));
|
return static_cast<T*>(allocate(count * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user