t7x/src/client/component/command.cpp

198 lines
4.3 KiB
C++
Raw Normal View History

2022-12-30 13:17:36 -05:00
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "command.hpp"
#include <utils/hook.hpp>
2023-01-02 09:18:37 -05:00
#include <utils/string.hpp>
2022-12-30 13:17:36 -05:00
#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;
}
2023-01-09 10:53:51 -05:00
std::unordered_map<std::string, sv_command_param_function>& get_sv_command_map()
{
static std::unordered_map<std::string, sv_command_param_function> command_map{};
return command_map;
}
2022-12-30 13:17:36 -05:00
void execute_custom_command()
{
const params params{};
2023-01-02 09:18:37 -05:00
const auto command = utils::string::to_lower(params[0]);
2022-12-30 13:17:36 -05:00
auto& map = get_command_map();
2023-01-02 09:18:37 -05:00
const auto entry = map.find(command);
2022-12-30 13:17:36 -05:00
if (entry != map.end())
{
entry->second(params);
}
}
2023-01-09 10:53:51 -05:00
void execute_custom_sv_command()
{
const params_sv params{};
const auto command = utils::string::to_lower(params[0]);
auto& map = get_sv_command_map();
const auto entry = map.find(command);
if (entry != map.end())
{
entry->second(params);
}
}
2022-12-30 13:17:36 -05:00
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;
}
}
}
2023-01-02 09:18:37 -05:00
struct component final : generic_component
2022-12-30 13:17:36 -05:00
{
void post_unpack() override
{
// Disable whitelist
2023-01-02 09:18:37 -05:00
utils::hook::jump(game::select(0x1420EF190, 0x1404F9CD0), update_whitelist_stub);
2022-12-30 13:17:36 -05:00
}
};
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_];
}
2023-01-09 10:53:51 -05:00
params_sv::params_sv()
: nesting_(game::sv_cmd_args->nesting)
{
assert(this->nesting_ < game::CMD_MAX_NESTING);
}
int params_sv::size() const
{
return game::sv_cmd_args->argc[this->nesting_];
}
const char* params_sv::get(const int index) const
{
if (index >= this->size())
{
return "";
}
return game::sv_cmd_args->argv[this->nesting_][index];
}
std::string params_sv::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;
}
2022-12-30 13:17:36 -05:00
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;
}
2023-01-02 09:18:37 -05:00
void add(const std::string& command, command_function function)
2022-12-30 13:17:36 -05:00
{
2023-01-02 09:18:37 -05:00
add(command, [f = std::move(function)](const params&)
2022-12-30 13:17:36 -05:00
{
f();
});
}
2023-01-02 09:18:37 -05:00
void add(const std::string& command, command_param_function function)
2022-12-30 13:17:36 -05:00
{
2023-01-02 09:18:37 -05:00
auto lower_command = utils::string::to_lower(command);
2022-12-30 13:17:36 -05:00
auto& map = get_command_map();
2023-01-02 09:18:37 -05:00
const auto is_registered = map.contains(lower_command);
2022-12-30 13:17:36 -05:00
2023-01-02 09:18:37 -05:00
map[std::move(lower_command)] = std::move(function);
2022-12-30 13:17:36 -05:00
2023-01-02 09:18:37 -05:00
if (is_registered)
{
return;
2022-12-30 13:17:36 -05:00
}
2023-01-02 09:18:37 -05:00
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;
2022-12-30 13:17:36 -05:00
}
2023-01-09 10:53:51 -05:00
void add_sv(const std::string& command, sv_command_param_function function)
{
auto lower_command = utils::string::to_lower(command);
auto& map = get_sv_command_map();
const auto is_registered = map.contains(lower_command);
map[std::move(lower_command)] = std::move(function);
if (is_registered)
{
return;
}
auto& allocator = *utils::memory::get_allocator();
const auto* cmd_string = allocator.duplicate_string(command);
game::Cmd_AddCommandInternal(cmd_string, game::Cbuf_AddServerText_f, allocator.allocate<game::cmd_function_s>());
game::Cmd_AddServerCommandInternal(cmd_string, execute_custom_sv_command, allocator.allocate<game::cmd_function_s>());
}
2022-12-30 13:17:36 -05:00
}
REGISTER_COMPONENT(command::component)