Fix format or so I hope

This commit is contained in:
6arelyFuture 2022-03-22 23:44:31 +00:00
parent 8a2df0a179
commit 2ed98145da
No known key found for this signature in database
GPG Key ID: E883E2BC9657D955
14 changed files with 541 additions and 711 deletions

View File

@ -7,13 +7,11 @@
#include "key_catcher.hpp"
#include "command.hpp"
namespace cheats
{
game::dvar_t* cl_EnableCheats;
namespace cheats {
game::dvar_t* cl_EnableCheats;
__declspec(naked) void draw_red_box_stub()
{
__asm {
__declspec(naked) void draw_red_box_stub() {
__asm {
push eax
mov eax, cl_EnableCheats
cmp byte ptr [eax + 12], 1
@ -29,12 +27,11 @@ namespace cheats
draw:
push 0x43056A
retn
}
}
}
__declspec(naked) void blind_eye_check_stub()
{
__asm {
__declspec(naked) void blind_eye_check_stub() {
__asm {
push eax
mov eax, cl_EnableCheats
cmp byte ptr [eax + 12], 1
@ -54,60 +51,49 @@ namespace cheats
draw:
push 0x05AA529
retn
}
}
}
class component final : public component_interface {
public:
void post_unpack() override {
cl_EnableCheats = game::Dvar_RegisterBool(
"cl_EnableCheats", false, game::DVAR_NONE, "Enable FoF wallhack");
utils::hook::jump(0x430561, draw_red_box_stub);
utils::hook::nop(0x430566, 2);
utils::hook::jump(0x5AA524, blind_eye_check_stub);
add_cheat_commands();
}
class component final : public component_interface
{
public:
void post_unpack() override
{
cl_EnableCheats = game::Dvar_RegisterBool(
"cl_EnableCheats", false, game::DVAR_NONE, "Enable FoF wallhack");
private:
static void add_cheat_commands() {
key_catcher::on_key_press(
"Z", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
game::Dvar_SetBool(cl_EnableCheats, true);
});
utils::hook::jump(0x430561, draw_red_box_stub);
utils::hook::nop(0x430566, 2);
key_catcher::on_key_press(
"X", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
game::Dvar_SetBool(cl_EnableCheats, false);
});
utils::hook::jump(0x5AA524, blind_eye_check_stub);
key_catcher::on_key_press(
"Y", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
command::execute(
utils::string::va("cmd mr %i 2 allies", *game::serverId), true);
});
add_cheat_commands();
}
private:
static void add_cheat_commands()
{
key_catcher::on_key_press(
"Z",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
game::Dvar_SetBool(cl_EnableCheats, true);
});
key_catcher::on_key_press(
"X",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
game::Dvar_SetBool(cl_EnableCheats, false);
});
key_catcher::on_key_press(
"Y",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
command::execute(
utils::string::va("cmd mr %i 2 allies", *game::serverId), true);
});
key_catcher::on_key_press(
"8",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
command::execute(
utils::string::va("cmd mr %i -1 endround", *game::serverId),
true);
});
}
};
key_catcher::on_key_press(
"8", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
command::execute(
utils::string::va("cmd mr %i -1 endround", *game::serverId),
true);
});
}
};
} // namespace cheats
REGISTER_COMPONENT(cheats::component)

View File

