mirror of
https://github.com/diamante0018/BlackOpsPlugin.git
synced 2025-04-20 02:22:52 +00:00
Fix crash
This commit is contained in:
parent
2793afac0e
commit
d20cdfbb41
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -7,3 +7,6 @@
|
|||||||
[submodule "deps/rapidjson"]
|
[submodule "deps/rapidjson"]
|
||||||
path = deps/rapidjson
|
path = deps/rapidjson
|
||||||
url = https://github.com/Tencent/rapidjson.git
|
url = https://github.com/Tencent/rapidjson.git
|
||||||
|
[submodule "deps/asmjit"]
|
||||||
|
path = deps/asmjit
|
||||||
|
url = https://github.com/asmjit/asmjit.git
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[](https://github.com/diamante0018/BlackOpsPlugin/actions)
|
[](https://github.com/diamante0018/BlackOpsPlugin/actions)
|
||||||
|
|
||||||
# Black-Ops-Plugin
|
# Black-Ops-Plugin
|
||||||
I have no clue as to what this does. I use this program to test experimental features.
|
I use this program to test experimental features. Some may end up in the plutonium client. Some may not.
|
||||||
|
|
||||||
## Thanks to
|
## Thanks to
|
||||||
* [momo5502](https://github.com/momo5502) - Core component loader & utils
|
* [momo5502](https://github.com/momo5502) - Core component loader & utils
|
||||||
|
1
deps/asmjit
vendored
Submodule
1
deps/asmjit
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a4cb51b532af0f8137c4182914244c3b05d7745f
|
34
deps/premake/asmjit.lua
vendored
Normal file
34
deps/premake/asmjit.lua
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
asmjit = {
|
||||||
|
source = path.join(dependencies.basePath, "asmjit"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function asmjit.import()
|
||||||
|
links { "asmjit" }
|
||||||
|
asmjit.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function asmjit.includes()
|
||||||
|
includedirs {
|
||||||
|
path.join(asmjit.source, "src")
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"ASMJIT_STATIC"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function asmjit.project()
|
||||||
|
project "asmjit"
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
asmjit.includes()
|
||||||
|
|
||||||
|
files {
|
||||||
|
path.join(asmjit.source, "src/**.cpp"),
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, asmjit)
|
33
premake5.lua
33
premake5.lua
@ -51,7 +51,7 @@ editandcontinue "Off"
|
|||||||
warnings "Extra"
|
warnings "Extra"
|
||||||
characterset "ASCII"
|
characterset "ASCII"
|
||||||
|
|
||||||
flags { "NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks" }
|
flags {"NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks"}
|
||||||
|
|
||||||
filter "platforms:Win*"
|
filter "platforms:Win*"
|
||||||
defines {"_WINDOWS", "WIN32"}
|
defines {"_WINDOWS", "WIN32"}
|
||||||
@ -60,7 +60,7 @@ filter {}
|
|||||||
filter "configurations:Release"
|
filter "configurations:Release"
|
||||||
optimize "Size"
|
optimize "Size"
|
||||||
buildoptions {"/GL"}
|
buildoptions {"/GL"}
|
||||||
linkoptions { "/IGNORE:4702", "/LTCG" }
|
linkoptions {"/IGNORE:4702", "/LTCG"}
|
||||||
defines {"NDEBUG"}
|
defines {"NDEBUG"}
|
||||||
flags {"FatalCompileWarnings"}
|
flags {"FatalCompileWarnings"}
|
||||||
filter {}
|
filter {}
|
||||||
@ -70,13 +70,36 @@ filter "configurations:Debug"
|
|||||||
defines {"DEBUG", "_DEBUG"}
|
defines {"DEBUG", "_DEBUG"}
|
||||||
filter {}
|
filter {}
|
||||||
|
|
||||||
project "black-ops-plugin"
|
project "common"
|
||||||
|
kind "StaticLib"
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
files {"./src/common/**.hpp", "./src/common/**.cpp"}
|
||||||
|
|
||||||
|
includedirs {"./src/common", "%{prj.location}/src"}
|
||||||
|
|
||||||
|
resincludedirs {"$(ProjectDir)src"}
|
||||||
|
|
||||||
|
dependencies.imports()
|
||||||
|
|
||||||
|
project "client"
|
||||||
kind "SharedLib"
|
kind "SharedLib"
|
||||||
language "C++"
|
language "C++"
|
||||||
|
|
||||||
files {"./src/**.hpp", "./src/**.cpp"}
|
targetname "black-ops-plugin"
|
||||||
|
|
||||||
includedirs {"src"}
|
pchheader "std_include.hpp"
|
||||||
|
pchsource "src/client/std_include.cpp"
|
||||||
|
|
||||||
|
linkoptions {"/IGNORE:4254", "/PDBCompress"}
|
||||||
|
|
||||||
|
files {"./src/client/**.hpp", "./src/client/**.cpp"}
|
||||||
|
|
||||||
|
includedirs {"./src/client", "./src/common", "%{prj.location}/src"}
|
||||||
|
|
||||||
|
resincludedirs {"$(ProjectDir)src"}
|
||||||
|
|
||||||
|
links {"common"}
|
||||||
|
|
||||||
dependencies.imports()
|
dependencies.imports()
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "../loader/component_loader.hpp"
|
||||||
#include "utils/hook.hpp"
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
namespace ban {
|
namespace ban {
|
||||||
namespace {
|
namespace {
|
@ -1,9 +1,9 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "../loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "utils/hook.hpp"
|
#include <utils/hook.hpp>
|
||||||
#include "utils/io.hpp"
|
#include <utils/io.hpp>
|
||||||
|
|
||||||
namespace bots {
|
namespace bots {
|
||||||
namespace {
|
namespace {
|
||||||
@ -14,7 +14,7 @@ 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
|
// Json file is expected to contain a key for the bot's name. Value should be a
|
||||||
// string for the clantag
|
// string for the clantag
|
||||||
void load_bot_data() {
|
void load_bot_data() {
|
||||||
const auto path = game::Dvar_FindVar("fs_homepath")->current.string;
|
const auto* path = game::Dvar_FindVar("fs_homepath")->current.string;
|
||||||
std::filesystem::current_path(path);
|
std::filesystem::current_path(path);
|
||||||
|
|
||||||
if (!utils::io::file_exists("bots/bots.json")) {
|
if (!utils::io::file_exists("bots/bots.json")) {
|
@ -1,8 +1,8 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "../loader/component_loader.hpp"
|
||||||
#include "utils/hook.hpp"
|
#include <utils/hook.hpp>
|
||||||
#include "utils/string.hpp"
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
|
||||||
@ -11,26 +11,26 @@ namespace {
|
|||||||
std::mutex chat_mutex;
|
std::mutex chat_mutex;
|
||||||
std::unordered_set<std::uint64_t> mute_list{};
|
std::unordered_set<std::uint64_t> mute_list{};
|
||||||
|
|
||||||
void mute_player(const game::client_s* cl) {
|
void mute_player(const game::client_s* client) {
|
||||||
std::unique_lock<std::mutex> _(chat_mutex);
|
std::unique_lock<std::mutex> _(chat_mutex);
|
||||||
|
|
||||||
if (mute_list.contains(cl->xuid)) {
|
if (mute_list.contains(client->xuid)) {
|
||||||
game::SV_GameSendServerCommand(
|
game::SV_GameSendServerCommand(
|
||||||
-1, game::SV_CMD_CAN_IGNORE,
|
-1, game::SV_CMD_CAN_IGNORE,
|
||||||
utils::string::va("%c \"%s is already muted\"", 0x65, cl->name));
|
utils::string::va("%c \"%s is already muted\"", 0x65, client->name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mute_list.insert(cl->xuid);
|
mute_list.insert(client->xuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmute_player(const game::client_s* cl) {
|
void unmute_player(const game::client_s* client) {
|
||||||
std::unique_lock<std::mutex> _(chat_mutex);
|
std::unique_lock<std::mutex> _(chat_mutex);
|
||||||
|
|
||||||
mute_list.erase(cl->xuid);
|
mute_list.erase(client->xuid);
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(
|
game::SV_GameSendServerCommand(
|
||||||
cl->gentity->entnum, game::SV_CMD_CAN_IGNORE,
|
client->gentity->entnum, game::SV_CMD_CAN_IGNORE,
|
||||||
utils::string::va("%c \"You were unmuted\"", 0x65));
|
utils::string::va("%c \"You were unmuted\"", 0x65));
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "../loader/component_loader.hpp"
|
||||||
#include "utils/string.hpp"
|
|
||||||
#include "utils/nt.hpp"
|
#include <utils/string.hpp>
|
||||||
#include "utils/io.hpp"
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
|
||||||
@ -12,6 +12,33 @@ constexpr auto CMD_MAX_NESTING = 8;
|
|||||||
namespace command {
|
namespace command {
|
||||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void cmd_vstr_f(const params& 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) {
|
||||||
|
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() {
|
void main_handler() {
|
||||||
params params = {};
|
params params = {};
|
||||||
|
|
||||||
@ -63,26 +90,6 @@ void add(const char* name, const std::function<void(const params&)>& callback) {
|
|||||||
handlers[command] = callback;
|
handlers[command] = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> script_commands;
|
|
||||||
utils::memory::allocator allocator;
|
|
||||||
|
|
||||||
void add_script_command(const std::string& name,
|
|
||||||
const std::function<void(const params&)>& callback) {
|
|
||||||
script_commands.push_back(name);
|
|
||||||
const auto _name = allocator.duplicate_string(name);
|
|
||||||
add(_name, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_script_commands() {
|
|
||||||
for (const auto& name : script_commands) {
|
|
||||||
handlers.erase(name);
|
|
||||||
game::Cmd_RemoveCommand(name.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator.clear();
|
|
||||||
script_commands.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(std::string command, const bool sync) {
|
void execute(std::string command, const bool sync) {
|
||||||
command += "\n";
|
command += "\n";
|
||||||
|
|
||||||
@ -97,11 +104,20 @@ class component final : public component_interface {
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override { add_commands_generic(); }
|
void post_unpack() override { add_commands_generic(); }
|
||||||
|
|
||||||
void pre_destroy() override { clear_script_commands(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void add_commands_generic() {
|
static void add_commands_generic() {
|
||||||
add("properQuit", [](const params&) { utils::nt::raise_hard_exception(); });
|
add("properQuit", [](const params&) { utils::nt::raise_hard_exception(); });
|
||||||
|
|
||||||
|
add("echo", [](const params& 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");
|
||||||
|
});
|
||||||
|
|
||||||
|
game::Cmd_RemoveCommand("vstr");
|
||||||
|
add("vstr", cmd_vstr_f);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace command
|
} // namespace command
|
@ -18,9 +18,5 @@ private:
|
|||||||
void add_raw(const char* name, 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(const params&)>& callback);
|
||||||
|
|
||||||
void add_script_command(const std::string& name,
|
|
||||||
const std::function<void(const params&)>& callback);
|
|
||||||
void clear_script_commands();
|
|
||||||
|
|
||||||
void execute(std::string command, bool sync = false);
|
void execute(std::string command, bool sync = false);
|
||||||
} // namespace command
|
} // namespace command
|
30
src/client/component/gameplay.cpp
Normal file
30
src/client/component/gameplay.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
|
||||||
|
#include "../loader/component_loader.hpp"
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
namespace gameplay {
|
||||||
|
namespace {
|
||||||
|
game::dvar_s** player_sustainAmmo = nullptr;
|
||||||
|
|
||||||
|
utils::hook::detour pm_weapon_use_ammo_hook;
|
||||||
|
|
||||||
|
void pm_weapon_use_ammo_stub(void* ps, int wp, int amount) {
|
||||||
|
if (!(*player_sustainAmmo)->current.enabled) {
|
||||||
|
pm_weapon_use_ammo_hook.invoke<void>(ps, wp, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class component final : public component_interface {
|
||||||
|
public:
|
||||||
|
void post_unpack() override {
|
||||||
|
if (game::environment::t5zm()) {
|
||||||
|
player_sustainAmmo = reinterpret_cast<game::dvar_s**>(0xBCD250);
|
||||||
|
pm_weapon_use_ammo_hook.create(0x6979B0, &pm_weapon_use_ammo_stub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace gameplay
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(gameplay::component)
|
@ -1,4 +1,4 @@
|
|||||||
#include <stdinc.hpp>
|
#include "std_include.hpp"
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD ul_reason_for_call,
|
BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD ul_reason_for_call,
|
@ -1,4 +1,4 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
gamemode current = reinterpret_cast<const char*>(0xA6840C) == "multiplayer"s
|
gamemode current = reinterpret_cast<const char*>(0xA6840C) == "multiplayer"s
|
@ -19,6 +19,7 @@ public:
|
|||||||
|
|
||||||
T* get() const {
|
T* get() const {
|
||||||
if (environment::t5mp()) {
|
if (environment::t5mp()) {
|
||||||
|
|
||||||
return t5mp_;
|
return t5mp_;
|
||||||
}
|
}
|
||||||
|
|
@ -276,10 +276,9 @@ typedef struct dvar_s {
|
|||||||
DvarValue saved;
|
DvarValue saved;
|
||||||
DvarLimits domain;
|
DvarLimits domain;
|
||||||
dvar_s* hashNext;
|
dvar_s* hashNext;
|
||||||
unsigned char pad0[8];
|
|
||||||
} dvar_t;
|
} dvar_t;
|
||||||
|
|
||||||
static_assert(sizeof(dvar_s) == 112);
|
static_assert(sizeof(dvar_s) == 104);
|
||||||
|
|
||||||
enum playerFlag {
|
enum playerFlag {
|
||||||
PLAYER_FLAG_NOCLIP = 1 << 0,
|
PLAYER_FLAG_NOCLIP = 1 << 0,
|
@ -32,7 +32,7 @@ WEAK symbol<bool(netsrc_t, netadr_s, const char*)> NET_OutOfBandPrint{0x560BB0,
|
|||||||
0x472850};
|
0x472850};
|
||||||
WEAK symbol<const char*(netadr_s)> NET_AdrToString{0x49F970, 0x40D790};
|
WEAK symbol<const char*(netadr_s)> NET_AdrToString{0x49F970, 0x40D790};
|
||||||
|
|
||||||
WEAK symbol<dvar_s*(const char*)> Dvar_FindVar{0x512F70, 0x5AE810};
|
WEAK symbol<const dvar_s*(const char*)> Dvar_FindVar{0x512F70, 0x5AE810};
|
||||||
WEAK symbol<const char*(const dvar_s*)> Dvar_DisplayableValue{0x681DD0,
|
WEAK symbol<const char*(const dvar_s*)> Dvar_DisplayableValue{0x681DD0,
|
||||||
0x5B56F0};
|
0x5B56F0};
|
||||||
WEAK symbol<const char*(const dvar_s*)> Dvar_DisplayableLatchedValue{0x4AE1A0,
|
WEAK symbol<const char*(const dvar_s*)> Dvar_DisplayableLatchedValue{0x4AE1A0,
|
@ -1,4 +1,4 @@
|
|||||||
#include <stdinc.hpp>
|
#include <std_include.hpp>
|
||||||
#include "component_loader.hpp"
|
#include "component_loader.hpp"
|
||||||
|
|
||||||
void component_loader::register_component(
|
void component_loader::register_component(
|
1
src/client/std_include.cpp
Normal file
1
src/client/std_include.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "std_include.hpp"
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
@ -17,6 +17,14 @@ public:
|
|||||||
} __;
|
} __;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
asmjit::Error assembler::call(void* target) {
|
||||||
|
return Assembler::call(size_t(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
asmjit::Error assembler::jmp(void* target) {
|
||||||
|
return Assembler::jmp(size_t(target));
|
||||||
|
}
|
||||||
|
|
||||||
detour::detour(const size_t place, void* target)
|
detour::detour(const size_t place, void* target)
|
||||||
: detour(reinterpret_cast<void*>(place), target) {}
|
: detour(reinterpret_cast<void*>(place), target) {}
|
||||||
|
|
||||||
@ -153,4 +161,20 @@ void redirect_jump(void* pointer, void* data) {
|
|||||||
void redirect_jump(size_t pointer, void* data) {
|
void redirect_jump(size_t pointer, void* data) {
|
||||||
redirect_jump(reinterpret_cast<void*>(pointer), data);
|
redirect_jump(reinterpret_cast<void*>(pointer), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* assemble(const std::function<void(assembler&)>& asm_function) {
|
||||||
|
static asmjit::JitRuntime runtime;
|
||||||
|
|
||||||
|
asmjit::CodeHolder code;
|
||||||
|
code.init(runtime.environment());
|
||||||
|
|
||||||
|
assembler a(&code);
|
||||||
|
|
||||||
|
asm_function(a);
|
||||||
|
|
||||||
|
void* result = nullptr;
|
||||||
|
runtime.add(&result, &code);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
} // namespace utils::hook
|
} // namespace utils::hook
|
@ -2,9 +2,24 @@
|
|||||||
#include "signature.hpp"
|
#include "signature.hpp"
|
||||||
|
|
||||||
#define CalculateRelativeJMPAddress(X, Y) \
|
#define CalculateRelativeJMPAddress(X, Y) \
|
||||||
(((std::uintptr_t)Y - (std::uintptr_t)X) - 5)
|
(((std::uintptr_t)(Y) - (std::uintptr_t)(X)) - 5)
|
||||||
|
|
||||||
|
#include <asmjit/core/jitruntime.h>
|
||||||
|
#include <asmjit/x86/x86assembler.h>
|
||||||
|
|
||||||
|
using namespace asmjit::x86;
|
||||||
|
|
||||||
namespace utils::hook {
|
namespace utils::hook {
|
||||||
|
class assembler : public Assembler {
|
||||||
|
public:
|
||||||
|
using Assembler::Assembler;
|
||||||
|
using Assembler::call;
|
||||||
|
using Assembler::jmp;
|
||||||
|
|
||||||
|
asmjit::Error call(void* target);
|
||||||
|
asmjit::Error jmp(void* target);
|
||||||
|
};
|
||||||
|
|
||||||
class detour {
|
class detour {
|
||||||
public:
|
public:
|
||||||
detour() = default;
|
detour() = default;
|
||||||
@ -70,6 +85,8 @@ void jump(std::uintptr_t address, void* destination);
|
|||||||
void redirect_jump(void* pointer, void* data);
|
void redirect_jump(void* pointer, void* data);
|
||||||
void redirect_jump(size_t pointer, void* data);
|
void redirect_jump(size_t pointer, void* data);
|
||||||
|
|
||||||
|
void* assemble(const std::function<void(assembler&)>& asm_function);
|
||||||
|
|
||||||
template <typename T> T extract(void* address) {
|
template <typename T> T extract(void* address) {
|
||||||
const auto data = static_cast<uint8_t*>(address);
|
const auto data = static_cast<uint8_t*>(address);
|
||||||
const auto offset = *reinterpret_cast<int32_t*>(data);
|
const auto offset = *reinterpret_cast<int32_t*>(data);
|
@ -11,7 +11,9 @@ bool move_file(const std::string& src, const std::string& target) {
|
|||||||
return MoveFileA(src.data(), target.data()) == TRUE;
|
return MoveFileA(src.data(), target.data()) == TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool file_exists(const std::string& file) { return std::ifstream(file).good(); }
|
bool file_exists(const std::string& file) {
|
||||||
|
return std::filesystem::exists(file);
|
||||||
|
}
|
||||||
|
|
||||||
bool write_file(const std::string& file, const std::string& data,
|
bool write_file(const std::string& file, const std::string& data,
|
||||||
const bool append) {
|
const bool append) {
|
||||||
@ -54,7 +56,7 @@ bool read_file(const std::string& file, std::string* data) {
|
|||||||
|
|
||||||
if (size > -1) {
|
if (size > -1) {
|
||||||
data->resize(static_cast<uint32_t>(size));
|
data->resize(static_cast<uint32_t>(size));
|
||||||
stream.read(const_cast<char*>(data->data()), size);
|
stream.read(data->data(), size);
|
||||||
stream.close();
|
stream.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ memory::allocator::~allocator() { this->clear(); }
|
|||||||
void memory::allocator::clear() {
|
void memory::allocator::clear() {
|
||||||
std::lock_guard _(this->mutex_);
|
std::lock_guard _(this->mutex_);
|
||||||
|
|
||||||
for (auto& data : this->pool_) {
|
for (const auto& data : this->pool_) {
|
||||||
memory::free(data);
|
memory::free(data);
|
||||||
}
|
}
|
||||||
|
|
@ -18,11 +18,9 @@ public:
|
|||||||
|
|
||||||
void* allocate(size_t length);
|
void* allocate(size_t length);
|
||||||
|
|
||||||
template <typename T> inline T* allocate() {
|
template <typename T> T* allocate() { return this->allocate_array<T>(1); }
|
||||||
return this->allocate_array<T>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> inline T* allocate_array(const size_t count = 1) {
|
template <typename T> 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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,12 +35,9 @@ public:
|
|||||||
|
|
||||||
static void* allocate(size_t length);
|
static void* allocate(size_t length);
|
||||||
|
|
||||||
template <typename T> static inline T* allocate() {
|
template <typename T> static T* allocate() { return allocate_array<T>(1); }
|
||||||
return allocate_array<T>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> static T* allocate_array(const size_t count = 1) {
|
||||||
static inline T* allocate_array(const size_t count = 1) {
|
|
||||||
return static_cast<T*>(allocate(count * sizeof(T)));
|
return static_cast<T*>(allocate(count * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
@ -24,8 +24,7 @@ std::vector<std::string> split(const std::string& s, const char delim) {
|
|||||||
std::vector<std::string> elems;
|
std::vector<std::string> elems;
|
||||||
|
|
||||||
while (std::getline(ss, item, delim)) {
|
while (std::getline(ss, item, delim)) {
|
||||||
elems.push_back(item); // elems.push_back(std::move(item)); // if C++11
|
elems.push_back(item); // elems.push_back(std::move(item)); if C++11
|
||||||
// (based on comment from @mchiasson)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return elems;
|
return elems;
|
||||||
@ -92,12 +91,12 @@ std::string get_clipboard_data() {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max) {
|
void strip(const char* in, char* out, size_t max) {
|
||||||
if (!in || !out)
|
if (!in || !out)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
max--;
|
max--;
|
||||||
auto current = 0;
|
size_t current = 0;
|
||||||
while (*in != 0 && current < max) {
|
while (*in != 0 && current < max) {
|
||||||
const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48);
|
const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48);
|
||||||
|
|
||||||
@ -111,6 +110,7 @@ void strip(const char* in, char* out, int max) {
|
|||||||
|
|
||||||
++in;
|
++in;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = '\0';
|
*out = '\0';
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#ifndef ARRAYSIZE
|
#ifndef ARRAYSIZE
|
||||||
template <class Type, size_t n> size_t ARRAYSIZE(Type (&)[n]) { return n; }
|
template <class Type, size_t n> size_t ARRAYSIZE(Type (&)[n]) { return n; }
|
||||||
@ -87,7 +86,7 @@ std::string dump_hex(const std::string& data,
|
|||||||
|
|
||||||
std::string get_clipboard_data();
|
std::string get_clipboard_data();
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max);
|
void strip(const char* in, char* out, size_t max);
|
||||||
|
|
||||||
std::string convert(const std::wstring& wstr);
|
std::string convert(const std::wstring& wstr);
|
||||||
std::wstring convert(const std::string& str);
|
std::wstring convert(const std::string& str);
|
@ -1,31 +0,0 @@
|
|||||||
#include <stdinc.hpp>
|
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
|
||||||
#include "utils/hook.hpp"
|
|
||||||
|
|
||||||
namespace gameplay {
|
|
||||||
namespace {
|
|
||||||
const game::dvar_s* player_meleeRange = nullptr;
|
|
||||||
utils::hook::detour fire_weapon_melee_hook;
|
|
||||||
|
|
||||||
void fire_weapon_melee_stub(game::gentity_s* ent, int time) {
|
|
||||||
if (player_meleeRange->current.value == 0.0f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fire_weapon_melee_hook.invoke<void>(ent, time);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class component final : public component_interface {
|
|
||||||
public:
|
|
||||||
void post_unpack() override {
|
|
||||||
player_meleeRange =
|
|
||||||
*reinterpret_cast<game::dvar_s**>(SELECT(0xC51990, 0xBCAFE4));
|
|
||||||
|
|
||||||
fire_weapon_melee_hook.create(SELECT(0x401E00, 0x465E40),
|
|
||||||
&fire_weapon_melee_stub);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace gameplay
|
|
||||||
|
|
||||||
REGISTER_COMPONENT(gameplay::component)
|
|
@ -1 +0,0 @@
|
|||||||
#include <stdinc.hpp>
|
|
Loading…
x
Reference in New Issue
Block a user