From e530495ecb6cdae086114ab7890d91fc608200f4 Mon Sep 17 00:00:00 2001 From: 6arelyFuture Date: Mon, 23 Dec 2024 12:14:50 +0100 Subject: [PATCH] Christmas Update --- deps/GSL | 2 +- deps/libtomcrypt | 2 +- deps/minhook | 2 +- deps/rapidjson | 2 +- deps/zlib | 2 +- src/client/component/auth.cpp | 23 +++++++++++- src/client/component/branding.cpp | 12 ++++-- src/client/component/debug.cpp | 16 +++++--- src/client/component/dvar_patches.cpp | 2 + src/client/component/fov.cpp | 42 +++++++++++++++++++++ src/client/component/network.cpp | 4 +- src/client/component/patches.cpp | 37 +++++++++++++++++++ src/client/component/player_movement.cpp | 12 +++--- src/client/game/dvars.cpp | 4 +- src/client/game/dvars.hpp | 4 +- src/client/game/symbols.hpp | 6 +++ src/common/utils/nt.hpp | 47 +++++++++++++++++++++++- 17 files changed, 190 insertions(+), 29 deletions(-) create mode 100644 src/client/component/fov.cpp diff --git a/deps/GSL b/deps/GSL index e64c97f..b8ac820 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit e64c97fc2cfc11992098bb38eda932de275e3f4d +Subproject commit b8ac820fe1efde9c63ca290f4ae8670f938a7dae diff --git a/deps/libtomcrypt b/deps/libtomcrypt index f7e6519..c900951 160000 --- a/deps/libtomcrypt +++ b/deps/libtomcrypt @@ -1 +1 @@ -Subproject commit f7e6519fae1e11ff5ff9d36c84101a673002133b +Subproject commit c900951dab1bb94bab803fc57688dac18e3b71f9 diff --git a/deps/minhook b/deps/minhook index 1cc4610..c1a7c38 160000 --- a/deps/minhook +++ b/deps/minhook @@ -1 +1 @@ -Subproject commit 1cc46107ee522d7a5c73656c519ca16addf2c23a +Subproject commit c1a7c3843bd1a5fe3eb779b64c0d823bca3dc339 diff --git a/deps/rapidjson b/deps/rapidjson index ab1842a..d621dc9 160000 --- a/deps/rapidjson +++ b/deps/rapidjson @@ -1 +1 @@ -Subproject commit ab1842a2dae061284c0a62dca1cc6d5e7e37e346 +Subproject commit d621dc9e9c77f81e5c8a35b8dcc16dcd63351321 diff --git a/deps/zlib b/deps/zlib index 0f51fb4..ef24c4c 160000 --- a/deps/zlib +++ b/deps/zlib @@ -1 +1 @@ -Subproject commit 0f51fb4933fc9ce18199cb2554dacea8033e7fd3 +Subproject commit ef24c4c7502169f016dcd2a26923dbaf3216748c diff --git a/src/client/component/auth.cpp b/src/client/component/auth.cpp index d2d030c..f35196e 100644 --- a/src/client/component/auth.cpp +++ b/src/client/component/auth.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -68,9 +69,29 @@ utils::cryptography::ecc::key& get_key() { return key; } +bool is_second_instance() { + static const auto is_first = []() -> bool { + static utils::nt::handle mutex = + CreateMutexA(nullptr, FALSE, "iw4xsp_mutex"); + return mutex && GetLastError() != ERROR_ALREADY_EXISTS; + }(); + + return !is_first; +} } // namespace -std::uint64_t get_guid() { return get_key().get_hash(); } +std::uint64_t get_guid() { + static const auto guid = []() -> std::uint64_t { + if (is_second_instance()) { + return 0x110000100000000 | + (::utils::cryptography::random::get_integer() & ~0x80000000); + } + + return get_key().get_hash(); + }(); + + return guid; +} class component final : public component_interface { public: diff --git a/src/client/component/branding.cpp b/src/client/component/branding.cpp index d77a783..e4d398a 100644 --- a/src/client/component/branding.cpp +++ b/src/client/component/branding.cpp @@ -77,6 +77,7 @@ void cg_draw_full_screen_debug_overlays_stub(int local_client_num) { utils::hook::invoke(0x44BD00, local_client_num); } +volatile bool left_side = true; game::Font_s** small_font; void branding_loop() { float color[4] = {1.0f, 1.0f, 1.0f, 0.25f}; @@ -88,9 +89,12 @@ void branding_loop() { auto* const scr_place = game::ScrPlace_GetActivePlacement(game::LOCAL_CLIENT_0); - const auto x = scr_place->realViewportSize[0] - - static_cast(game::R_TextWidth(text, 0, *small_font)) - - 10.0f; + const auto x = + left_side + ? 10.0f + : scr_place->realViewportSize[0] - + static_cast(game::R_TextWidth(text, 0, *small_font)) - + 10.0f; game::R_AddCmdDrawText(text, std::numeric_limits::max(), *small_font, x, 30.0f, 1.0f, 1.0f, 0.0f, color, 3); @@ -122,6 +126,8 @@ public: small_font = reinterpret_cast(0x192A0DC); scheduler::loop(branding_loop, scheduler::pipeline::renderer); + scheduler::loop([] { left_side = !left_side; }, + scheduler::pipeline::renderer, 60s); } static void register_branding_dvars() { diff --git a/src/client/component/debug.cpp b/src/client/component/debug.cpp index dcf2ce2..58e4da2 100644 --- a/src/client/component/debug.cpp +++ b/src/client/component/debug.cpp @@ -14,14 +14,15 @@ namespace { void com_assert_f() { assert("a" && false); } void com_bug_f(const command::params& params) { - char new_file_name[0x105]{}; + char new_file_name[MAX_PATH]{}; char to_ospath[MAX_PATH]{}; char from_ospath[MAX_PATH]{}; - const char* bug; + const char* bug{}; if (!*game::logfile) { game::Com_PrintError(game::CON_CHANNEL_ERROR, "CopyFile failed: logfile wasn't opened\n"); + return; } if (params.size() == 2) { @@ -31,10 +32,11 @@ void com_bug_f(const command::params& params) { bug = dvars::bug_name->current.string; } - sprintf_s(new_file_name, "%s_%s.log", bug, game::Live_GetLocalClientName(0)); + sprintf_s(new_file_name, "%s_%s.log", bug, + game::Live_GetLocalClientName(game::LOCAL_CLIENT_0)); - game::engine::scoped_critical_section _(game::CRITSECT_CONSOLE, - game::SCOPED_CRITSECT_NORMAL); + game::engine::scoped_critical_section lock(game::CRITSECT_CONSOLE, + game::SCOPED_CRITSECT_NORMAL); if (*game::logfile) { game::FS_FCloseFile(*game::logfile); @@ -48,6 +50,8 @@ void com_bug_f(const command::params& params) { const auto result = CopyFileA(from_ospath, to_ospath, 0); game::Com_OpenLogFile(); + lock.leave_crit_sect(); + if (!result) { game::Com_PrintError(game::CON_CHANNEL_ERROR, "CopyFile failed(%d) %s %s\n", GetLastError(), "console.log", new_file_name); @@ -55,7 +59,7 @@ void com_bug_f(const command::params& params) { } void com_bug_name_inc_f() { - char buf[260]{}; + char buf[MAX_PATH]{}; if (std::strlen(dvars::bug_name->current.string) < 4) { game::Dvar_SetString(dvars::bug_name, "bug0"); diff --git a/src/client/component/dvar_patches.cpp b/src/client/component/dvar_patches.cpp index 4c2b6d5..e138d67 100644 --- a/src/client/component/dvar_patches.cpp +++ b/src/client/component/dvar_patches.cpp @@ -22,6 +22,8 @@ public: dvar::override::register_bool("intro", false, game::DVAR_ARCHIVE); dvar::override::register_float("cg_fov", 65.0f, 65.0f, 160.0f, game::DVAR_ARCHIVE | game::DVAR_SAVED); + dvar::override::register_float("cg_fovScale", 1.0f, 0.2f, 2.0f, + game::DVAR_ARCHIVE | game::DVAR_SAVED); dvar::override::register_string("fs_basegame", BASEGAME, game::DVAR_INIT); #ifdef _DEBUG diff --git a/src/client/component/fov.cpp b/src/client/component/fov.cpp new file mode 100644 index 0000000..357a53e --- /dev/null +++ b/src/client/component/fov.cpp @@ -0,0 +1,42 @@ +#include +#include "loader/component_loader.hpp" +#include "game/dvars.hpp" + +#include + +#include + +namespace fov { +namespace { +void dvar_set_from_string_by_name_from_source(const char* dvar_name, + const char* string, + game::DvarSetSource source) { + if ((!std::strcmp(dvar_name, "cg_fov")) || + (!std::strcmp(dvar_name, "cg_fovScale"))) { + game::Com_Printf(game::CON_CHANNEL_DONT_FILTER, + xorstr_("Not allowing the client to override dvar '%s'\n"), + dvar_name); + return; + } + + game::Dvar_SetFromStringByNameFromSource(dvar_name, string, source); +} +} // namespace + +class component final : public component_interface { +public: + void post_load() override { + utils::hook(0x5D7818, dvar_set_from_string_by_name_from_source, + HOOK_CALL) + .install() // hook* + ->quick(); // GScr_SetSavedDvar + + utils::hook(0x5CC8D9, dvar_set_from_string_by_name_from_source, + HOOK_CALL) + .install() // hook* + ->quick(); // GScr_SetDvar_Internal + } +}; +} // namespace fov + +REGISTER_COMPONENT(fov::component) diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index 11ae9d1..00e446d 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -46,8 +46,8 @@ private: // Disable MP packet handler utils::hook::set(0x65E717, 0xEB); - // Disable LSP packet handler - utils::hook::set(0x65E3A4, 0xEB); + // Disable LSP packet handler (suppress print message) + utils::hook::nop(0x65E3C4, 5); // Avoid spam utils::hook(0x65E786, game::Com_DPrintf, HOOK_CALL).install()->quick(); diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index 4af9216..eef70d6 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -31,6 +31,30 @@ const char* live_get_local_client_name_stub() { } bool g_exit_after_tool_complete_stub() { return false; } + +void ui_replace_directive_stub(const int local_client_num, + const char* src_string, char* dst_string, + const int dst_buffer_size) { + if (!src_string) { + return; + } + + if (!dst_string) { + return; + } + + if (dst_buffer_size <= 0) { + return; + } + + constexpr std::size_t MAX_HUDELEM_TEXT_LEN = 0x100; + if (std::strlen(src_string) > MAX_HUDELEM_TEXT_LEN) { + return; + } + + game::UI_ReplaceDirective(local_client_num, src_string, dst_string, + dst_buffer_size); +} } // namespace class component final : public component_interface { @@ -58,6 +82,19 @@ public: .install() // hook* ->quick(); + utils::hook(0x563C0C, ui_replace_directive_stub, HOOK_CALL) + .install() // hook* + ->quick(); + utils::hook(0x56454F, ui_replace_directive_stub, HOOK_CALL) + .install() // hook* + ->quick(); + utils::hook(0x568A7E, ui_replace_directive_stub, HOOK_CALL) + .install() // hook* + ->quick(); + utils::hook(0x6283AE, ui_replace_directive_stub, HOOK_CALL) + .install() // hook* + ->quick(); + patch_sp(); } diff --git a/src/client/component/player_movement.cpp b/src/client/component/player_movement.cpp index ceb36da..ac4713c 100644 --- a/src/client/component/player_movement.cpp +++ b/src/client/component/player_movement.cpp @@ -11,7 +11,7 @@ namespace { void __declspec(naked) pm_step_slide_move_stub() { __asm { push eax; - mov eax, dvars::pm_bounce; + mov eax, dvars::pm_bounces; cmp byte ptr [eax + 0x10], 1; pop eax; @@ -48,7 +48,7 @@ void pm_project_velocity_stub(const float* vel_in, const float* normal, std::sqrtf((vel_in[2] * vel_in[2] + length_squared_2d) / (new_z * new_z + length_squared_2d)); - if (dvars::pm_bouncingAllAngles->current.enabled || + if (dvars::pm_bouncesAllAngles->current.enabled || (length_scale < 1.f || new_z < 0.f || vel_in[2] > 0.f)) { vel_out[0] = vel_in[0] * length_scale; vel_out[1] = vel_in[1] * length_scale; @@ -222,10 +222,10 @@ public: static void register_dvars() { // clang-format off - dvars::pm_bounce = game::Dvar_RegisterBool( - "pm_bounce", false, game::DVAR_NONE, "CoD4 Bounces"); - dvars::pm_bouncingAllAngles = game::Dvar_RegisterBool( - "pm_bouncingAllAngles", false, game::DVAR_NONE, "Enable bouncing from all angles"); + dvars::pm_bounces = game::Dvar_RegisterBool( + "pm_bounces", false, game::DVAR_NONE, "CoD4 Bounces"); + dvars::pm_bouncesAllAngles = game::Dvar_RegisterBool( + "pm_bouncesAllAngles", false, game::DVAR_NONE, "Enable bouncing from all angles"); dvars::pm_rocketJump = game::Dvar_RegisterBool( "pm_rocketJump", true, game::DVAR_NONE, "CoD4 rocket jumps"); dvars::pm_rocketJumpScale = game::Dvar_RegisterFloat( diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index 311dd5a..26f1acb 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -3,8 +3,8 @@ namespace dvars { const game::dvar_t* r_noBorder = nullptr; -const game::dvar_t* pm_bounce = nullptr; -const game::dvar_t* pm_bouncingAllAngles = nullptr; +const game::dvar_t* pm_bounces = nullptr; +const game::dvar_t* pm_bouncesAllAngles = nullptr; const game::dvar_t* pm_rocketJump = nullptr; const game::dvar_t* pm_rocketJumpScale = nullptr; const game::dvar_t* pm_playerCollision = nullptr; diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index 6d8703e..f5291c2 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -3,8 +3,8 @@ namespace dvars { extern const game::dvar_t* r_noBorder; -extern const game::dvar_t* pm_bounce; -extern const game::dvar_t* pm_bouncingAllAngles; +extern const game::dvar_t* pm_bounces; +extern const game::dvar_t* pm_bouncesAllAngles; extern const game::dvar_t* pm_rocketJump; extern const game::dvar_t* pm_rocketJumpScale; extern const game::dvar_t* pm_playerCollision; diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index db58def..ed56cc3 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -95,6 +95,9 @@ WEAK symbol Dvar_SetFloatByName{ 0x497250}; WEAK symbol Dvar_SetStringByName{ 0x440C60}; +WEAK symbol + Dvar_SetFromStringByNameFromSource{0x4774E0}; WEAK symbol Dvar_SetInt{0x4FA540}; WEAK symbol Dvar_SetBool{0x4E57E0}; WEAK symbol Dvar_SetString{ @@ -229,6 +232,9 @@ WEAK symbol UI_DrawText{0x40FC70}; +WEAK symbol + UI_ReplaceDirective{0x4BBD10}; // PC WEAK symbol PC_Directive_define{0x4F8CF0}; diff --git a/src/common/utils/nt.hpp b/src/common/utils/nt.hpp index 299e273..a499465 100644 --- a/src/common/utils/nt.hpp +++ b/src/common/utils/nt.hpp @@ -91,8 +91,8 @@ public: PIMAGE_DOS_HEADER get_dos_header() const; PIMAGE_OPTIONAL_HEADER get_optional_header() const; - void** get_iat_entry(const std::string& module_name, - const std::string& proc_name) const; + [[nodiscard]] void** get_iat_entry(const std::string& module_name, + const std::string& proc_name) const; static void set_dll_directory(const std::string& directory); static std::string get_dll_directory(); @@ -101,6 +101,49 @@ private: HMODULE module_; }; +template class handle { +public: + handle() = default; + + handle(const HANDLE h) : handle_(h) {} + + ~handle() { + if (*this) { + CloseHandle(this->handle_); + this->handle_ = InvalidHandle; + } + } + + handle(const handle&) = delete; + handle& operator=(const handle&) = delete; + + handle(handle&& obj) noexcept : handle() { this->operator=(std::move(obj)); } + + handle& operator=(handle&& obj) noexcept { + if (this != &obj) { + this->~handle(); + this->handle_ = obj.handle_; + obj.handle_ = InvalidHandle; + } + + return *this; + } + + handle& operator=(HANDLE h) noexcept { + this->~handle(); + this->handle_ = h; + + return *this; + } + + operator bool() const { return this->handle_ != InvalidHandle; } + + operator HANDLE() const { return this->handle_; } + +private: + HANDLE handle_{InvalidHandle}; +}; + bool is_wine(); __declspec(noreturn) void raise_hard_exception();