@ -8,117 +8,87 @@
constexpr auto CMD_MAX_NESTING = 8;
namespace command
{
std::unordered_map<std::string, std::function<void(params&)>> handlers;
namespace command {
std::unordered_map<std::string, std::function<void(params&)>> handlers;
void main_handler()
{
params params = {};
void main_handler() {
params params = {};
const auto command = utils::string::to_lower(params[0]);
if (!handlers.contains(command))
{
handlers[command](params);
}
const auto command = utils::string::to_lower(params[0]);
if (!handlers.contains(command)) {
handlers[command](params);
}
}
params::params() : nesting_(game::cmd_args->nesting) {
assert(game::cmd_args->nesting < CMD_MAX_NESTING);
}
int params::size() const { return game::cmd_args->argc[this->nesting_]; }
const char* params::get(const int index) const {
if (index >= this->size()) {
return "";
}
params::params()
: nesting_(game::cmd_args->nesting)
{
assert(game::cmd_args->nesting < CMD_MAX_NESTING);
return game::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));
}
int params::size() const
{
return game::cmd_args->argc[this->nesting_];
return result;
}
void add_raw(const char* name, void (*callback)()) {
game::Cmd_AddCommandInternal(
name, callback,
utils::memory::get_allocator()->allocate<game::cmd_function_t>());
}
void add(const char* name, const std::function<void(const params&)>& callback) {
const auto command = utils::string::to_lower(name);
if (!handlers.contains(command)) {
add_raw(name, main_handler);
}
const char* params::get(const int index) const
{
if (index >= this->size())
{
return "";
}
handlers[command] = callback;
}
return game::cmd_args->argv[this->nesting_][index];
void add(const char* name, const std::function<void()>& callback) {
add(name, [callback](const params&) { callback(); });
}
void execute(std::string command, const bool sync) {
command += "\n";
if (sync) {
game::Cmd_ExecuteSingleCommand(game::LocalClientNum_t::LOCAL_CLIENT_0, 0,
command.data());
} else {
game::Cbuf_AddText(game::LocalClientNum_t::LOCAL_CLIENT_0, command.data());
}
}
std::string params::join(const int index) const
{
std::string result = {};
class component final : public component_interface {
public:
void post_unpack() override { add_commands_generic(); }
for (auto i = index; i < this->size(); i++)
{
if (i > index) result.append(" ");
result.append(this->get(i));
}
private:
static void add_commands_generic() {
// Will cause blue screen
add("quit_meme", utils::nt::raise_hard_exception);
return result;
add("quit", game::Com_Quit_f);
}
void add_raw(const char* name, void (*callback)())
{
game::Cmd_AddCommandInternal(
name,
callback,
utils::memory::get_allocator()->allocate<game::cmd_function_t>());
}
void add(const char* name, const std::function<void(const params&)>& callback)
{
const auto command = utils::string::to_lower(name);
if (!handlers.contains(command))
{
add_raw(name, main_handler);
}
handlers[command] = callback;
}
void add(const char* name, const std::function<void()>& callback)
{
add(name,
[callback](const params&)
{
callback();
});
}
void execute(std::string command, const bool sync)
{
command += "\n";
if (sync)
{
game::Cmd_ExecuteSingleCommand(
game::LocalClientNum_t::LOCAL_CLIENT_0, 0, command.data());
}
else
{
game::Cbuf_AddText(game::LocalClientNum_t::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()
{
// Will cause blue screen
add("quit_meme", utils::nt::raise_hard_exception);
add("quit", game::Com_Quit_f);
}
};
};
} // namespace command
REGISTER_COMPONENT(command::component)

View File

@ -1,29 +1,23 @@
#pragma once
namespace command
{
class params
{
public:
params();
namespace command {
class params {
public:
params();
[[nodiscard]] int size() const;
[[nodiscard]] const char* get(int index) const;
[[nodiscard]] std::string join(int index) const;
[[nodiscard]] int size() const;
[[nodiscard]] const char* get(int index) const;
[[nodiscard]] std::string join(int index) const;
const char* operator[](const int index) const
{
return this->get(index);
}
const char* operator[](const int index) const { return this->get(index); }
private:
int nesting_;
};
private:
int nesting_;
};
void add_raw(const char* name, void (*callback)());
void add(const char* name,
const std::function<void(const params&)>& callback);
void add(const char* name, const std::function<void()>& callback);
void add_raw(const char* name, void (*callback)());
void add(const char* name, const std::function<void(const params&)>& callback);
void add(const char* name, const std::function<void()>& callback);
void execute(std::string command, bool sync = false);
void execute(std::string command, bool sync = false);
} // namespace command

View File

@ -2,54 +2,42 @@
#include <loader/component_loader.hpp>
namespace console
{
namespace
{
std::thread thread;
std::thread::id async_thread_id;
namespace console {
namespace {
std::thread thread;
std::thread::id async_thread_id;
LRESULT __stdcall sys_start_console(HWND, UINT, WPARAM, LPARAM)
{
game::Sys_ShowConsole();
return 0;
}
LRESULT __stdcall sys_start_console(HWND, UINT, WPARAM, LPARAM) {
game::Sys_ShowConsole();
return 0;
}
void console_unlock()
{
const auto callback =
SetWindowLongA(*game::g_wv_hWnd,
GWL_WNDPROC,
reinterpret_cast<LONG>(sys_start_console));
void console_unlock() {
const auto callback = SetWindowLongA(
*game::g_wv_hWnd, GWL_WNDPROC, reinterpret_cast<LONG>(sys_start_console));
SendMessageA(*game::g_wv_hWnd, WM_QUIT, 0, 0);
SetWindowLongA(*game::g_wv_hWnd, GWL_WNDPROC, callback);
}
SendMessageA(*game::g_wv_hWnd, WM_QUIT, 0, 0);
SetWindowLongA(*game::g_wv_hWnd, GWL_WNDPROC, callback);
}
void show_console()
{
if (*game::s_wcd_hWnd)
{
ShowWindow(*game::s_wcd_hWnd, SW_SHOW);
}
}
} // namespace
void show_console() {
if (*game::s_wcd_hWnd) {
ShowWindow(*game::s_wcd_hWnd, SW_SHOW);
}
}
} // namespace
class component final : public component_interface
{
public:
void post_unpack() override
{
thread = std::thread(
[]()
{
console_unlock();
show_console();
});
class component final : public component_interface {
public:
void post_unpack() override {
thread = std::thread([]() {
console_unlock();
show_console();
});
async_thread_id = thread.get_id();
}
};
async_thread_id = thread.get_id();
}
};
} // namespace console
REGISTER_COMPONENT(console::component)

View File

@ -3,18 +3,15 @@
#include <utils/hook.hpp>
namespace dvar_patches
{
void dvar_set_from_string_by_name_stub(const char*, const char*) {}
namespace dvar_patches {
void dvar_set_from_string_by_name_stub(const char*, const char*) {}
class component final : public component_interface
{
public:
void post_unpack() override
{
utils::hook::call(0x59C0EF, dvar_set_from_string_by_name_stub);
}
};
class component final : public component_interface {
public:
void post_unpack() override {
utils::hook::call(0x59C0EF, dvar_set_from_string_by_name_stub);
}
};
} // namespace dvar_patches
REGISTER_COMPONENT(dvar_patches::component)

View File

@ -6,120 +6,103 @@
#include "command.hpp"
#include "key_catcher.hpp"
namespace exploit
{
game::dvar_t* cl_exploit;
namespace exploit {
game::dvar_t* cl_exploit;
/*
* void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3)
* A brief description of data: the first few bytes contain information from
* clientConnection_t structure Offset 0: ServerID Size : 1 Offset 1:
* serverMessageSequence Size: 4 Offset 5: serverCommandSequence Size: 4 One
* clean way of sending invalid data to the server is to hook the functions
* that write the info to the packet Credit:
* https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable
*/
/*
* void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3)
* A brief description of data: the first few bytes contain information from
* clientConnection_t structure Offset 0: ServerID Size : 1 Offset 1:
* serverMessageSequence Size: 4 Offset 5: serverCommandSequence Size: 4 One
* clean way of sending invalid data to the server is to hook the functions
* that write the info to the packet Credit:
* https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable
*/
void write_message_sequence(game::msg_t* msg, int data)
{
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int))
{
msg->overflowed = TRUE;
return;
}
if (cl_exploit->current.enabled) data = (data & 0xFFFFFF00) | 0xAAu;
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
*dest = data;
msg->cursize += sizeof(int);
void write_message_sequence(game::msg_t* msg, int data) {
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int)) {
msg->overflowed = TRUE;
return;
}
void write_command_sequence(game::msg_t* msg, int data)
{
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int))
{
msg->overflowed = TRUE;
return;
}
if (cl_exploit->current.enabled)
data = (data & 0xFFFFFF00) | 0xAAu;
if (cl_exploit->current.enabled) data = (data & 0x00FFFFFF) | (0x80u << 24);
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
*dest = data;
msg->cursize += sizeof(int);
}
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
*dest = data;
msg->cursize += sizeof(int);
void write_command_sequence(game::msg_t* msg, int data) {
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int)) {
msg->overflowed = TRUE;
return;
}
class component final : public component_interface
{
public:
void post_unpack() override
{
cl_exploit = game::Dvar_RegisterBool(
"cl_exploit", false, game::DVAR_NONE, "Enable server freezer");
if (cl_exploit->current.enabled)
data = (data & 0x00FFFFFF) | (0x80u << 24);
add_exploit_commands();
add_key_hooks();
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
*dest = data;
msg->cursize += sizeof(int);
}
utils::hook::call(0x420B76, write_message_sequence);
utils::hook::call(0x420B86, write_command_sequence);
}
class component final : public component_interface {
public:
void post_unpack() override {
cl_exploit = game::Dvar_RegisterBool("cl_exploit", false, game::DVAR_NONE,
"Enable server freezer");
private:
static void add_key_hooks()
{
key_catcher::on_key_press(
"O",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
command::execute("exploit");
});
add_exploit_commands();
add_key_hooks();
key_catcher::on_key_press(
"L",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
command::execute("undo_exploit");
});
utils::hook::call(0x420B76, write_message_sequence);
utils::hook::call(0x420B86, write_command_sequence);
}
key_catcher::on_key_press(
"K",
[]([[maybe_unused]] const game::LocalClientNum_t& local_client)
{
command::execute("disconnect");
});
}
private:
static void add_key_hooks() {
key_catcher::on_key_press(
"O", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
command::execute("exploit");
});
static void add_exploit_commands()
{
command::add("exploit",
[]([[maybe_unused]] const command::params& params)
{
game::Dvar_SetBool(cl_exploit, true);
});
key_catcher::on_key_press(
"L", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
command::execute("undo_exploit");
});
command::add("undo_exploit",
[]([[maybe_unused]] const command::params& params)
{
game::Dvar_SetBool(cl_exploit, false);
});
key_catcher::on_key_press(
"K", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
command::execute("disconnect");
});
}
command::add(
"send_command",
[]([[maybe_unused]] const command::params& params)
{
if (params.size() < 2) return;
static void add_exploit_commands() {
command::add("exploit", []([[maybe_unused]] const command::params& params) {
game::Dvar_SetBool(cl_exploit, true);
});
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING)
return;
command::add("undo_exploit",
[]([[maybe_unused]] const command::params& params) {
game::Dvar_SetBool(cl_exploit, false);
});
const auto cmd = std::format("queryserverinfo ;{}", params.join(1));
game::NET_OutOfBandPrint(game::NS_SERVER,
game::localClientConnection->serverAddress,
cmd.data());
});
}
};
command::add(
"send_command", []([[maybe_unused]] const command::params& params) {
if (params.size() < 2)
return;
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING)
return;
const auto cmd = std::format("queryserverinfo ;{}", params.join(1));
game::NET_OutOfBandPrint(game::NS_SERVER,
game::localClientConnection->serverAddress,
cmd.data());
});
}
};
} // namespace exploit
REGISTER_COMPONENT(exploit::component)

