mirror of
https://github.com/diamante0018/BlackOpsPlugin.git
synced 2025-04-19 18:12:54 +00:00
fix hook compatability with plutonium
This commit is contained in:
parent
798e0e780c
commit
314a3424ea
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,9 +4,6 @@
|
||||
[submodule "deps/minhook"]
|
||||
path = deps/minhook
|
||||
url = https://github.com/TsudaKageyu/minhook.git
|
||||
[submodule "deps/rapidjson"]
|
||||
path = deps/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson.git
|
||||
[submodule "deps/asmjit"]
|
||||
path = deps/asmjit
|
||||
url = https://github.com/asmjit/asmjit.git
|
||||
|
19
deps/premake/rapidjson.lua
vendored
19
deps/premake/rapidjson.lua
vendored
@ -1,19 +0,0 @@
|
||||
rapidjson = {
|
||||
source = path.join(dependencies.basePath, "rapidjson"),
|
||||
}
|
||||
|
||||
function rapidjson.import()
|
||||
rapidjson.includes()
|
||||
end
|
||||
|
||||
function rapidjson.includes()
|
||||
includedirs {
|
||||
path.join(rapidjson.source, "include"),
|
||||
}
|
||||
end
|
||||
|
||||
function rapidjson.project()
|
||||
|
||||
end
|
||||
|
||||
table.insert(dependencies, rapidjson)
|
1
deps/rapidjson
vendored
1
deps/rapidjson
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d
|
@ -1,46 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace ban {
|
||||
namespace {
|
||||
const game::dvar_t* sv_discord = nullptr;
|
||||
const game::dvar_t* sv_clanWebsite = nullptr;
|
||||
|
||||
bool out_of_band_print_hk(game::netsrc_t src, game::netadr_s to,
|
||||
const char* msg) {
|
||||
// Proof of concept patch. Please ignore
|
||||
if (msg != "error\nPATCH_BANNED_FROM_SERVER"s) {
|
||||
return game::NET_OutOfBandPrint(src, to, msg);
|
||||
}
|
||||
|
||||
const auto error_msg =
|
||||
std::format("error\nPermanently banned\nDiscord: {}\nWebsite: {}",
|
||||
sv_discord->current.string, sv_clanWebsite->current.string);
|
||||
|
||||
return game::NET_OutOfBandPrint(src, to, error_msg.data());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
if (game::current == game::gamemode::zombies)
|
||||
return;
|
||||
|
||||
sv_discord = game::Dvar_RegisterString(
|
||||
"sv_discord", "https://www.discord.gg/", game::DVAR_ARCHIVE,
|
||||
"Discord invitation link");
|
||||
|
||||
sv_clanWebsite =
|
||||
game::Dvar_RegisterString("sv_clanWebsite", "https://www.google.com/",
|
||||
game::DVAR_ARCHIVE, "Website link");
|
||||
|
||||
utils::hook::call(0x48B7E2, out_of_band_print_hk);
|
||||
}
|
||||
};
|
||||
} // namespace ban
|
||||
|
||||
REGISTER_COMPONENT(ban::component)
|
@ -1,98 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace bots {
|
||||
namespace {
|
||||
using bot_entry = std::pair<std::string, std::string>;
|
||||
std::vector<bot_entry> bot_names;
|
||||
utils::hook::detour sv_bot_name_random_hook;
|
||||
|
||||
// Json file is expected to contain a key for the bot's name. Value should be a
|
||||
// string for the clantag
|
||||
void load_bot_data() {
|
||||
if (!utils::io::file_exists("bots/bots.json")) {
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER, "bots.json was not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document obj;
|
||||
const rapidjson::ParseResult result =
|
||||
obj.Parse(utils::io::read_file("bots/bots.json").data());
|
||||
|
||||
if (!result || !obj.IsObject()) {
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER,
|
||||
"Failed to parse ban file. Empty?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (rapidjson::Value::ConstMemberIterator itr = obj.MemberBegin();
|
||||
itr != obj.MemberEnd(); ++itr) {
|
||||
if (itr->value.GetType() == rapidjson::Type::kStringType) {
|
||||
bot_names.emplace_back(
|
||||
std::make_pair(itr->name.GetString(), itr->value.GetString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* sv_bot_name_random_stub() {
|
||||
static auto loaded = false;
|
||||
|
||||
if (bot_names.empty() && !loaded) {
|
||||
load_bot_data();
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
if (!bot_names.empty()) {
|
||||
static std::size_t bot_id = 0;
|
||||
bot_id %= bot_names.size();
|
||||
const auto& entry = bot_names.at(bot_id++);
|
||||
return entry.first.data();
|
||||
}
|
||||
|
||||
return sv_bot_name_random_hook.invoke<const char*>();
|
||||
}
|
||||
|
||||
int build_connect_string(char* buf, const char* connect_string,
|
||||
const char* name, const char* bd_online_user_id,
|
||||
int protocol, int qport) {
|
||||
// Default
|
||||
auto clan_tag = "3arc"s;
|
||||
for (const auto& [bot_name, tag] : bot_names) {
|
||||
if (bot_name == name) {
|
||||
// Found their clantag
|
||||
clan_tag = tag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _snprintf_s(buf, 0x400, _TRUNCATE, connect_string, name,
|
||||
clan_tag.data(), bd_online_user_id, protocol, qport);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
if (game::current == game::gamemode::zombies)
|
||||
return;
|
||||
|
||||
// Add custom clantag
|
||||
utils::hook::set<const char*>(
|
||||
0x6B6294,
|
||||
"connect "
|
||||
"\"\\cg_predictItems\\1\\cl_punkbuster\\0\\cl_"
|
||||
"anonymous\\0\\color\\4\\head\\default\\"
|
||||
" model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\clanAbbrev\\%"
|
||||
"s\\bdOnlineUserID\\%s\\protocol\\%d\\qport\\%d\"");
|
||||
|
||||
sv_bot_name_random_hook.create(0x49ED80, &sv_bot_name_random_stub);
|
||||
utils::hook::call(0x6B6299, build_connect_string);
|
||||
}
|
||||
};
|
||||
} // namespace bots
|
||||
|
||||
REGISTER_COMPONENT(bots::component)
|
@ -1,41 +1,36 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
#include "command.hpp"
|
||||
|
||||
namespace chat {
|
||||
namespace {
|
||||
std::mutex chat_mutex;
|
||||
std::unordered_set<std::uint64_t> mute_list{};
|
||||
utils::hook::detour client_command_hook;
|
||||
|
||||
using client_list = std::unordered_set<std::uint64_t>;
|
||||
utils::concurrency::container<client_list> mute_list;
|
||||
|
||||
void mute_player(const game::client_s* client) {
|
||||
std::unique_lock<std::mutex> _(chat_mutex);
|
||||
|
||||
if (mute_list.contains(client->xuid)) {
|
||||
game::SV_GameSendServerCommand(
|
||||
-1, game::SV_CMD_CAN_IGNORE,
|
||||
utils::string::va("%c \"%s is already muted\"", 0x65, client->name));
|
||||
return;
|
||||
}
|
||||
|
||||
mute_list.insert(client->xuid);
|
||||
const auto xuid = client->xuid;
|
||||
mute_list.access([&](client_list& clients) { clients.insert(xuid); });
|
||||
}
|
||||
|
||||
void unmute_player(const game::client_s* client) {
|
||||
std::unique_lock<std::mutex> _(chat_mutex);
|
||||
|
||||
mute_list.erase(client->xuid);
|
||||
const auto xuid = client->xuid;
|
||||
mute_list.access([&](client_list& clients) { clients.erase(xuid); });
|
||||
|
||||
game::SV_GameSendServerCommand(
|
||||
client->gentity->entnum, game::SV_CMD_CAN_IGNORE,
|
||||
utils::string::va("%c \"You were unmuted\"", 0x65));
|
||||
}
|
||||
|
||||
void client_command(int client_number) {
|
||||
char buf[1024] = {0};
|
||||
void client_command_stub(const int client_number) {
|
||||
char buf[1024]{};
|
||||
|
||||
if (game::g_entities[client_number].client == nullptr) {
|
||||
// Not in game
|
||||
@ -44,30 +39,36 @@ void client_command(int client_number) {
|
||||
|
||||
game::SV_Cmd_ArgvBuffer(0, buf, sizeof(buf));
|
||||
|
||||
std::unique_lock<std::mutex> _(chat_mutex);
|
||||
if (utils::string::starts_with(buf, "say") &&
|
||||
mute_list.contains(game::svs_clients[client_number].xuid)) {
|
||||
game::SV_GameSendServerCommand(
|
||||
client_number, game::SV_CMD_CAN_IGNORE,
|
||||
utils::string::va("%c \"You are muted\"", 0x65));
|
||||
return;
|
||||
if (utils::string::starts_with(buf, "say")) {
|
||||
const auto is_muted =
|
||||
mute_list.access<bool>([&](const client_list& clients) {
|
||||
return clients.contains(game::svs_clients[client_number].xuid);
|
||||
});
|
||||
|
||||
if (is_muted) {
|
||||
game::SV_GameSendServerCommand(
|
||||
client_number, game::SV_CMD_CAN_IGNORE,
|
||||
utils::string::va("%c \"You are muted\"", 0x65));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
game::ClientCommand(client_number);
|
||||
client_command_hook.invoke<void>(client_number);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
utils::hook::call(SELECT_VALUE(0x58DA1C, 0x4FB3BD), client_command);
|
||||
client_command_hook.create(SELECT_VALUE(0x63DB70, 0x4AF770),
|
||||
client_command_stub);
|
||||
|
||||
add_chat_commands();
|
||||
}
|
||||
|
||||
private:
|
||||
static void add_chat_commands() {
|
||||
command::add("sayAs", [](const command::params& params) {
|
||||
command::add("sayAs", [](const command::params_sv& params) {
|
||||
if (params.size() < 3) {
|
||||
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
||||
"Usage: sayAs <client number> <message>\n");
|
||||
@ -89,7 +90,7 @@ private:
|
||||
game::G_Say(gentity, nullptr, 0, message.data());
|
||||
});
|
||||
|
||||
command::add("mutePlayer", [](const command::params& params) {
|
||||
command::add("mutePlayer", [](const command::params_sv& params) {
|
||||
if (params.size() < 2) {
|
||||
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
||||
"Usage: mutePlayer <client number>\n");
|
||||
@ -109,7 +110,7 @@ private:
|
||||
mute_player(client);
|
||||
});
|
||||
|
||||
command::add("unmutePlayer", [](const command::params& params) {
|
||||
command::add("unmutePlayer", [](const command::params_sv& params) {
|
||||
if (params.size() < 2) {
|
||||
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
||||
"Usage: unmutePlayer <client number>\n");
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
@ -10,11 +9,11 @@
|
||||
constexpr auto CMD_MAX_NESTING = 8;
|
||||
|
||||
namespace command {
|
||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||
std::unordered_map<std::string, std::function<void(const params_sv&)>> handlers;
|
||||
|
||||
namespace {
|
||||
void cmd_vstr_f() {
|
||||
const params params;
|
||||
const params_sv params;
|
||||
|
||||
if (params.size() < 2) {
|
||||
game::Com_Printf(game::CON_CHANNEL_DONT_FILTER,
|
||||
@ -43,7 +42,7 @@ void cmd_vstr_f() {
|
||||
} // namespace
|
||||
|
||||
void main_handler() {
|
||||
params params = {};
|
||||
params_sv params = {};
|
||||
|
||||
const auto command = utils::string::to_lower(params[0]);
|
||||
|
||||
@ -52,13 +51,13 @@ void main_handler() {
|
||||
}
|
||||
}
|
||||
|
||||
params::params() : nesting_(game::sv_cmd_args->nesting) {
|
||||
params_sv::params_sv() : nesting_(game::sv_cmd_args->nesting) {
|
||||
assert(game::sv_cmd_args->nesting < CMD_MAX_NESTING);
|
||||
}
|
||||
|
||||
int params::size() const { return game::sv_cmd_args->argc[this->nesting_]; }
|
||||
int params_sv::size() const { return game::sv_cmd_args->argc[this->nesting_]; }
|
||||
|
||||
const char* params::get(const int index) const {
|
||||
const char* params_sv::get(const int index) const {
|
||||
if (index >= this->size()) {
|
||||
return "";
|
||||
}
|
||||
@ -66,10 +65,10 @@ const char* params::get(const int index) const {
|
||||
return game::sv_cmd_args->argv[this->nesting_][index];
|
||||
}
|
||||
|
||||
std::string params::join(const int index) const {
|
||||
std::string params_sv::join(const int index) const {
|
||||
std::string result = {};
|
||||
|
||||
for (auto i = index; i < this->size(); i++) {
|
||||
for (auto i = index; i < this->size(); ++i) {
|
||||
if (i > index)
|
||||
result.append(" ");
|
||||
result.append(this->get(i));
|
||||
@ -83,7 +82,8 @@ void add_raw(const char* name, void (*callback)()) {
|
||||
utils::memory::get_allocator()->allocate<game::cmd_function_s>());
|
||||
}
|
||||
|
||||
void add(const char* name, const std::function<void(const params&)>& callback) {
|
||||
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)) {
|
||||
@ -109,9 +109,10 @@ public:
|
||||
|
||||
private:
|
||||
static void add_commands_generic() {
|
||||
add("properQuit", [](const params&) { utils::nt::raise_hard_exception(); });
|
||||
add("properQuit",
|
||||
[](const params_sv&) { utils::nt::raise_hard_exception(); });
|
||||
|
||||
add("echo", [](const params& params) {
|
||||
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));
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace command {
|
||||
class params {
|
||||
public:
|
||||
params();
|
||||
|
||||
int size() const;
|
||||
const char* get(int index) const;
|
||||
std::string join(int index) const;
|
||||
class params_sv {
|
||||
public:
|
||||
params_sv();
|
||||
|
||||
[[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); }
|
||||
|
||||
@ -16,7 +17,8 @@ private:
|
||||
};
|
||||
|
||||
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(const params_sv&)>& callback);
|
||||
|
||||
void execute(std::string command, bool sync = false);
|
||||
} // namespace command
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace gameplay {
|
||||
|
@ -1,21 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "../loader/component_loader.hpp"
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace gsc_patches {
|
||||
namespace {
|
||||
void g_log_printf(const char* fmt) { game::G_LogPrintf("%s", fmt); }
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
if (game::environment::is_mp()) {
|
||||
utils::hook::call(0x8426D3, g_log_printf);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace gsc_patches
|
||||
|
||||
REGISTER_COMPONENT(gsc_patches::component)
|
@ -49,8 +49,9 @@ WEAK symbol<const dvar_s*(const char*, int, int, int, unsigned __int16,
|
||||
const char*)>
|
||||
Dvar_RegisterInt{0x58D900, 0x651910};
|
||||
|
||||
WEAK symbol<void(const char*, void(), cmd_function_s*)> Cmd_AddCommandInternal{
|
||||
0x6AD580, 0x661400};
|
||||
WEAK symbol<void(const char* cmdName, void (*function)(),
|
||||
cmd_function_s* allocedCmd)>
|
||||
Cmd_AddCommandInternal{0x6AD580, 0x661400};
|
||||
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{0x527EA0, 0x5F1A90};
|
||||
WEAK symbol<cmd_function_s*(const char*)> Cmd_FindCommand{0x445B60, 0x479DD0};
|
||||
|
||||
@ -71,6 +72,7 @@ WEAK symbol<void(const float*, scriptInstance_t)> Scr_AddVector{0x532EF0, 0x0};
|
||||
WEAK symbol<int(const playerState_s*)> PM_GetEffectiveStance{0x659590, 0x0};
|
||||
|
||||
WEAK symbol<CmdArgs> sv_cmd_args{0x355BD88, 0x243D208};
|
||||
|
||||
WEAK symbol<int> dvarCount{0x385BE74, 0x261CBD4};
|
||||
WEAK symbol<dvar_t*> sortedDvars{0x385BE88, 0x261CBE8};
|
||||
WEAK symbol<client_s> svs_clients{0x372D11C, 0x286D01C};
|
||||
|
@ -18,10 +18,6 @@
|
||||
|
||||
#pragma warning(disable : 26812)
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
using namespace std::literals;
|
||||
|
Loading…
x
Reference in New Issue
Block a user