mirror of
https://github.com/diamante0018/BlackOpsPlugin.git
synced 2025-04-19 10:02:54 +00:00
133 lines
3.2 KiB
C++
133 lines
3.2 KiB
C++
#include <std_include.hpp>
|
|
#include "../loader/component_loader.hpp"
|
|
|
|
#include <utils/string.hpp>
|
|
#include <utils/nt.hpp>
|
|
|
|
#include "command.hpp"
|
|
|
|
constexpr auto CMD_MAX_NESTING = 8;
|
|
|
|
namespace command {
|
|
std::unordered_map<std::string, std::function<void(const params_sv&)>> handlers;
|
|
|
|
namespace {
|
|
void cmd_vstr_f() {
|
|
const params_sv params;
|
|
|
|
if (params.size() < 2) {
|
|
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
|
"vstr <variablename> : execute a variable command\n");
|
|
return;
|
|
}
|
|
|
|
const auto* dvar_name = params.get(1);
|
|
const auto* dvar = game::Dvar_FindVar(dvar_name);
|
|
|
|
if (dvar == nullptr) {
|
|
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER, "%s doesn't exist\n",
|
|
dvar_name);
|
|
return;
|
|
}
|
|
|
|
if (dvar->type == game::DVAR_TYPE_STRING ||
|
|
dvar->type == game::DVAR_TYPE_ENUM) {
|
|
// Adds \n automatically
|
|
execute(dvar->current.string);
|
|
} else {
|
|
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
|
"%s is not a string-based dvar\n", dvar->name);
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
void main_handler() {
|
|
params_sv params = {};
|
|
|
|
const auto command = utils::string::to_lower(params[0]);
|
|
|
|
if (const auto got = handlers.find(command); got != handlers.end()) {
|
|
got->second(params);
|
|
}
|
|
}
|
|
|
|
params_sv::params_sv() : nesting_(game::sv_cmd_args->nesting) {
|
|
assert(game::sv_cmd_args->nesting < 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;
|
|
}
|
|
|
|
void add_raw(const char* name, void (*callback)()) {
|
|
game::Cmd_AddCommandInternal(
|
|
name, callback,
|
|
utils::memory::get_allocator()->allocate<game::cmd_function_s>());
|
|
}
|
|
|
|
void add(const char* name,
|
|
const std::function<void(const params_sv&)>& callback) {
|
|
const auto command = utils::string::to_lower(name);
|
|
|
|
if (!handlers.contains(command)) {
|
|
add_raw(name, main_handler);
|
|
}
|
|
|
|
handlers[command] = callback;
|
|
}
|
|
|
|
void execute(std::string command, const bool sync) {
|
|
command += "\n";
|
|
|
|
if (sync) {
|
|
game::Cmd_ExecuteSingleCommand(game::LOCAL_CLIENT_0, 0, command.data());
|
|
} else {
|
|
game::Cbuf_AddText(game::LOCAL_CLIENT_0, command.data());
|
|
}
|
|
}
|
|
|
|
class component final : public component_interface {
|
|
public:
|
|
void post_unpack() override { add_commands_generic(); }
|
|
|
|
private:
|
|
static void add_commands_generic() {
|
|
add("properQuit",
|
|
[](const params_sv&) { utils::nt::raise_hard_exception(); });
|
|
|
|
add("echo", [](const params_sv& params) {
|
|
for (auto i = 1; i < params.size(); i++) {
|
|
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER, "%s ", params.get(i));
|
|
}
|
|
|
|
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER, "\n");
|
|
});
|
|
|
|
// Override vstr this way
|
|
auto* cmd = game::Cmd_FindCommand("vstr");
|
|
if (cmd != nullptr) {
|
|
cmd->function = cmd_vstr_f;
|
|
}
|
|
}
|
|
};
|
|
} // namespace command
|
|
|
|
REGISTER_COMPONENT(command::component)
|