View File

@ -5,63 +5,49 @@
#include "key_catcher.hpp"
namespace key_catcher
{
utils::hook::detour cl_key_event_hook;
namespace key_catcher {
utils::hook::detour cl_key_event_hook;
namespace
{
std::unordered_map<std::string, key_catcher::callback>& get_key_callbacks()
{
static std::unordered_map<std::string, key_catcher::callback>
key_callbacks{};
return key_callbacks;
namespace {
std::unordered_map<std::string, key_catcher::callback>& get_key_callbacks() {
static std::unordered_map<std::string, key_catcher::callback> key_callbacks{};
return key_callbacks;
}
void handle_key_event(game::LocalClientNum_t local_client, int key_id) {
const auto result = VkKeyScanA(static_cast<CHAR>(key_id));
const auto vk_key = LOBYTE(result);
const auto& callbacks = get_key_callbacks();
for (auto const& [key, value] : callbacks) {
const auto game_vk_key = game::Key_StringToKeynum(key.data());
if (static_cast<BYTE>(game_vk_key) == vk_key) {
value(local_client);
return;
}
}
}
} // namespace
void handle_key_event(game::LocalClientNum_t local_client, int key_id)
{
const auto result = VkKeyScanA(static_cast<CHAR>(key_id));
const auto vk_key = LOBYTE(result);
const auto& callbacks = get_key_callbacks();
void on_key_press(const std::string& command, const callback& callback) {
get_key_callbacks()[command] = callback;
}
for (auto const& [key, value] : callbacks)
{
const auto game_vk_key = game::Key_StringToKeynum(key.data());
if (static_cast<BYTE>(game_vk_key) == vk_key)
{
value(local_client);
return;
}
}
}
} // namespace
void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id,
int a3) {
handle_key_event(local_client, key_id);
void on_key_press(const std::string& command, const callback& callback)
{
get_key_callbacks()[command] = callback;
cl_key_event_hook.invoke<void>(local_client, key_id, a3);
}
class component final : public component_interface {
public:
void post_unpack() override {
cl_key_event_hook.create(0x4CD840, &cl_key_event_stub);
}
void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id,
int a3)
{
handle_key_event(local_client, key_id);
cl_key_event_hook.invoke<void>(local_client, key_id, a3);
}
class component final : public component_interface
{
public:
void post_unpack() override
{
cl_key_event_hook.create(0x4CD840, &cl_key_event_stub);
}
void pre_destroy() override
{
cl_key_event_hook.clear();
}
};
void pre_destroy() override { cl_key_event_hook.clear(); }
};
} // namespace key_catcher
REGISTER_COMPONENT(key_catcher::component)

View File

@ -1,8 +1,7 @@
#pragma once
namespace key_catcher
{
using callback = std::function<void(game::LocalClientNum_t& local_client)>;
namespace key_catcher {
using callback = std::function<void(game::LocalClientNum_t& local_client)>;
void on_key_press(const std::string& command, const callback& callback);
void on_key_press(const std::string& command, const callback& callback);
} // namespace key_catcher

View File

@ -7,77 +7,64 @@
#include "network.hpp"
#include "command.hpp"
namespace network
{
namespace
{
std::unordered_map<std::string, network::callback>& get_callbacks()
{
static std::unordered_map<std::string, network::callback>
network_callbacks{};
return network_callbacks;
}
namespace network {
namespace {
std::unordered_map<std::string, network::callback>& get_callbacks() {
static std::unordered_map<std::string, network::callback> network_callbacks{};
return network_callbacks;
}
bool handle_command(game::netadr_s* address, const char* command,
game::msg_t* msg)
{
const auto cmd_string = utils::string::to_lower(command);
auto& callbacks = get_callbacks();
const auto handler = callbacks.find(cmd_string);
const auto offset = cmd_string.size() + 5;
bool handle_command(game::netadr_s* address, const char* command,
game::msg_t* msg) {
const auto cmd_string = utils::string::to_lower(command);
auto& callbacks = get_callbacks();
const auto handler = callbacks.find(cmd_string);
const auto offset = cmd_string.size() + 5;
if (static_cast<unsigned int>(msg->cursize) < offset ||
handler == callbacks.end())
{
return false;
}
const std::string_view data(reinterpret_cast<char*>(msg->data) + offset,
msg->cursize - offset);
handler->second(*address, data);
return true;
}
} // namespace
int packet_interception_handler(game::netadr_s* from, const char* command,
game::msg_t* message)
{
if (!handle_command(from, command, message))
{
return reinterpret_cast<int (*)(
game::netadr_s*, const char*, game::msg_t*)>(0x525730)(
from, command, message);
}
return TRUE;
if (static_cast<unsigned int>(msg->cursize) < offset ||
handler == callbacks.end()) {
return false;
}
void on_packet(const std::string& command, const callback& callback)
{
get_callbacks()[utils::string::to_lower(command)] = callback;
const std::string_view data(reinterpret_cast<char*>(msg->data) + offset,
msg->cursize - offset);
handler->second(*address, data);
return true;
}
} // namespace
int packet_interception_handler(game::netadr_s* from, const char* command,
game::msg_t* message) {
if (!handle_command(from, command, message)) {
return reinterpret_cast<int (*)(game::netadr_s*, const char*,
game::msg_t*)>(0x525730)(from, command,
message);
}
class component final : public component_interface
{
public:
void post_unpack() override
{
add_network_commands();
return TRUE;
}
utils::hook::call(0x5B27E1, packet_interception_handler);
}
void on_packet(const std::string& command, const callback& callback) {
get_callbacks()[utils::string::to_lower(command)] = callback;
}
private:
static void add_network_commands()
{
on_packet("naughty_reply",
[](const game::netadr_s&, const std::string_view&)
{
command::execute("quit_meme");
});
}
};
class component final : public component_interface {
public:
void post_unpack() override {
add_network_commands();
utils::hook::call(0x5B27E1, packet_interception_handler);
}
private:
static void add_network_commands() {
on_packet("naughty_reply",
[](const game::netadr_s&, const std::string_view&) {
command::execute("quit_meme");
});
}
};
} // namespace network
REGISTER_COMPONENT(network::component)

View File

@ -1,9 +1,8 @@
#pragma once
namespace network
{
using callback =
std::function<void(const game::netadr_s&, const std::string_view&)>;
namespace network {
using callback =
std::function<void(const game::netadr_s&, const std::string_view&)>;
void on_packet(const std::string& command, const callback& callback);
void on_packet(const std::string& command, const callback& callback);
} // namespace network

View File

@ -3,32 +3,26 @@
#include <utils/hook.hpp>
namespace remove_hooks
{
class component final : public component_interface
{
public:
void post_unpack() override
{
remove_tekno_hooks();
}
namespace remove_hooks {
class component final : public component_interface {
public:
void post_unpack() override { remove_tekno_hooks(); }
private:
static void remove_tekno_hooks()
{
utils::hook::set<BYTE>(0x4E3D42, 0xE8);
utils::hook::set<BYTE>(0x4E3D43, 0xA9);
utils::hook::set<BYTE>(0x4E3D44, 0x25);
utils::hook::set<BYTE>(0x4E3D45, 0xFE);
utils::hook::set<BYTE>(0x4E3D46, 0xFF);
private:
static void remove_tekno_hooks() {
utils::hook::set<BYTE>(0x4E3D42, 0xE8);
utils::hook::set<BYTE>(0x4E3D43, 0xA9);
utils::hook::set<BYTE>(0x4E3D44, 0x25);
utils::hook::set<BYTE>(0x4E3D45, 0xFE);
utils::hook::set<BYTE>(0x4E3D46, 0xFF);
utils::hook::set<BYTE>(0x6EA960, 0x55);
utils::hook::set<BYTE>(0x6EA961, 0x8B);
utils::hook::set<BYTE>(0x6EA962, 0xEC);
utils::hook::set<BYTE>(0x6EA963, 0x81);
utils::hook::set<BYTE>(0x6EA964, 0xEC);
}
};
utils::hook::set<BYTE>(0x6EA960, 0x55);
utils::hook::set<BYTE>(0x6EA961, 0x8B);
utils::hook::set<BYTE>(0x6EA962, 0xEC);
utils::hook::set<BYTE>(0x6EA963, 0x81);
utils::hook::set<BYTE>(0x6EA964, 0xEC);
}
};
} // namespace remove_hooks
REGISTER_COMPONENT(remove_hooks::component)

View File

@ -6,181 +6,139 @@
#include "scheduler.hpp"
namespace scheduler
{
std::thread::id async_thread_id;
namespace scheduler {
std::thread::id async_thread_id;
namespace
{
struct task
{
std::function<bool()> handler{};
std::chrono::milliseconds interval{};
std::chrono::high_resolution_clock::time_point last_call{};
};
namespace {
struct task {
std::function<bool()> handler{};
std::chrono::milliseconds interval{};
std::chrono::high_resolution_clock::time_point last_call{};
};
using task_list = std::vector<task>;
using task_list = std::vector<task>;
class task_pipeline
{
public:
void add(task&& task)
{
new_callbacks_.access(
[&task, this](task_list& tasks)
{
tasks.emplace_back(std::move(task));
});
}
void clear()
{
callbacks_.access(
[&](task_list& tasks)
{
this->merge_callbacks();
tasks.clear();
});
}
void execute()
{
callbacks_.access(
[&](task_list& tasks)
{
this->merge_callbacks();
for (auto i = tasks.begin(); i != tasks.end();)
{
const auto now = std::chrono::high_resolution_clock::now();
const auto diff = now - i->last_call;
if (diff < i->interval)
{
++i;
continue;
}
i->last_call = now;
const auto res = i->handler();
if (res == cond_end)
{
i = tasks.erase(i);
}
else
{
++i;
}
}
});
}
private:
utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
void merge_callbacks()
{
callbacks_.access(
[&](task_list& tasks)
{
new_callbacks_.access(
[&](task_list& new_tasks)
{
tasks.insert(tasks.end(),
std::move_iterator<task_list::iterator>(
new_tasks.begin()),
std::move_iterator<task_list::iterator>(
new_tasks.end()));
new_tasks = {};
});
});
}
};
std::thread thread;
task_pipeline pipelines[pipeline::count];
void execute(const pipeline type)
{
assert(type >= 0 && type < pipeline::count);
pipelines[type].execute();
}
void cl_frame_stub(game::LocalClientNum_t local)
{
reinterpret_cast<void (*)(game::LocalClientNum_t)>(0x41C9B0)(local);
execute(pipeline::client);
}
} // namespace
void clear_tasks(const pipeline type)
{
return pipelines[type].clear();
class task_pipeline {
public:
void add(task&& task) {
new_callbacks_.access([&task, this](task_list& tasks) {
tasks.emplace_back(std::move(task));
});
}
void schedule(const std::function<bool()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
assert(type >= 0 && type < pipeline::count);
task task;
task.handler = callback;
task.interval = delay;
task.last_call = std::chrono::high_resolution_clock::now();
pipelines[type].add(std::move(task));
void clear() {
callbacks_.access([&](task_list& tasks) {
this->merge_callbacks();
tasks.clear();
});
}
void loop(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
schedule(
[callback]()
{
callback();
return cond_continue;
},
type,
delay);
void execute() {
callbacks_.access([&](task_list& tasks) {
this->merge_callbacks();
for (auto i = tasks.begin(); i != tasks.end();) {
const auto now = std::chrono::high_resolution_clock::now();
const auto diff = now - i->last_call;
if (diff < i->interval) {
++i;
continue;
}
i->last_call = now;
const auto res = i->handler();
if (res == cond_end) {
i = tasks.erase(i);
} else {
++i;
}
}
});
}
void once(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
schedule(
[callback]()
{
callback();
return cond_end;
},
type,
delay);
private:
utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
void merge_callbacks() {
callbacks_.access([&](task_list& tasks) {
new_callbacks_.access([&](task_list& new_tasks) {
tasks.insert(tasks.end(),
std::move_iterator<task_list::iterator>(new_tasks.begin()),
std::move_iterator<task_list::iterator>(new_tasks.end()));
new_tasks = {};
});
});
}
};
unsigned int thread_id;
std::thread thread;
task_pipeline pipelines[pipeline::count];
class component final : public component_interface
{
public:
void post_unpack() override
{
thread = std::thread(
[]()
{
while (true)
{
execute(pipeline::async);
std::this_thread::sleep_for(10ms);
}
});
void execute(const pipeline type) {
assert(type >= 0 && type < pipeline::count);
pipelines[type].execute();
}
async_thread_id = thread.get_id();
void cl_frame_stub(game::LocalClientNum_t local) {
reinterpret_cast<void (*)(game::LocalClientNum_t)>(0x41C9B0)(local);
execute(pipeline::client);
}
} // namespace
utils::hook::call(0x4E4A0D, cl_frame_stub);
}
};
void clear_tasks(const pipeline type) { return pipelines[type].clear(); }
void schedule(const std::function<bool()>& callback, const pipeline type,
const std::chrono::milliseconds delay) {
assert(type >= 0 && type < pipeline::count);
task task;
task.handler = callback;
task.interval = delay;
task.last_call = std::chrono::high_resolution_clock::now();
pipelines[type].add(std::move(task));
}
void loop(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay) {
schedule(
[callback]() {
callback();
return cond_continue;
},
type, delay);
}
void once(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay) {
schedule(
[callback]() {
callback();
return cond_end;
},
type, delay);
}
unsigned int thread_id;
class component final : public component_interface {
public:
void post_unpack() override {
thread = std::thread([]() {
while (true) {
execute(pipeline::async);
std::this_thread::sleep_for(10ms);
}
});
async_thread_id = thread.get_id();
utils::hook::call(0x4E4A0D, cl_frame_stub);
}
};
} // namespace scheduler
REGISTER_COMPONENT(scheduler::component)

View File

@ -1,28 +1,26 @@
#pragma once
namespace scheduler
{
extern std::thread::id async_thread_id;
namespace scheduler {
extern std::thread::id async_thread_id;
enum pipeline
{
client,
async,
count,
};
enum pipeline {
client,
async,
count,
};
static const bool cond_continue = false;
static const bool cond_end = true;
static const bool cond_continue = false;
static const bool cond_end = true;
void clear_tasks(const pipeline type);
void clear_tasks(const pipeline type);
void schedule(const std::function<bool()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
void loop(const std::function<void()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
void once(const std::function<void()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
void schedule(const std::function<bool()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
void loop(const std::function<void()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
void once(const std::function<void()>& callback,
pipeline type = pipeline::client,
std::chrono::milliseconds delay = 0ms);
} // namespace scheduler

View File

@ -8,46 +8,44 @@
#include "scheduler.hpp"
namespace user_info
{
namespace
namespace user_info {
namespace {
int a1 = 0;
void cl_check_user_info(int _a1, const int force) {
a1 = _a1;
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING)
return;
if (game::cl_paused->current.enabled && !force)
return;
const std::string info_string = game::Dvar_InfoString(_a1, 0x200);
utils::info_string info(info_string);
const auto color_code = std::rand() % 10;
char name[16];
const auto numbers = std::to_string(std::rand() % 10000);
_snprintf_s(name, sizeof(name), _TRUNCATE, "^%d%s", color_code,
numbers.data());
info.set("name", name);
info.set("ec_usingTag", "1");
info.set("ec_TagText", utils::string::va("^%dGG", color_code));
const auto big_title = std::to_string(std::rand() % 512);
info.set("ec_TitleBg", big_title);
game::CL_AddReliableCommand(
_a1, utils::string::va("userinfo \"%s\"", info.build().data()));
}
__declspec(naked) void cl_check_user_info_stub() {
__asm
{
int a1 = 0;
void cl_check_user_info(int _a1, const int force)
{
a1 = _a1;
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING) return;
if (game::cl_paused->current.enabled && !force) return;
const std::string info_string = game::Dvar_InfoString(_a1, 0x200);
utils::info_string info(info_string);
const auto color_code = std::rand() % 10;
char name[16];
const auto numbers = std::to_string(std::rand() % 10000);
_snprintf_s(
name, sizeof(name), _TRUNCATE, "^%d%s", color_code, numbers.data());
info.set("name", name);
info.set("ec_usingTag", "1");
info.set("ec_TagText", utils::string::va("^%dGG", color_code));
const auto big_title = std::to_string(std::rand() % 512);
info.set("ec_TitleBg", big_title);
game::CL_AddReliableCommand(
_a1, utils::string::va("userinfo \"%s\"", info.build().data()));
}
__declspec(naked) void cl_check_user_info_stub()
{
__asm
{
pushad
push 0
@ -57,26 +55,19 @@ namespace user_info
popad
ret
}
}
} // namespace
}
}
} // namespace
class component final : public component_interface
{
public:
void post_unpack() override
{
utils::hook::call(0x41CA53, cl_check_user_info_stub);
class component final : public component_interface {
public:
void post_unpack() override {
utils::hook::call(0x41CA53, cl_check_user_info_stub);
scheduler::loop(
[]
{
cl_check_user_info(a1, TRUE);
},
scheduler::pipeline::client,
4s);
}
};
scheduler::loop([] { cl_check_user_info(a1, TRUE); },
scheduler::pipeline::client, 4s);
}
};
} // namespace user_info
REGISTER_COMPONENT(user_info::component)