Prepare dedicated server support
This commit is contained in:
parent
f4a4a95674
commit
3a6f973473
@ -696,9 +696,8 @@ namespace arxan
|
|||||||
return zw_terminate_process_hook.invoke<NTSTATUS>(process_handle, exit_status);
|
return zw_terminate_process_hook.invoke<NTSTATUS>(process_handle, exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_load() override
|
void post_load() override
|
||||||
{
|
{
|
||||||
auto* dll_characteristics = &utils::nt::library().get_optional_header()->DllCharacteristics;
|
auto* dll_characteristics = &utils::nt::library().get_optional_header()->DllCharacteristics;
|
||||||
|
@ -107,9 +107,8 @@ namespace auth
|
|||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Patch steam id bit check
|
// Patch steam id bit check
|
||||||
|
@ -41,9 +41,8 @@ namespace bots
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::jump(0x141653B70_g, get_bot_name);
|
utils::hook::jump(0x141653B70_g, get_bot_name);
|
||||||
|
@ -27,9 +27,8 @@ namespace branding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
scheduler::loop(draw_branding, scheduler::renderer);
|
scheduler::loop(draw_branding, scheduler::renderer);
|
||||||
|
@ -30,9 +30,8 @@ namespace colors
|
|||||||
utils::hook::copy(g_color_table + index * 4, color_float, sizeof(color_float));
|
utils::hook::copy(g_color_table + index * 4, color_float, sizeof(color_float));
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
patch_color<1>(255, 49, 49); // 1 - Red
|
patch_color<1>(255, 49, 49); // 1 - Red
|
||||||
|
@ -46,9 +46,8 @@ namespace command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Disable whitelist
|
// Disable whitelist
|
||||||
|
@ -193,9 +193,8 @@ namespace console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::set<uint8_t>(0x14133D2FE_g, 0xEB); // Always enable ingame console
|
utils::hook::set<uint8_t>(0x14133D2FE_g, 0xEB); // Always enable ingame console
|
||||||
|
@ -9,9 +9,8 @@ namespace dedicated
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : server_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -441,9 +441,8 @@ namespace demonware
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
component()
|
component()
|
||||||
{
|
{
|
||||||
udp_servers.create<stun_server>("stun.us.demonware.net");
|
udp_servers.create<stun_server>("stun.us.demonware.net");
|
||||||
@ -477,6 +476,11 @@ namespace demonware
|
|||||||
{
|
{
|
||||||
server_thread = utils::thread::create_named_thread("Demonware", server_main);
|
server_thread = utils::thread::create_named_thread("Demonware", server_main);
|
||||||
|
|
||||||
|
if (game::is_server())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
utils::hook::set<uint8_t>(0x14293E829_g, 0x0); // CURLOPT_SSL_VERIFYPEER
|
utils::hook::set<uint8_t>(0x14293E829_g, 0x0); // CURLOPT_SSL_VERIFYPEER
|
||||||
utils::hook::set<uint8_t>(0x15F3CCFED_g, 0xAF); // CURLOPT_SSL_VERIFYHOST
|
utils::hook::set<uint8_t>(0x15F3CCFED_g, 0xAF); // CURLOPT_SSL_VERIFYHOST
|
||||||
utils::hook::set<uint8_t>(0x1430B9810_g, 0x0); // HTTPS -> HTTP
|
utils::hook::set<uint8_t>(0x1430B9810_g, 0x0); // HTTPS -> HTTP
|
||||||
|
@ -32,7 +32,7 @@ namespace discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void post_load() override
|
void post_load() override
|
||||||
|
@ -193,9 +193,8 @@ namespace exception
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
component()
|
component()
|
||||||
{
|
{
|
||||||
main_thread_id = GetCurrentThreadId();
|
main_thread_id = GetCurrentThreadId();
|
||||||
|
@ -29,9 +29,8 @@ namespace icon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_load() override
|
void post_load() override
|
||||||
{
|
{
|
||||||
load_icon_a_hook.create(LoadIconA, load_icon_a_stub);
|
load_icon_a_hook.create(LoadIconA, load_icon_a_stub);
|
||||||
|
@ -14,7 +14,8 @@ namespace loot
|
|||||||
utils::hook::detour liveinventory_getitemquantity_hook;
|
utils::hook::detour liveinventory_getitemquantity_hook;
|
||||||
utils::hook::detour liveinventory_areextraslotspurchased_hook;
|
utils::hook::detour liveinventory_areextraslotspurchased_hook;
|
||||||
|
|
||||||
int loot_getitemquantity_stub(const game::ControllerIndex_t /*controller_index*/, const game::eModes mode, const int /*item_id*/)
|
int loot_getitemquantity_stub(const game::ControllerIndex_t /*controller_index*/, const game::eModes mode,
|
||||||
|
const int /*item_id*/)
|
||||||
{
|
{
|
||||||
if (mode == game::eModes::MODE_ZOMBIES)
|
if (mode == game::eModes::MODE_ZOMBIES)
|
||||||
{
|
{
|
||||||
@ -27,7 +28,8 @@ namespace loot
|
|||||||
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
int liveinventory_getitemquantity_stub(const game::ControllerIndex_t controller_index, const int item_id)
|
||||||
{
|
{
|
||||||
// Item id's for extra CaC slots, CWL camo's and paid specialist outfits
|
// Item id's for extra CaC slots, CWL camo's and paid specialist outfits
|
||||||
if (item_id == 99003 || item_id >= 99018 && item_id <= 99021 || item_id == 99025 || item_id >= 90047 && item_id <= 90064)
|
if (item_id == 99003 || item_id >= 99018 && item_id <= 99021 || item_id == 99025 || item_id >= 90047 &&
|
||||||
|
item_id <= 90064)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -47,9 +49,8 @@ namespace loot
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
scheduler::once(set_dvars_on_startup, scheduler::pipeline::main);
|
scheduler::once(set_dvars_on_startup, scheduler::pipeline::main);
|
||||||
|
@ -210,9 +210,8 @@ namespace network
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
//utils::hook::jump(0x14143CAB0_g, ret2); // patch dwGetConnectionStatus
|
//utils::hook::jump(0x14143CAB0_g, ret2); // patch dwGetConnectionStatus
|
||||||
|
@ -217,9 +217,8 @@ namespace party
|
|||||||
network::send(host, "getInfo", challenge);
|
network::send(host, "getInfo", challenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::jump(0x141E19B60_g, 0x141E19BB6_g); // patch steam id validity check
|
utils::hook::jump(0x141E19B60_g, 0x141E19BB6_g); // patch steam id validity check
|
||||||
|
@ -149,9 +149,8 @@ namespace scheduler
|
|||||||
}, type, delay);
|
}, type, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_load() override
|
void post_load() override
|
||||||
{
|
{
|
||||||
thread = utils::thread::create_named_thread("Async Scheduler", []()
|
thread = utils::thread::create_named_thread("Async Scheduler", []()
|
||||||
@ -165,11 +164,14 @@ namespace scheduler
|
|||||||
}
|
}
|
||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
if (!game::is_server())
|
||||||
{
|
{
|
||||||
r_end_frame_hook.create(0x142273560_g, r_end_frame_stub); // some func called before R_EndFrame, maybe SND_EndFrame?
|
r_end_frame_hook.create(0x142273560_g, r_end_frame_stub); // some func called before R_EndFrame, maybe SND_EndFrame?
|
||||||
g_run_frame_hook.create(0x14065C360_g, server_frame_stub); // GlassSv_Update
|
g_run_frame_hook.create(0x14065C360_g, server_frame_stub); // GlassSv_Update
|
||||||
main_frame_hook.create(0x1420F9860_g, main_frame_stub); // Com_Frame_Try_Block_Function
|
main_frame_hook.create(0x1420F9860_g, main_frame_stub); // Com_Frame_Try_Block_Function
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
{
|
{
|
||||||
|
@ -165,9 +165,8 @@ namespace splash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : client_component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
component()
|
component()
|
||||||
{
|
{
|
||||||
enable_dpi_awareness();
|
enable_dpi_awareness();
|
||||||
|
@ -205,9 +205,8 @@ namespace steam_proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
struct component final : component_interface
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void post_load() override
|
void post_load() override
|
||||||
{
|
{
|
||||||
load_client();
|
load_client();
|
||||||
|
@ -5,18 +5,33 @@
|
|||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
size_t get_base()
|
namespace
|
||||||
{
|
{
|
||||||
static auto base = []
|
const utils::nt::library& get_host_library()
|
||||||
{
|
{
|
||||||
const utils::nt::library host{};
|
static auto host = []
|
||||||
|
{
|
||||||
|
utils::nt::library host{};
|
||||||
if (!host || host == utils::nt::library::get_by_address(get_base))
|
if (!host || host == utils::nt::library::get_by_address(get_base))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Invalid host application");
|
throw std::runtime_error("Invalid host application");
|
||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<size_t>(host.get_ptr());
|
return host;
|
||||||
}();
|
}();
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_base()
|
||||||
|
{
|
||||||
|
static auto base = reinterpret_cast<size_t>(get_host_library().get_ptr());
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_server()
|
||||||
|
{
|
||||||
|
static auto server = get_host_library().get_optional_header()->CheckSum == 0x14C28B4;
|
||||||
|
return server;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
size_t get_base();
|
size_t get_base();
|
||||||
|
bool is_server();
|
||||||
|
|
||||||
inline size_t relocate(const size_t val)
|
inline size_t relocate(const size_t val)
|
||||||
{
|
{
|
||||||
|
@ -10,9 +10,17 @@ enum class component_priority
|
|||||||
arxan,
|
arxan,
|
||||||
};
|
};
|
||||||
|
|
||||||
class component_interface
|
enum class component_type
|
||||||
{
|
{
|
||||||
public:
|
client,
|
||||||
|
server,
|
||||||
|
any,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct component_interface
|
||||||
|
{
|
||||||
|
static constexpr component_type type = component_type::any;
|
||||||
|
|
||||||
virtual ~component_interface() = default;
|
virtual ~component_interface() = default;
|
||||||
|
|
||||||
virtual void post_load()
|
virtual void post_load()
|
||||||
@ -32,3 +40,13 @@ public:
|
|||||||
return component_priority::min;
|
return component_priority::min;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct client_component_interface : component_interface
|
||||||
|
{
|
||||||
|
static constexpr component_type type = component_type::client;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct server_component_interface : component_interface
|
||||||
|
{
|
||||||
|
static constexpr component_type type = component_type::server;
|
||||||
|
};
|
||||||
|
@ -23,9 +23,9 @@ namespace component_loader
|
|||||||
return *components;
|
return *components;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<registration_functor>& get_registration_functors()
|
std::vector<std::pair<registration_functor, component_type>>& get_registration_functors()
|
||||||
{
|
{
|
||||||
static std::vector<registration_functor> functors;
|
static std::vector<std::pair<registration_functor, component_type>> functors;
|
||||||
return functors;
|
return functors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,25 +42,28 @@ namespace component_loader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_component(registration_functor functor)
|
void register_component(registration_functor functor, component_type type)
|
||||||
{
|
{
|
||||||
if (!get_components().empty())
|
if (!get_components().empty())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Registration is too late");
|
throw std::runtime_error("Registration is too late");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_registration_functors().push_back(std::move(functor));
|
get_registration_functors().emplace_back(std::move(functor), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool activate()
|
bool activate(bool server)
|
||||||
{
|
{
|
||||||
static auto res = []
|
static auto res = [server]
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (auto& functor : get_registration_functors())
|
for (auto& functor : get_registration_functors())
|
||||||
{
|
{
|
||||||
activate_component(functor());
|
if (functor.second == component_type::any || server == (functor.second == component_type::server))
|
||||||
|
{
|
||||||
|
activate_component(functor.first());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (premature_shutdown_trigger&)
|
catch (premature_shutdown_trigger&)
|
||||||
|
@ -5,9 +5,9 @@ namespace component_loader
|
|||||||
{
|
{
|
||||||
using registration_functor = std::function<std::unique_ptr<component_interface>()>;
|
using registration_functor = std::function<std::unique_ptr<component_interface>()>;
|
||||||
|
|
||||||
void register_component(registration_functor functor);
|
void register_component(registration_functor functor, component_type type);
|
||||||
|
|
||||||
bool activate();
|
bool activate(bool server);
|
||||||
bool post_load();
|
bool post_load();
|
||||||
void post_unpack();
|
void post_unpack();
|
||||||
void pre_destroy();
|
void pre_destroy();
|
||||||
@ -33,7 +33,7 @@ namespace component_loader
|
|||||||
register_component([]
|
register_component([]
|
||||||
{
|
{
|
||||||
return std::make_unique<T>();
|
return std::make_unique<T>();
|
||||||
});
|
}, T::type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,8 @@ namespace
|
|||||||
const auto game_entry = game.get_iat_entry("steam_api64.dll", func);
|
const auto game_entry = game.get_iat_entry("steam_api64.dll", func);
|
||||||
if (!game_entry)
|
if (!game_entry)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Import '" + func + "' not found!");
|
//throw std::runtime_error("Import '" + func + "' not found!");
|
||||||
|
return {nullptr, nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto original_import = game_entry;
|
const auto original_import = game_entry;
|
||||||
@ -183,12 +184,16 @@ namespace
|
|||||||
{
|
{
|
||||||
remove_crash_file();
|
remove_crash_file();
|
||||||
|
|
||||||
if (!component_loader::activate())
|
const auto client_binary = "BlackOps3.exe"s;
|
||||||
|
const auto server_binary = "BlackOps3_UnrankedDedicatedServer.exe"s;
|
||||||
|
const auto has_server = utils::io::file_exists(server_binary);
|
||||||
|
|
||||||
|
if (!component_loader::activate(has_server))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_point = load_process("BlackOps3.exe");
|
entry_point = load_process(has_server ? server_binary : client_binary);
|
||||||
if (!entry_point)
|
if (!entry_point)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Unable to load binary into memory");
|
throw std::runtime_error("Unable to load binary into memory");
|
||||||
|
@ -3,51 +3,42 @@
|
|||||||
#include "nt.hpp"
|
#include "nt.hpp"
|
||||||
|
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "finally.hpp"
|
||||||
|
|
||||||
namespace utils::flags
|
namespace utils::flags
|
||||||
{
|
{
|
||||||
void parse_flags(std::vector<std::string>& flags)
|
std::unordered_set<std::string> parse_flags()
|
||||||
{
|
{
|
||||||
int num_args;
|
int num_args{};
|
||||||
auto* const argv = CommandLineToArgvW(GetCommandLineW(), &num_args);
|
auto* const argv = CommandLineToArgvW(GetCommandLineW(), &num_args);
|
||||||
|
const auto _ = finally([&argv]
|
||||||
flags.clear();
|
{
|
||||||
|
|
||||||
if (argv)
|
if (argv)
|
||||||
{
|
{
|
||||||
for (auto i = 0; i < num_args; ++i)
|
LocalFree(argv);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
std::unordered_set<std::string> flags{};
|
||||||
|
|
||||||
|
for (auto i = 0; i < num_args && argv; ++i)
|
||||||
{
|
{
|
||||||
std::wstring wide_flag(argv[i]);
|
std::wstring wide_flag(argv[i]);
|
||||||
if (wide_flag[0] == L'-')
|
if (wide_flag[0] == L'-')
|
||||||
{
|
{
|
||||||
wide_flag.erase(wide_flag.begin());
|
wide_flag.erase(wide_flag.begin());
|
||||||
flags.emplace_back(string::convert(wide_flag));
|
flags.emplace(string::to_lower(string::convert(wide_flag)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalFree(argv);
|
return flags;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_flag(const std::string& flag)
|
bool has_flag(const std::string& flag)
|
||||||
{
|
{
|
||||||
static auto parsed = false;
|
static const auto enabled_flags = parse_flags();
|
||||||
static std::vector<std::string> enabled_flags;
|
return enabled_flags.contains(string::to_lower(flag));
|
||||||
|
|
||||||
if (!parsed)
|
|
||||||
{
|
|
||||||
parse_flags(enabled_flags);
|
|
||||||
parsed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& entry : enabled_flags)
|
|
||||||
{
|
|
||||||
if (string::to_lower(entry) == string::to_lower(flag))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user